一个单链式实现的线性表 mList (GCC编译)。

 /**
* @brief 线性表的链式实现 (单链表)
* @author wid
* @date 2013-10-21
*
* @note 若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢!
*/ #include <stdio.h>
#include <stdlib.h> #define TRUE 1
#define FALSE 0 typedef struct
{
int x;
int y;
}Point2D; //Point2D 结构
typedef Point2D ElemType; //声明 Point2D 结构的别名 ElemType typedef struct LNode
{
Point2D pt;
struct LNode *next;
}ListNode; //线性表数据项结构 typedef struct
{
ListNode *head; //数据项头节点
int length; //线性表长度
}mList; //线性表 mList 结构 //线性表方法声明
mList *CreateList(); ///创建一个空的线性表
void DestroyList( mList *pList ); ///销毁一条线性表
void ClearList( mList *pList ); ///置空一条线性表
int GetLength( mList *pList ); ///获取线性表当前长度
int IsEmpty( mList *pList ); ///检测线性表是否为空
int AppendElem( mList *pList, ElemType *pt ); ///向线性表末尾添加一个元素
int InsertElem( mList *pList, int nPos, ElemType *pt ); ///向线性表中插入一个元素
int DeleteElem( mList *pList, int nPos ); ///从线性表中删除一个元素
int GetElem( mList *pList, int nPos, ElemType *pt ); ///获取线性表中某位置上的元素
int FindElem( mList *pList, int nPos, ElemType *pt ); ///从某位置起查找某元素在线性表中第一次出现的位置
int GetPriorElem( mList *pList, ElemType *pt, ElemType *prior_pt ); ///从线性表中获取 pt 的前驱节点到 prior_pt
int GetNextElem( mList *pList, ElemType *pt, ElemType *next_pt ); ///从线性表中获取 pt 的后继节点到 next_pt
void ForEachList( mList *pList, void (*func)(ElemType *pt) ); ///对线性表中每个元素执行 func 函数
int ListCpy( mList *pDestList, mList *pSrcList ); ///将一线性表复制到另一线性表后
int ListCat( mList *pDestList, mList *pSrcList ); ///将一线性表连接到另一线性表后 //线性表方法实现 /**
* @brief 创建一个空的线性表
*
* @return 指向创建的线性表的指针
*/
mList *CreateList()
{
mList *pList = (mList *)malloc(sizeof(mList));
pList->head = (ListNode *)malloc(sizeof(ListNode));
pList->head->next = NULL;
pList->length = ; return pList;
} /**
* @brief 销毁一条线性表
*
* @param 指向待销毁的线性表的指针
*
* @return void
*/
void DestroyList( mList *pList )
{
ListNode *pm = pList->head, *pn = NULL;
while( pm != NULL )
{
pn = pm->next;
free(pm);
pm = pn;
}
free(pList);
pList = NULL;
} /**
* @brief 置空一条线性表
*
* @param 指向待置空的线性表指针
*
* @return void
*/
void ClearList( mList *pList )
{
ListNode *pm = pList->head, *pn = NULL;
while( pm != NULL )
{
pn = pm->next;
free(pm);
pm = pn;
}
pList->head->next = NULL;
pList->length = ;
} /**
* @brief 获取线性表当前长度
*
* @param 指针待获取长度的线性表的指针
*
* @return 返回获取到的线性表长度
*/
int GetLength( mList *pList )
{
return pList->length;
} /**
* @brief 检测线性表是否为空
*
* @param pList 指向待检测的线性表的指针
*
* @return 若为空则返回 TRUE, 否则返回 FALSE
*/
int IsEmpty( mList *pList )
{
return pList->length == ? TRUE : FALSE;
} /**
* @brief 向线性表末尾添加一个元素
*
* @param pList 目标线性表
* @param pe 指向待添加元素的指针
*
* @return 返回添加成功后当前线性表长度
*/
int AppendElem( mList *pList, ElemType *pt )
{
ListNode *pm = pList->head, *pn = NULL; while( pm->next != NULL ) { pm = pm->next; };
pn = (ListNode *)malloc(sizeof(ListNode));
pn->pt.x = pt->x;
pn->pt.y = pt->y;
pn->next = NULL;
pm->next = pn; return ++pList->length;
} /**
* @brief 向线性表中插入一个元素
*
* @param pList 指向待插入元素的线性表
* @param nPos 插入的位置
* @param pt 指向待插入的元素的指针
*
* @return 若插入成功则返回插入后线性表当前长度, 否则返回 -1
*
* @note 插入位置 nPos 从 0 计起
*/
int InsertElem( mList *pList, int nPos, ElemType *pt )
{
ListNode *pm = pList->head, *pn = NULL; if( nPos < || nPos > pList->length - ) ///插入位置是否在线性表内
return -; int n = ;
for( n = ; n < nPos; ++n, (pm = pm->next) );
pn = (ListNode *)malloc(sizeof(ListNode));
pn->pt.x = pt->x;
pn->pt.y = pt->y; pn->next = pm->next;
pm->next = pn; return ++pList->length;
} /**
* @brief 从线性表中删除一个元素
*
* @param pList 指向待删除元素的线性表指针
* @param nPos 待删除元素的位置
*
* @return 若删除成功则返回删除后线性表当前长度, 否则返回 -1
*
* @note 删除位置 nPos 从 0 计起
*/
int DeleteElem( mList *pList, int nPos )
{
ListNode *pm = pList->head, *pn = NULL; if( nPos < || nPos > pList->length - ) ///删除位置是否在线性表内
return -; int i = ;
for( i = ; i < nPos; ++i, (pm = pm->next) );
pn = pm->next;
pm->next = pn->next;
free(pn); return --pList->length;
} /**
* @brief 获取线性表中某位置上的元素
*
* @param pList 指向待获取元素的线性表指针
* @param nPos 元素在线性表中的位置
* @param pt 指向存放获取到的元素的指针
*
* @return 若获取成功, 返回 TRUE, 否则返回 FALSE
*
* @note 元素位置从 0 计起
*/
int GetElem( mList *pList, int nPos, ElemType *pt )
{
int n = nPos;
if( n < || n > pList->length - )
return FALSE; ListNode *pm = pList->head;
for( n = ; n <= nPos; ++n, (pm = pm->next) );
pt->x = pm->pt.x;
pt->y = pm->pt.y; return TRUE;
} /**
* @brief 从某位置起查找某元素在线性表中第一次出现的位置
*
* @param pList 指向待查找元素的线性表的指针
* @param nPos 查找起始位置
* @param pt 指向待查找的元素的指针
*
* @return 若找到, 则返回元素所在的位置, 否则返回 -1
*
* @note 起始位置由 0 计起
*/
int FindElem( mList *pList, int nPos, ElemType *pt )
{
int n = nPos;
if( n < || n > pList->length - )
return -; ListNode *pm = pList->head;
for( n = ; n <= nPos; ++n, (pm = pm->next) );
for( ; pm != NULL; ++n )
{
if( (pm->pt.x == pt->x) && (pm->pt.y == pt->y) )
return n-; pm = pm->next;
} return -;
} /**
* @brief 获取某 pt 元素的前驱节点到 prior_pt
*
* @param 指向待获取前驱节点的线性表指针
* @param pt 指向目标节点的指针
* @param prior_pt 存放目标节点 pt 的前驱节点
*
* @return 若成功获取前驱节点, 返回该前驱节点在线性表中的位置, 否则返回 -1
*
* @note 元素位置从 0 计起
*/
int GetPriorElem( mList *pList, ElemType *pt, ElemType *prior_pt )
{
ListNode *pm = pList->head;
int ncnt = ;
while( pm->next != NULL )
{
if( pm->next->pt.x == pt->x && pm->next->pt.y == pt->y )
{
if( ncnt != ) ///不为首节点
{
prior_pt->x = pm->pt.x;
prior_pt->y = pm->pt.y;
return ncnt - ;
}
else return -; ///不存在前驱节点
}
pm = pm->next;
++ncnt;
} return -;
} /**
* @brief 获取某 pt 元素的后继节点到 next_pt
*
* @param 指向待获取前后继点的线性表指针
* @param pt 指向目标节点的指针
* @param prior_pt 存放目标节点 pt 的后继节点
*
* @return 若成功获取后继节点, 返回该后继节点在线性表中的位置, 否则返回 -1
*
* @note 元素位置从 0 计起
*/
int GetNextElem( mList *pList, ElemType *pt, ElemType *next_pt )
{
ListNode *pm = pList->head;
int ncnt = ;
while( (pm = pm->next) != NULL )
{
       if( ncnt == pList->length )  //bug修复, 不存在后继节点
          return -1;
if( pm->pt.x == pt->x && pm->pt.y == pt->y )
{
if( pm->next != NULL )
{
next_pt->x = pm->next->pt.x;
next_pt->y = pm->next->pt.y; return ncnt + ;
}
}
++ncnt;
} return -;
} /**
* @brief 对线性表中每个元素执行 func 函数
*
* @param pList 指向待处理的线性表的指针
* @param func 传入的函数指针
*
* @return void
*/
void ForEachList( mList *pList, void (*func)(ElemType *pt) )
{
ListNode *pm = pList->head;
while( (pm = pm->next) != NULL )
func( &pm->pt );
} /**
* @brief 将 pSrcList 性表复制到 pDestList 线性表后
*
* @param pDestList 指向目标线性表指针
* @param pSrcList 指向源线性表指针
*
* @return 返回复制后目标线性表长度
*/
int ListCpy( mList *pDestList, mList *pSrcList )
{
ListNode *pm = pDestList->head;
ListNode *pn = pSrcList->head;
ListNode *ptmp = NULL; while( pm->next != NULL ) pm = pm->next;
while( (pn = pn->next) != NULL )
{
ptmp = (ListNode *)malloc(sizeof(ListNode));
ptmp->pt.x = pn->pt.x;
ptmp->pt.y = pn->pt.y;
pm->next = ptmp;
pm = pm->next;
}
pm->next = NULL;
pDestList->length += pSrcList->length; return pDestList->length;
} /**
* @brief 将 pSrcList 性表连接到 pDestList 线性表后
*
* @param pDestList 指向目标线性表指针
* @param pSrcList 指向源线性表指针
*
* @return 返回连接后目标线性表长度
*
* @note 连接后 pSrcList 线性表将被销毁
*/
int ListCat( mList *pDestList, mList *pSrcList )
{
ListNode *pm = pDestList->head;
while( pm->next != NULL ) pm = pm->next;
pm->next = pSrcList->head->next;
pDestList->length += pSrcList->length;
free( pSrcList ); return pDestList->length;
} //测试 mList void display( ElemType *pt )
{
printf("(%d,%d) ", pt->x, pt->y);
} int main()
{
mList *plstA = CreateList(), *plstB = CreateList(); //创建 plst 与 plst2 两根空线性表
ElemType pt, pt2; //两个 ElemType 型元素 int i = ;
for( i = ; i < ; ++i )
{
pt.x = i;
pt.y = i;
AppendElem( plstA, &pt ); //向 plst 循环添加 (0,0) 至 (10,10)
} for( i = ; i < ; ++i )
{
pt.x = i;
pt.y = i;
AppendElem( plstB, &pt ); //向 plst 循环添加 (55,55) 至 (60,60)
} ///测试 ForEachList
printf("plstA 初始数据: ");
ForEachList( plstA, display ); //对线性表中每个元素执行 display 函数 printf("\nplstB 初始数据: ");
ForEachList( plstB, display ); ///测试 InsertElem
printf("\n\n向 plstA 位置3处插入元素(100,99)后:\n");
pt.x = ; pt.y = ;
InsertElem( plstA, , &pt ); //向 plstA 位置 3 处插入 pt
ForEachList( plstA, display ); ///测试 DeleteElem
printf("\n\n删除 plstB 位置0处的元素后:\n");
DeleteElem( plstB, ); //删除 plstA 位置 0 处的元素
ForEachList( plstB, display ); ///测试 IsEmpty、GetLength
printf("\n\n线性表 plstA 是否为空: %d\n", IsEmpty(plstA) );
printf("线性表 plstB 的长度: %d\n", GetLength(plstB) ); ///测试 GetElem
GetElem( plstA, , &pt );
printf("获取 plstA 位置 5 的元素: (%d, %d)\n", pt.x, pt.y ); ///测试 FindElem
pt.x = ; pt.y = ;
printf("获取元素(6,6)在线性表plstA中的位置: %d\n", FindElem(plstA, , &pt)); ///测试 GetPriorElem
GetPriorElem( plstA, &pt, &pt2 );
printf("获取pt=(6,6)在plstA中的前驱节点: (%d,%d)\n", pt2.x, pt2.y); ///测试 GetNextElem
GetNextElem( plstA, &pt, &pt2 );
printf("获取pt=(6,6)在plstA中的后继节点: (%d,%d)\n", pt2.x, pt2.y); ///测试 ListCpy
printf("\n将 plstB 复制到 plstA 后:\n");
ListCpy( plstA, plstB );
ForEachList( plstA, display );
printf("\nplstA长度=%d\n", GetLength(plstA)); ///测试 ListCat
printf("\n将 plstB 连接到 plstA 后:\n");
ListCat( plstA, plstB );
ForEachList( plstA, display );
printf("\nplstA长度=%d\n", GetLength(plstA)); ///测试 ClearList
printf("\n置空 plstA 线性表:\n");
ClearList(plstA);
printf("plstA 长度=%d\n", GetLength(plstA)); ///测试 DestroyList
printf("销毁 plstA..");
DestroyList(plstA); return ;
}

