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

  1. /**
  2. * @brief 线性表的链式实现 (单链表)
  3. * @author wid
  4. * @date 2013-10-21
  5. *
  6. * @note 若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢!
  7. */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11.  
  12. #define TRUE 1
  13. #define FALSE 0
  14.  
  15. typedef struct
  16. {
  17. int x;
  18. int y;
  19. }Point2D; //Point2D 结构
  20. typedef Point2D ElemType; //声明 Point2D 结构的别名 ElemType
  21.  
  22. typedef struct LNode
  23. {
  24. Point2D pt;
  25. struct LNode *next;
  26. }ListNode; //线性表数据项结构
  27.  
  28. typedef struct
  29. {
  30. ListNode *head; //数据项头节点
  31. int length; //线性表长度
  32. }mList; //线性表 mList 结构
  33.  
  34. //线性表方法声明
  35. mList *CreateList(); ///创建一个空的线性表
  36. void DestroyList( mList *pList ); ///销毁一条线性表
  37. void ClearList( mList *pList ); ///置空一条线性表
  38. int GetLength( mList *pList ); ///获取线性表当前长度
  39. int IsEmpty( mList *pList ); ///检测线性表是否为空
  40. int AppendElem( mList *pList, ElemType *pt ); ///向线性表末尾添加一个元素
  41. int InsertElem( mList *pList, int nPos, ElemType *pt ); ///向线性表中插入一个元素
  42. int DeleteElem( mList *pList, int nPos ); ///从线性表中删除一个元素
  43. int GetElem( mList *pList, int nPos, ElemType *pt ); ///获取线性表中某位置上的元素
  44. int FindElem( mList *pList, int nPos, ElemType *pt ); ///从某位置起查找某元素在线性表中第一次出现的位置
  45. int GetPriorElem( mList *pList, ElemType *pt, ElemType *prior_pt ); ///从线性表中获取 pt 的前驱节点到 prior_pt
  46. int GetNextElem( mList *pList, ElemType *pt, ElemType *next_pt ); ///从线性表中获取 pt 的后继节点到 next_pt
  47. void ForEachList( mList *pList, void (*func)(ElemType *pt) ); ///对线性表中每个元素执行 func 函数
  48. int ListCpy( mList *pDestList, mList *pSrcList ); ///将一线性表复制到另一线性表后
  49. int ListCat( mList *pDestList, mList *pSrcList ); ///将一线性表连接到另一线性表后
  50.  
  51. //线性表方法实现
  52.  
  53. /**
  54. * @brief 创建一个空的线性表
  55. *
  56. * @return 指向创建的线性表的指针
  57. */
  58. mList *CreateList()
  59. {
  60. mList *pList = (mList *)malloc(sizeof(mList));
  61. pList->head = (ListNode *)malloc(sizeof(ListNode));
  62. pList->head->next = NULL;
  63. pList->length = ;
  64.  
  65. return pList;
  66. }
  67.  
  68. /**
  69. * @brief 销毁一条线性表
  70. *
  71. * @param 指向待销毁的线性表的指针
  72. *
  73. * @return void
  74. */
  75. void DestroyList( mList *pList )
  76. {
  77. ListNode *pm = pList->head, *pn = NULL;
  78. while( pm != NULL )
  79. {
  80. pn = pm->next;
  81. free(pm);
  82. pm = pn;
  83. }
  84. free(pList);
  85. pList = NULL;
  86. }
  87.  
  88. /**
  89. * @brief 置空一条线性表
  90. *
  91. * @param 指向待置空的线性表指针
  92. *
  93. * @return void
  94. */
  95. void ClearList( mList *pList )
  96. {
  97. ListNode *pm = pList->head, *pn = NULL;
  98. while( pm != NULL )
  99. {
  100. pn = pm->next;
  101. free(pm);
  102. pm = pn;
  103. }
  104. pList->head->next = NULL;
  105. pList->length = ;
  106. }
  107.  
  108. /**
  109. * @brief 获取线性表当前长度
  110. *
  111. * @param 指针待获取长度的线性表的指针
  112. *
  113. * @return 返回获取到的线性表长度
  114. */
  115. int GetLength( mList *pList )
  116. {
  117. return pList->length;
  118. }
  119.  
  120. /**
  121. * @brief 检测线性表是否为空
  122. *
  123. * @param pList 指向待检测的线性表的指针
  124. *
  125. * @return 若为空则返回 TRUE, 否则返回 FALSE
  126. */
  127. int IsEmpty( mList *pList )
  128. {
  129. return pList->length == ? TRUE : FALSE;
  130. }
  131.  
  132. /**
  133. * @brief 向线性表末尾添加一个元素
  134. *
  135. * @param pList 目标线性表
  136. * @param pe 指向待添加元素的指针
  137. *
  138. * @return 返回添加成功后当前线性表长度
  139. */
  140. int AppendElem( mList *pList, ElemType *pt )
  141. {
  142. ListNode *pm = pList->head, *pn = NULL;
  143.  
  144. while( pm->next != NULL ) { pm = pm->next; };
  145. pn = (ListNode *)malloc(sizeof(ListNode));
  146. pn->pt.x = pt->x;
  147. pn->pt.y = pt->y;
  148. pn->next = NULL;
  149. pm->next = pn;
  150.  
  151. return ++pList->length;
  152. }
  153.  
  154. /**
  155. * @brief 向线性表中插入一个元素
  156. *
  157. * @param pList 指向待插入元素的线性表
  158. * @param nPos 插入的位置
  159. * @param pt 指向待插入的元素的指针
  160. *
  161. * @return 若插入成功则返回插入后线性表当前长度, 否则返回 -1
  162. *
  163. * @note 插入位置 nPos 从 0 计起
  164. */
  165. int InsertElem( mList *pList, int nPos, ElemType *pt )
  166. {
  167. ListNode *pm = pList->head, *pn = NULL;
  168.  
  169. if( nPos < || nPos > pList->length - ) ///插入位置是否在线性表内
  170. return -;
  171.  
  172. int n = ;
  173. for( n = ; n < nPos; ++n, (pm = pm->next) );
  174. pn = (ListNode *)malloc(sizeof(ListNode));
  175. pn->pt.x = pt->x;
  176. pn->pt.y = pt->y;
  177.  
  178. pn->next = pm->next;
  179. pm->next = pn;
  180.  
  181. return ++pList->length;
  182. }
  183.  
  184. /**
  185. * @brief 从线性表中删除一个元素
  186. *
  187. * @param pList 指向待删除元素的线性表指针
  188. * @param nPos 待删除元素的位置
  189. *
  190. * @return 若删除成功则返回删除后线性表当前长度, 否则返回 -1
  191. *
  192. * @note 删除位置 nPos 从 0 计起
  193. */
  194. int DeleteElem( mList *pList, int nPos )
  195. {
  196. ListNode *pm = pList->head, *pn = NULL;
  197.  
  198. if( nPos < || nPos > pList->length - ) ///删除位置是否在线性表内
  199. return -;
  200.  
  201. int i = ;
  202. for( i = ; i < nPos; ++i, (pm = pm->next) );
  203. pn = pm->next;
  204. pm->next = pn->next;
  205. free(pn);
  206.  
  207. return --pList->length;
  208. }
  209.  
  210. /**
  211. * @brief 获取线性表中某位置上的元素
  212. *
  213. * @param pList 指向待获取元素的线性表指针
  214. * @param nPos 元素在线性表中的位置
  215. * @param pt 指向存放获取到的元素的指针
  216. *
  217. * @return 若获取成功, 返回 TRUE, 否则返回 FALSE
  218. *
  219. * @note 元素位置从 0 计起
  220. */
  221. int GetElem( mList *pList, int nPos, ElemType *pt )
  222. {
  223. int n = nPos;
  224. if( n < || n > pList->length - )
  225. return FALSE;
  226.  
  227. ListNode *pm = pList->head;
  228. for( n = ; n <= nPos; ++n, (pm = pm->next) );
  229. pt->x = pm->pt.x;
  230. pt->y = pm->pt.y;
  231.  
  232. return TRUE;
  233. }
  234.  
  235. /**
  236. * @brief 从某位置起查找某元素在线性表中第一次出现的位置
  237. *
  238. * @param pList 指向待查找元素的线性表的指针
  239. * @param nPos 查找起始位置
  240. * @param pt 指向待查找的元素的指针
  241. *
  242. * @return 若找到, 则返回元素所在的位置, 否则返回 -1
  243. *
  244. * @note 起始位置由 0 计起
  245. */
  246. int FindElem( mList *pList, int nPos, ElemType *pt )
  247. {
  248. int n = nPos;
  249. if( n < || n > pList->length - )
  250. return -;
  251.  
  252. ListNode *pm = pList->head;
  253. for( n = ; n <= nPos; ++n, (pm = pm->next) );
  254. for( ; pm != NULL; ++n )
  255. {
  256. if( (pm->pt.x == pt->x) && (pm->pt.y == pt->y) )
  257. return n-;
  258.  
  259. pm = pm->next;
  260. }
  261.  
  262. return -;
  263. }
  264.  
  265. /**
  266. * @brief 获取某 pt 元素的前驱节点到 prior_pt
  267. *
  268. * @param 指向待获取前驱节点的线性表指针
  269. * @param pt 指向目标节点的指针
  270. * @param prior_pt 存放目标节点 pt 的前驱节点
  271. *
  272. * @return 若成功获取前驱节点, 返回该前驱节点在线性表中的位置, 否则返回 -1
  273. *
  274. * @note 元素位置从 0 计起
  275. */
  276. int GetPriorElem( mList *pList, ElemType *pt, ElemType *prior_pt )
  277. {
  278. ListNode *pm = pList->head;
  279. int ncnt = ;
  280. while( pm->next != NULL )
  281. {
  282. if( pm->next->pt.x == pt->x && pm->next->pt.y == pt->y )
  283. {
  284. if( ncnt != ) ///不为首节点
  285. {
  286. prior_pt->x = pm->pt.x;
  287. prior_pt->y = pm->pt.y;
  288. return ncnt - ;
  289. }
  290. else return -; ///不存在前驱节点
  291. }
  292. pm = pm->next;
  293. ++ncnt;
  294. }
  295.  
  296. return -;
  297. }
  298.  
  299. /**
  300. * @brief 获取某 pt 元素的后继节点到 next_pt
  301. *
  302. * @param 指向待获取前后继点的线性表指针
  303. * @param pt 指向目标节点的指针
  304. * @param prior_pt 存放目标节点 pt 的后继节点
  305. *
  306. * @return 若成功获取后继节点, 返回该后继节点在线性表中的位置, 否则返回 -1
  307. *
  308. * @note 元素位置从 0 计起
  309. */
  310. int GetNextElem( mList *pList, ElemType *pt, ElemType *next_pt )
  311. {
  312. ListNode *pm = pList->head;
  313. int ncnt = ;
  314. while( (pm = pm->next) != NULL )
  315. {
           if( ncnt == pList->length )  //bug修复, 不存在后继节点
              return -1;
  316. if( pm->pt.x == pt->x && pm->pt.y == pt->y )
  317. {
  318. if( pm->next != NULL )
  319. {
  320. next_pt->x = pm->next->pt.x;
  321. next_pt->y = pm->next->pt.y;
  322.  
  323. return ncnt + ;
  324. }
  325. }
  326. ++ncnt;
  327. }
  328.  
  329. return -;
  330. }
  331.  
  332. /**
  333. * @brief 对线性表中每个元素执行 func 函数
  334. *
  335. * @param pList 指向待处理的线性表的指针
  336. * @param func 传入的函数指针
  337. *
  338. * @return void
  339. */
  340. void ForEachList( mList *pList, void (*func)(ElemType *pt) )
  341. {
  342. ListNode *pm = pList->head;
  343. while( (pm = pm->next) != NULL )
  344. func( &pm->pt );
  345. }
  346.  
  347. /**
  348. * @brief 将 pSrcList 性表复制到 pDestList 线性表后
  349. *
  350. * @param pDestList 指向目标线性表指针
  351. * @param pSrcList 指向源线性表指针
  352. *
  353. * @return 返回复制后目标线性表长度
  354. */
  355. int ListCpy( mList *pDestList, mList *pSrcList )
  356. {
  357. ListNode *pm = pDestList->head;
  358. ListNode *pn = pSrcList->head;
  359. ListNode *ptmp = NULL;
  360.  
  361. while( pm->next != NULL ) pm = pm->next;
  362. while( (pn = pn->next) != NULL )
  363. {
  364. ptmp = (ListNode *)malloc(sizeof(ListNode));
  365. ptmp->pt.x = pn->pt.x;
  366. ptmp->pt.y = pn->pt.y;
  367. pm->next = ptmp;
  368. pm = pm->next;
  369. }
  370. pm->next = NULL;
  371. pDestList->length += pSrcList->length;
  372.  
  373. return pDestList->length;
  374. }
  375.  
  376. /**
  377. * @brief 将 pSrcList 性表连接到 pDestList 线性表后
  378. *
  379. * @param pDestList 指向目标线性表指针
  380. * @param pSrcList 指向源线性表指针
  381. *
  382. * @return 返回连接后目标线性表长度
  383. *
  384. * @note 连接后 pSrcList 线性表将被销毁
  385. */
  386. int ListCat( mList *pDestList, mList *pSrcList )
  387. {
  388. ListNode *pm = pDestList->head;
  389. while( pm->next != NULL ) pm = pm->next;
  390. pm->next = pSrcList->head->next;
  391. pDestList->length += pSrcList->length;
  392. free( pSrcList );
  393.  
  394. return pDestList->length;
  395. }
  396.  
  397. //测试 mList
  398.  
  399. void display( ElemType *pt )
  400. {
  401. printf("(%d,%d) ", pt->x, pt->y);
  402. }
  403.  
  404. int main()
  405. {
  406. mList *plstA = CreateList(), *plstB = CreateList(); //创建 plst 与 plst2 两根空线性表
  407. ElemType pt, pt2; //两个 ElemType 型元素
  408.  
  409. int i = ;
  410. for( i = ; i < ; ++i )
  411. {
  412. pt.x = i;
  413. pt.y = i;
  414. AppendElem( plstA, &pt ); //向 plst 循环添加 (0,0) 至 (10,10)
  415. }
  416.  
  417. for( i = ; i < ; ++i )
  418. {
  419. pt.x = i;
  420. pt.y = i;
  421. AppendElem( plstB, &pt ); //向 plst 循环添加 (55,55) 至 (60,60)
  422. }
  423.  
  424. ///测试 ForEachList
  425. printf("plstA 初始数据: ");
  426. ForEachList( plstA, display ); //对线性表中每个元素执行 display 函数
  427.  
  428. printf("\nplstB 初始数据: ");
  429. ForEachList( plstB, display );
  430.  
  431. ///测试 InsertElem
  432. printf("\n\n向 plstA 位置3处插入元素(100,99)后:\n");
  433. pt.x = ; pt.y = ;
  434. InsertElem( plstA, , &pt ); //向 plstA 位置 3 处插入 pt
  435. ForEachList( plstA, display );
  436.  
  437. ///测试 DeleteElem
  438. printf("\n\n删除 plstB 位置0处的元素后:\n");
  439. DeleteElem( plstB, ); //删除 plstA 位置 0 处的元素
  440. ForEachList( plstB, display );
  441.  
  442. ///测试 IsEmpty、GetLength
  443. printf("\n\n线性表 plstA 是否为空: %d\n", IsEmpty(plstA) );
  444. printf("线性表 plstB 的长度: %d\n", GetLength(plstB) );
  445.  
  446. ///测试 GetElem
  447. GetElem( plstA, , &pt );
  448. printf("获取 plstA 位置 5 的元素: (%d, %d)\n", pt.x, pt.y );
  449.  
  450. ///测试 FindElem
  451. pt.x = ; pt.y = ;
  452. printf("获取元素(6,6)在线性表plstA中的位置: %d\n", FindElem(plstA, , &pt));
  453.  
  454. ///测试 GetPriorElem
  455. GetPriorElem( plstA, &pt, &pt2 );
  456. printf("获取pt=(6,6)在plstA中的前驱节点: (%d,%d)\n", pt2.x, pt2.y);
  457.  
  458. ///测试 GetNextElem
  459. GetNextElem( plstA, &pt, &pt2 );
  460. printf("获取pt=(6,6)在plstA中的后继节点: (%d,%d)\n", pt2.x, pt2.y);
  461.  
  462. ///测试 ListCpy
  463. printf("\n将 plstB 复制到 plstA 后:\n");
  464. ListCpy( plstA, plstB );
  465. ForEachList( plstA, display );
  466. printf("\nplstA长度=%d\n", GetLength(plstA));
  467.  
  468. ///测试 ListCat
  469. printf("\n将 plstB 连接到 plstA 后:\n");
  470. ListCat( plstA, plstB );
  471. ForEachList( plstA, display );
  472. printf("\nplstA长度=%d\n", GetLength(plstA));
  473.  
  474. ///测试 ClearList
  475. printf("\n置空 plstA 线性表:\n");
  476. ClearList(plstA);
  477. printf("plstA 长度=%d\n", GetLength(plstA));
  478.  
  479. ///测试 DestroyList
  480. printf("销毁 plstA..");
  481. DestroyList(plstA);
  482.  
  483. return ;
  484. }

