双向链表也叫双链表,是链表的一种,它的每一个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的随意一个结点開始,都能够非常方便地訪问它的前驱结点和后继结点。

单链表的局限

1。单链表的结点都仅仅有一个指向下一个结点的指针

2,单链表的数据元素无法直接訪问其前驱元素

3。逆序訪问单链表中的元素是极其耗时的操作

双向链表的操作

双向链表的新操作

1,获取当前游标指向的数据元素

2,将游标重置指向链表中的第一个数据元素

3,将游标移动指向到链表中的下一个数据元素

4,将游标移动指向到链表中的上一个数据元素

5,直接指定删除链表中的某个数据元素

DLinkListNode*DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node);

DLinkListNode*DLinkList_Reset(DLinkList* list);

DLinkListNode*DLinkList_Current(DLinkList* list);

DLinkListNode*DLinkList_Next(DLinkList* list);

DLinkListNode*DLinkList_Pre(DLinkList* list);

头文件:

  1. #ifndef _DDLinkList_H_
  2. #define _DDLinkList_H_
  3. typedef void DLinkList;
  4. typedef struct DLinkListNode //声明指针域
  5. {
  6. DLinkListNode * pre;
  7. DLinkListNode * next;
  8. }DLinkListNode;
  9.  
  10. DLinkList * DLinkList_Create();
  11.  
  12. void DLinkList_DesTroy(DLinkList * list);
  13.  
  14. void DLinkList_Clear(DLinkList* list);
  15.  
  16. int DLinkList_Length(DLinkList* list);
  17.  
  18. int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos);
  19.  
  20. DLinkListNode* DLinkList_Get(DLinkList* list, int pos);
  21.  
  22. DLinkListNode* DLinkList_Delete(DLinkList* list, int pos);
  23.  
  24. DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node);
  25.  
  26. DLinkListNode* DLinkList_Reset(DLinkList* list);
  27.  
  28. DLinkListNode* DLinkList_Current(DLinkList* list);
  29.  
  30. DLinkListNode* DLinkList_Next(DLinkList* list);
  31.  
  32. DLinkListNode* DLinkList_Pre(DLinkList* list);
  33.  
  34. #endif

