C语言 线性表 链式表结构 实现
一个单链式实现的线性表 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语言 线性表 链式表结构 实现的更多相关文章
- javascript实现数据结构:线性表--线性链表(链式存储结构)
上一节中, 线性表的顺序存储结构的特点是逻辑关系上相邻的两个元素在物理位置上也相邻,因此可以随机存取表中任一元素,它的存储位置可用一个简单,直观的公式来表示.然后,另一方面来看,这个特点也造成这种存储 ...
- [置顶] ※数据结构※→☆线性表结构(queue)☆============优先队列 链式存储结构(queue priority list)(十二)
优先队列(priority queue) 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除.在优先队列中,元素被赋予优先级.当访问元素时,具有最高优先级的元素最先删除.优先队列具有 ...
- C++编程练习(2)----“实现简单的线性表的链式存储结构“
单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素. 对于查找操作,单链表的时间复杂度为O(n). 对于插入和删除操作,单链表在确定位置后,插入和删除时间仅为O(1). 单链表不需要分配存储 ...
- c数据结构 -- 线性表之 复杂的链式存储结构
复杂的链式存储结构 循环链表 定义:是一种头尾相接的链表(即表中最后一个结点的指针域指向头结点,整个链表形成一个环) 优点:从表中任一节点出发均可找到表中其他结点 注意:涉及遍历操作时,终止条件是判断 ...
- c数据结构 -- 线性表之 顺序存储结构 于 链式存储结构 (单链表)
线性表 定义:线性表是具有相同特性的数据元素的一个有限序列 类型: 1:顺序存储结构 定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构 算法: #include <stdio. ...
- C++线性表的链式存储结构
C++实现线性表的链式存储结构: 为了解决顺序存储不足:用线性表另外一种结构-链式存储.在顺序存储结构(数组描述)中,元素的地址是由数学公式决定的,而在链式储存结构中,元素的地址是随机分布的,每个元素 ...
- 线性表->链式存储->循环链表
文字描述 循环链表是另一种形式的链式存储结构.它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环.由此,从表中任一结点出发均可找到表中其他结点. 示意图 算法分析 插入.删除.查找等同单 ...
- C语言实现链表(链式存储结构)
链表(链式存储结构)及创建 链表,别名链式存储结构或单链表,用于存储逻辑关系为 "一对一" 的数据.与顺序表不同,链表不限制数据的物理存储状态,换句话说,使用链表存储的数据元素,其 ...
- PTA 带头结点的链式表操作集
6-2 带头结点的链式表操作集 (20 分) 本题要求实现带头结点的链式表操作集. 函数接口定义: List MakeEmpty(); Position Find( List L, Element ...
随机推荐
- 使用NuGet Package Project快速制作NuGet包
今天在visual studio gallery发现了一个插件NuGet Package Project,通过它可以在Visual Studio中建立Nuget Package工程,直接生成Nuget ...
- avalon2学习教程11数据联动
在许多表单应用,我们经常遇到点击一个复选框(或下拉框)会引发旁边的复选框(或下拉框)发生改变,这种联动效果用avalon来做是非常简单的.因为avalon拥有经典MVVM框架的一大利器,双向绑定!绝大 ...
- 样式link属性media用法--媒体类型查询
引用外部样式使用link 你可能想针对将要显示页面的设备类型(桌面PC.笔记本电脑.平板电脑.手机或者甚至页面的印刷版本)来调整页面的样式,可以利用一个media属性, 在<link>元素 ...
- js中==与===的区别
- jquery 找不到live方法解决
http://stackoverflow.com/questions/15573645/typeerror-live-is-not-a-function
- 深刻理解和运用XMLHttpRequest
本文为转载文章,因见猎心喜,担心失传,故贴此以备不时之需. 原文地址:传送 你真的会使用XMLHttpRequest吗? xmlhttprequest http cors ajax ruoyiqing ...
- umf(转)
深入浅出Eclipse Modeling Framework (EMF) Eclipse Modeling Framework (EMF),简单的说,就是Eclipse提供的一套建模框架,可以用EMF ...
- background-size的两个属性:cover和contain
两种都不会造成图片失真,其中: (1)cover:相当于宽度等于元素的宽度,高度设为auto: (2)contain:相当于高度等于元素的高度,宽度设为auto: 例如:设置一个高度和宽度都为300p ...
- nodejs--偏函数
偏函数的例子,解释--假设有一个参数或变量已经预置的函数A,我们通过调用A来产生一个新的函数B,函数B就是我们说的偏函数 偏函数解决这样的问题:如果我们有函数是多个参数的,我们希望能固定其中某几个参数 ...
- Server Apache Tomcat v7.0 at localhost failed to start.
自己在学习servlet中,突然启动不了Tomcat7服务器,提示出现如下错误: 百度之后,没有找到解决办法,偶然发现是我的Web-content下--WEB-INF下--web.xml的配置文件内 ...