若代码存在 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. android开发时gen和bin目录的SVN管理(转)

    转自:http://www.cnblogs.com/brucenan/archive/2012/02/23/2364702.html android在eclipse下的项目,会生成gen和bin两个目 ...

  2. Multipart to single part feature

    Multipart to single part feature Explode Link: http://edndoc.esri.com/arcobjects/8.3/?URL=/arcobject ...

  3. Linux课程实践一:Linux基础实践(基础操作)

    一.软件源维护 1. 基本操作 (1)查看源列表 sudo vim /etc/apt/sources.list deb:二进制软件安装包 deb-src:源码包 (2)备份软件源列表 sudo cp ...

  4. 实践一:Linux基础实践

    一.Linux基础实践 1.1 1. 掌握软件源的维护方法,配置系统使用软件源镜像.掌握通过软件源来查找,安装,卸载,更新软件的方法. 这部分内容在许多学长学姐的报告里都有很详细的讲解,我在此就不赘述 ...

  5. 安卓中adapter的应用

    个人菜鸟总结,期待大神指点,悉心倾看! Adapter是ListView界面与数据之间的桥梁,Adapter提供对数据的访问,也负责为每一项数据产生一个对应的View(白话通俗点:先写adapter为 ...

  6. java打包遇到问题java.io.IOException: invalid header field

    问题:java打包时报以下错误 $ jar -cvmf main.txt test.jar Shufile1.class java.io.IOException: invalid header fie ...

  7. AndroidStudio调试APP

    AndroidStudio调试APP 电脑用数据线连上手机 开启手机的开发者模式 注:通常连续狂点手机的版本号即可显示出开发者选项,然后进入菜单,勾选开发者选项.USB调试. 给程序加断点 单击调试按 ...

  8. 灭顶之灾之网络电视精灵——S2 2.8

    从前,有一个神奇的东西叫做搞搞精灵 关于他,有一段历史. 哎呀!我去!写不下去了. -.-以上玩笑 首先需求分析 TreeView显示两种频道 TypeA和TypeB 所以创建三个类 ChannelB ...

  9. Trie树:POJ2001

    这是一道最简单的trie树的题 有趣的是这道题的测试用例无法在VS上调试,只能在框框里不断提交测试了,哈哈 最基本的Trie树,插入和查找操作没什么好说的 注意节点添加一个count变量作为附加条件, ...

  10. Strict Standards: Only variables should be passed by reference

    <?php $tag="1 2 3 4 5 6 7"; $tag_sel = array_shift(explode(' ', $tag)); print_r($tag_se ...