源文件:

  1. // 双向链表.cpp : 定义控制台应用程序的入口点。
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "DLinkList.h"
  6. #include <stdlib.h>
  7. #include <malloc.h>
  8.  
  9. typedef struct
  10. {
  11. DLinkListNode header;
  12. DLinkListNode * slider; //游标
  13. int len;
  14. }TDLinkList;
  15.  
  16. struct Value
  17. {
  18. DLinkListNode header; //指针域
  19. int v; //数据域
  20. };
  21.  
  22. int _tmain(int argc, _TCHAR* argv[])
  23. {
  24. int i = 0;
  25. DLinkList* list = DLinkList_Create();//创建链表
  26. struct Value* pv = NULL;
  27. struct Value v1;
  28. struct Value v2;
  29. struct Value v3;
  30. struct Value v4;
  31. struct Value v5;
  32.  
  33. v1.v = 1;
  34. v2.v = 2;
  35. v3.v = 3;
  36. v4.v = 4;
  37. v5.v = 5;
  38. //插入5个数
  39. DLinkList_Insert(list, (DLinkListNode*)&v1, DLinkList_Length(list));
  40. DLinkList_Insert(list, (DLinkListNode*)&v2, DLinkList_Length(list));
  41. DLinkList_Insert(list, (DLinkListNode*)&v3, DLinkList_Length(list));
  42. DLinkList_Insert(list, (DLinkListNode*)&v4, DLinkList_Length(list));
  43. DLinkList_Insert(list, (DLinkListNode*)&v5, DLinkList_Length(list));
  44.  
  45. for(i=0; i<DLinkList_Length(list); i++)
  46. {
  47. pv = (struct Value*)DLinkList_Get(list, i);
  48.  
  49. printf("插入了:%d\n", pv->v);
  50. }
  51.  
  52. printf("\n");
  53. //删除头尾
  54. DLinkList_Delete(list, DLinkList_Length(list)-1);
  55. DLinkList_Delete(list, 0);
  56. printf("删除头尾结点后:\n");
  57. for(i=0; i<DLinkList_Length(list); i++)
  58. {
  59. pv = (struct Value*)DLinkList_Next(list);
  60.  
  61. printf("%d\n", pv->v);
  62. }
  63.  
  64. printf("\n");
  65.  
  66. DLinkList_Reset(list);//游标指向第一个结点 2
  67. DLinkList_Next(list);//游标指向第二个结点 3
  68.  
  69. pv = (struct Value*)DLinkList_Current(list);
  70.  
  71. printf("游标移到第二个结点后的值: %d\n", pv->v);
  72.  
  73. DLinkList_DeleteNode(list, (DLinkListNode*)pv);//删除第二个结点
  74.  
  75. pv = (struct Value*)DLinkList_Current(list);
  76.  
  77. printf("游标删除第二个结点后的值: %d\n", pv->v);
  78.  
  79. DLinkList_Pre(list); //将游标向前移动一位
  80.  
  81. pv = (struct Value*)DLinkList_Current(list);
  82.  
  83. printf("游标向前移了一位后的值:%d\n", pv->v);
  84.  
  85. printf("Length: %d\n", DLinkList_Length(list));
  86.  
  87. DLinkList_DesTroy(list);
  88. system("pause");
  89. return 0;
  90. }
  91.  
  92. //创建
  93. DLinkList * DLinkList_Create()
  94. {
  95. TDLinkList* list = NULL;
  96. list = (TDLinkList*)malloc(sizeof(TDLinkList));
  97. if(NULL != list)
  98. {
  99. list->len = 0;
  100. list->header.next = NULL;
  101. list->header.pre = NULL;
  102. list->slider = NULL;
  103. }
  104. return list;
  105. }
  106.  
  107. //销毁
  108. void DLinkList_DesTroy(DLinkList * list)
  109. {
  110. free(list);
  111. }
  112.  
  113. //清空
  114. void DLinkList_Clear(DLinkList* list)
  115. {
  116. TDLinkList* sList = (TDLinkList*)list;
  117. if(NULL != sList)
  118. {
  119. sList->len = 0;
  120. sList->header.next = NULL;
  121. sList->header.pre = NULL;
  122. sList->slider = NULL;
  123. }
  124. }
  125.  
  126. //获得长度
  127. int DLinkList_Length(DLinkList* list)
  128. {
  129. TDLinkList* sList = (TDLinkList*)list;
  130. int len = -1;
  131. if(NULL != sList)
  132. {
  133. len = sList->len;
  134. }
  135. return len;
  136. }
  137.  
  138. //插入
  139. int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos)
  140. {
  141. TDLinkList* sList = (TDLinkList*)list;
  142.  
  143. int i = 0;
  144. int ret = 0;
  145. if((NULL != sList) && (pos >= 0) && (NULL != node))
  146. {
  147. DLinkListNode* current = (DLinkListNode*)sList;
  148. DLinkListNode* next = NULL;
  149. for( i=0; (i<pos) && (current->next != NULL); i++)
  150. {
  151. current = current->next;
  152. }
  153. next = current->next;
  154. current->next = node;
  155. node->next = next;
  156. if(NULL != next)
  157. {
  158. next->pre = node;
  159. }
  160. node->pre = current;
  161.  
  162. if(sList->len == 0)
  163. {
  164. node->pre = NULL;
  165. sList->slider = node;
  166. }
  167. sList->len++;
  168. ret = 1;
  169. }
  170. return ret;
  171. }
  172.  
  173. //获得结点
  174. DLinkListNode* DLinkList_Get(DLinkList* list, int pos)
  175. {
  176. TDLinkList* sList = (TDLinkList*)list;
  177. int i = 0;
  178. DLinkListNode * resnode = NULL;
  179. if((pos >= 0) && (pos < sList->len) && (NULL != sList))
  180. {
  181. DLinkListNode * current = (DLinkListNode*)sList;
  182. for ( i=0; i<pos; i++)
  183. {
  184. current = current->next;
  185. }
  186. resnode = current->next;
  187. }
  188. return resnode;
  189. }
  190.  
  191. //删除
  192. DLinkListNode* DLinkList_Delete(DLinkList* list, int pos)
  193. {
  194. TDLinkList* sList = (TDLinkList*)list;
  195. int i = 0;
  196. DLinkListNode* ret = NULL;
  197. if((NULL != sList) && (pos >= 0) && (pos < sList->len))
  198. {
  199. DLinkListNode* current = (DLinkListNode*)sList;
  200. DLinkListNode* next = NULL;
  201. for ( i=0; i<pos; i++)
  202. {
  203. current = current->next;
  204. }
  205. ret = current->next;
  206. next = ret->next;
  207.  
  208. current->next = next;
  209. if(NULL != next)
  210. {
  211. next->pre = current;
  212. //当删除的结点是第一个结点的时候
  213. if(current == (DLinkListNode*)sList)
  214. {
  215. //前驱指针为空
  216. next->pre = NULL;
  217. }
  218. }
  219. if(sList->slider == ret)
  220. {
  221. sList->slider = next;
  222. }
  223. sList->len--;
  224. }
  225. return ret;
  226. }
  227.  
  228. //通过指定结点删除
  229. DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node)
  230. {
  231. TDLinkList* sList = (TDLinkList*)list;
  232. DLinkListNode* ret = NULL;
  233. int i = 0;
  234. if((NULL != sList) && (NULL != node))
  235. {
  236. DLinkListNode* current = (DLinkListNode*)sList;
  237. for ( i=0; i<sList->len; i++)
  238. {
  239. if(current->next == node)
  240. {
  241. ret = current->next;
  242. break;
  243. }
  244. current = current->next;
  245. }
  246. if( ret != NULL )
  247. {
  248. DLinkList_Delete(sList, i);
  249. }
  250. }
  251. return ret;
  252.  
  253. }
  254.  
  255. //重置游标,使其到第一个结点处
  256. DLinkListNode* DLinkList_Reset(DLinkList* list)
  257. {
  258. TDLinkList* sList = (TDLinkList*)list;
  259. DLinkListNode* ret = NULL;
  260. if((NULL != sList))
  261. {
  262. sList->slider = sList->header.next;
  263. ret = sList->slider;
  264. }
  265. return ret;
  266. }
  267.  
  268. //将游标移至当前结点处
  269. DLinkListNode* DLinkList_Current(DLinkList* list)
  270. {
  271. TDLinkList* sList = (TDLinkList*)list;
  272. DLinkListNode* ret = NULL;
  273. if(NULL != sList)
  274. {
  275. ret = sList->slider;
  276. }
  277. return ret;
  278. }
  279.  
  280. //
  281. DLinkListNode* DLinkList_Next(DLinkList* list)
  282. {
  283. TDLinkList* sList = (TDLinkList*)list;
  284. DLinkListNode* ret = NULL;
  285. if((NULL != sList) && (NULL != sList->slider ))
  286. {
  287. ret = sList->slider;
  288. sList->slider = ret->next;
  289. }
  290. return ret;
  291. }
  292.  
  293. DLinkListNode* DLinkList_Pre(DLinkList* list)
  294. {
  295. TDLinkList* sList = (TDLinkList*)list;
  296. DLinkListNode* ret = NULL;
  297. if((NULL != sList) && (NULL != sList->slider ))
  298. {
  299. ret = sList->slider;
  300. sList->slider = ret->pre;
  301. }
  302. return ret;
  303. }

