一个单链式实现的线性表 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 或程序缺陷, 请留言反馈, 谢谢。