若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢。                                                                                                                                                                                                                                                                                  

C语言 线性表 链式表结构 实现的更多相关文章

  1. javascript实现数据结构:线性表--线性链表(链式存储结构)

    上一节中, 线性表的顺序存储结构的特点是逻辑关系上相邻的两个元素在物理位置上也相邻,因此可以随机存取表中任一元素,它的存储位置可用一个简单,直观的公式来表示.然后,另一方面来看,这个特点也造成这种存储 ...

  2. [置顶] ※数据结构※→☆线性表结构(queue)☆============优先队列 链式存储结构(queue priority list)(十二)

    优先队列(priority queue) 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除.在优先队列中,元素被赋予优先级.当访问元素时,具有最高优先级的元素最先删除.优先队列具有 ...

  3. C++编程练习(2)----“实现简单的线性表的链式存储结构“

    单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素. 对于查找操作,单链表的时间复杂度为O(n). 对于插入和删除操作,单链表在确定位置后,插入和删除时间仅为O(1). 单链表不需要分配存储 ...

  4. c数据结构 -- 线性表之 复杂的链式存储结构

    复杂的链式存储结构 循环链表 定义:是一种头尾相接的链表(即表中最后一个结点的指针域指向头结点,整个链表形成一个环) 优点:从表中任一节点出发均可找到表中其他结点 注意:涉及遍历操作时,终止条件是判断 ...

  5. c数据结构 -- 线性表之 顺序存储结构 于 链式存储结构 (单链表)

    线性表 定义:线性表是具有相同特性的数据元素的一个有限序列 类型: 1:顺序存储结构 定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构 算法: #include <stdio. ...

  6. C++线性表的链式存储结构

    C++实现线性表的链式存储结构: 为了解决顺序存储不足:用线性表另外一种结构-链式存储.在顺序存储结构(数组描述)中,元素的地址是由数学公式决定的,而在链式储存结构中,元素的地址是随机分布的,每个元素 ...

  7. 线性表->链式存储->循环链表

    文字描述 循环链表是另一种形式的链式存储结构.它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环.由此,从表中任一结点出发均可找到表中其他结点. 示意图 算法分析 插入.删除.查找等同单 ...

  8. C语言实现链表(链式存储结构)

    链表(链式存储结构)及创建 链表,别名链式存储结构或单链表,用于存储逻辑关系为 "一对一" 的数据.与顺序表不同,链表不限制数据的物理存储状态,换句话说,使用链表存储的数据元素,其 ...

  9. PTA 带头结点的链式表操作集

    6-2 带头结点的链式表操作集 (20 分)   本题要求实现带头结点的链式表操作集. 函数接口定义: List MakeEmpty(); Position Find( List L, Element ...

随机推荐

  1. 开源GIS简介.学习

    开发者都希望自己的软件能够运行在尽可能多的计算机上.然而事与愿违,摆在 GIS开发者面前的仍然是对峙的平台.J2EE随着Java5.0的发布,已经正式更名为JavaEE,而微软也正式发布了.NET2. ...

  2. 【转】常用css命名规则

    常用的css命名规则 头:header 内容:content/container 尾:footer 导航:nav 侧栏:sidebar 栏目:column 页面外围控制整体布局宽度:wrapper 左 ...

  3. textview 多行 省略号

    TextView自带的可以通过 android:ellipsize="end" android:singleLine="true"实现单行省略,  多行显示: ...

  4. 前端---HTML

    HTML基础 本章内容: 简介 HTML定义 标签定义和属性 HTML5基本结构 HTML5字符集 <head>标签 <title> <base/> <lin ...

  5. POJ 1637 Sightseeing tour (混合图欧拉回路)

    Sightseeing tour   Description The city executive board in Lund wants to construct a sightseeing tou ...

  6. 使用Coookie实现浏览器显示上次的登录时间

    实现的效果:  每一次刷新 都会显示上一次访问servlet的时间 ,只适用于同一个浏览器 ,更换浏览器再次访问就该使用session技术了, 因为cookie是浏览器端技术,cookie保存在浏览器 ...

  7. js中实现字母大小写转换

    js中实现字母大小写转换主要用到了四个js函数: 1.toLocaleUpperCase  2.toUpperCase3.toLocaleLowerCase4.toLowerCase 下面就这四个实现 ...

  8. Swift 遍历数组元素

    ..<Array.count { Array[index] } for (index, element) in Array.enumerate() { print(("\(index+ ...

  9. pdflatex, xelatex, texstudio中文编码问题

    使用xelatex,源文件需要用utf-8编译,pdf文件不会乱码. 使用pdflatex,源文件不能使用utf-8编码,否则pdf文件会乱码. 使用GB2312没问题.

  10. firame标签: IHTMLElement -> IHTMLFrameBase2 -> IHTMLWindow2 -> IHTMLDocument2 跨域访问

    获得iframe标签的元素指针 CComPtr<IHTMLElement> spAdIframe = ... CComQIPtr<IHTMLFrameBase2> spFram ...