执行结果:

  1. 插入了:1
  2. 插入了:2
  3. 插入了:3
  4. 插入了:4
  5. 插入了:5
  6.  
  7. 删除头尾结点后:
  8. 2
  9. 3
  10. 4
  11.  
  12. 游标移到第二个结点后的值: 3
  13. 游标删除第二个结点后的值: 4
  14. 游标向前移了一位后的值:2
  15. Length: 2
  16. 请按随意键继续. . .

如有错误,望不吝指出。

双向链表的实现与操作(C语言实现)的更多相关文章

  1. neo4j初次使用学习简单操作-cypher语言使用

    Neo4j 使用cypher语言进行操作 Cypher语言是在学习Neo4j时用到数据库操作语言(DML),涵盖对图数据的增删改查  neo4j数据库简单除暴理解的概念: Neo4j中不存在表的概念, ...

  2. 栈的实现与操作(C语言实现)

    栈的定义  1, 栈是一种特殊的线性表  2,栈仅能在线性表的一端进行操作  3,栈顶(Top): 同意操作的一端 同意操作的一端  4,栈底(Bottom): ,不同意操作的一端 不同意操作 ...

  3. 动态单链表的传统存储方式和10种常见操作-C语言实现

    顺序线性表的优点:方便存取(随机的),特点是物理位置和逻辑为主都是连续的(相邻).但是也有不足,比如:前面的插入和删除算法,需要移动大量元素,浪费时间,那么链式线性表 (简称链表) 就能解决这个问题. ...

  4. Gremlin--一种支持对图表操作的语言

    Gremlin 是操作图表的一个非常有用的图灵完备的编程语言.它是一种Java DSL语言,对图表进行查询.分析和操作时使用了大量的XPath. Gremlin可用于创建多关系图表.因为图表.顶点和边 ...

  5. 动态分配的顺序线性表的十五种操作—C语言实现

    线性表 定义:是最常用的,也是最简单的数据结构,是长度为n个数据元素的有序的序列. 含有大量记录的线性表叫文件 记录:稍微复杂的线性表里,数据元素为若干个数据项组成,这时把一个数据元素叫记录 结构特点 ...

  6. 循环链表的实现与操作(C语言实现)

    循环链表是还有一种形式的链式存贮结构.它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环. 循环链表的操作 1,循环链表的新操作 2, 获取当前游标指向的数据元素 3, 将游标重置指向链 ...

  7. 图的存储结构与操作--C语言实现

    图(graph)是一种比树结构还要复杂的数据结构,它的术语,存储方式,遍历方式,用途都比较广,所以如果想要一次性完成所有的代码,那代码会非常长.所以,我将分两次来完成图的代码.这一次,我会完成图的五种 ...

  8. 二叉树的操作--C语言实现

    树是一种比较复杂的数据结构,它的操作也比较多.常用的有二叉树的创建,遍历,线索化,线索化二叉树的遍历,这些操作又可以分为前序,中序和后序.其中,二叉树的操作有递归与迭代两种方式,鉴于我个人的习惯,在这 ...

  9. C文件操作的语言fgets()

        谈fgets(..)功能.     原型  char *  fgets(char * s, int n,FILE *stream);     參数:          s: 字符型指针.指向存 ...

随机推荐

  1. poj1179 区间dp(记忆化搜索写法)有巨坑!

    http://poj.org/problem?id=1179 Description Polygon is a game for one player that starts on a polygon ...

  2. [NOIP 2017] 奶酪

    [题目链接] http://uoj.ac/problem/332 [算法] 直接搜索即可 注意使用long long [代码] #include<bits/stdc++.h> using ...

  3. kubernetes系列(小知识):kubectl命令自动补全

    kubectl命令自动补全 linux系统 yum install -y bash-completion source /usr/share/bash-completion/completions/d ...

  4. linux下使用bcp备份sybase数据

    命令|数据库名|表名|导出到|文件名|格式|sybase服务名|数据库登录名 |字符集 bcp dbname..tablename out filename -n -Sgfdmhk -UISISMan ...

  5. [hihocoder][Offer收割]编程练习赛44

    扫雷游戏 #pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #includ ...

  6. 第一天:java与mysql的连接工具类

    第一天:java与mysql的连接工具类 java最新版马上就要收费,这无疑是这门语言的衰败起始,毕竟在中国收费便难发展,例如c#,但是毕业设计已经选好用java来写一个动态网站, 这已经是一个事实, ...

  7. css3动画简单案例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 【Oracle】Rman简介

    1.备份和恢复功能的用途: –保护数据 -介质故障 -用户错误 -应用程序错误 –数据保存和历史数据保留 –数据传输 2.典型的备份和恢复任务 –通过配置数据库实现可恢复 –定义备份计划 –对不同类型 ...

  9. 3D特征:关于HFM和HBB

    1.HBB    三维绑定框 (1): 要用到HBB,定义还不太清楚,来自于 VALVE Developer Community (https://developer.valvesoftware.co ...

  10. swift 类型备份

    Swift语法3.03(类型Types) https://www.jianshu.com/p/839f9bc4b9a3 https://developer.apple.com/library/cont ...