http://blog.csdn.net/jw903/article/details/38947753

双向链表其实是单链表的改进。 当我们对单链表进行操作时,有时你要对某个结点的直接前驱进行操作时,又必须从表头开始查找。这是由单链表结点的结构所限制的。因为单链表每个结点只有一个存储直接后继结点地址的链域,那么能不能定义一个既有存储直接后继结点地址的链域,又有存储直接前驱结点地址的链域的这样一个双链域结点结构呢?这就是双向链表。

在双向链表中,结点除含有数据域外,还有两个链域,一个存储直接后继结点地址,一般称之为右链域;一个存储直接前驱结点地址,一般称之为左链域。

在c语言中双向链表结点类型可以定义为:

[cpp] view plain copy
  1. typedef struct Node
  2. {
  3. int item;
  4. struct Node *pre;
  5. struct Node *next;
  6. }DListNode,*DList;

下面的代码就是对双向链表的创建和相关操作:

[cpp] view plain copy
  1. /***************************************************************************
  2. *name:jae chia                                                            *
  3. *date:2014.8.29                                                           *
  4. *version: 1.0                                                             *
  5. **************************************************************************/
  6. #include<iostream>
  7. #include<cassert>
  8. using namespace std;
  9. //双向链表的建立与操作
  10. typedef struct Node
  11. {
  12. int item;
  13. struct Node *pre;
  14. struct Node *next;
  15. }DListNode,*DList;
  16. DList InsertNodeToTail(DList head,int data)//将节点插入到双向链表的尾部
  17. {
  18. if(head==NULL)
  19. {
  20. head=(DList)malloc(sizeof(DListNode));
  21. assert(head!=NULL);
  22. head->item=data;
  23. head->next=NULL;
  24. head->pre=NULL;
  25. }
  26. else
  27. {
  28. DListNode *newnode=(DList)malloc(sizeof(DListNode));//创建新的链表节点
  29. assert(newnode!=NULL);
  30. newnode->item=data;
  31. newnode->next=NULL;
  32. newnode->pre=NULL;
  33. DListNode *p=head;
  34. while(p->next!=NULL)
  35. {
  36. p=p->next;
  37. }
  38. p->next=newnode;
  39. newnode->pre=p;
  40. }
  41. return head;
  42. }
  43. DList InsertDListByOrder(DList head,int data)//这里的插入操作是按序插入(保证双向链表中的节点以递增有序)
  44. {
  45. DListNode *newnode=(DList)malloc(sizeof(DListNode));
  46. assert(newnode);
  47. newnode->item=data;
  48. //newnode->next=NULL;
  49. //newnode->pre=NULL;
  50. DListNode *p=head;
  51. DListNode *prenode;
  52. for(;p!=NULL;p=p->next)
  53. {
  54. prenode=p;
  55. if(newnode->item <=p->item)
  56. break;
  57. }
  58. if(p==NULL)//如果遍历整个链表,结点的值都比要插入的小,那么只能在尾端插入
  59. {
  60. prenode->next=newnode;
  61. newnode->pre=prenode;
  62. newnode->next=NULL;
  63. }
  64. else if(p==head)//如果链表中的数都比要插入的数大则在头部插入;
  65. {
  66. newnode->pre=NULL;
  67. newnode->next=head;
  68. head=newnode;
  69. }
  70. else   //在中间插入
  71. {
  72. p->pre->next=newnode;
  73. newnode->pre=p->pre;
  74. newnode->next=p;
  75. p->pre=newnode;
  76. }
  77. return head;
  78. }
  79. bool FindNode(DList head,int data)//查找链表中含有某元素的节点是否存在
  80. {
  81. if(head==NULL)
  82. {
  83. cout<<"the Dlist is NULL"<<endl;
  84. return false;
  85. }
  86. DListNode *p=head;
  87. while(p!=NULL)
  88. {
  89. if(p->item==data)
  90. return true;
  91. p=p->next;
  92. }
  93. return false;
  94. }
  95. DList DeleteNode(DList head,int data)//删除节点
  96. {
  97. DListNode *p=head;
  98. while(p!=NULL)
  99. {
  100. if(p->item==data)
  101. break;
  102. p=p->next;
  103. }
  104. if(p==NULL)
  105. {
  106. cout<<"the node with data is not existed in the List"<<endl;
  107. exit(0);
  108. }
  109. if(p==head)//要删除的结点恰好是双向链表的头结点
  110. {
  111. DListNode *tmp=head;
  112. head=head->next;
  113. head->pre=NULL;//---------------------------------------------------
  114. free(tmp);
  115. }
  116. else if(p->next==NULL)//如果要删除的节点是链表的最后一个节点
  117. {
  118. p->pre->next=NULL;
  119. free(p);
  120. }
  121. else //删除中间节点
  122. {
  123. p->pre->next=p->next;
  124. p->next->pre=p->pre;
  125. }
  126. return head;
  127. }
  128. void PrintDList(DList head)//打印
  129. {
  130. cout<<"现在,链表如下:"<<endl;
  131. if(head==NULL)
  132. {
  133. cout<<"the Dlist is NULL"<<endl;
  134. return ;
  135. }
  136. DListNode *p=head;
  137. while(p!=NULL)
  138. {
  139. cout<<p->item<<" ";
  140. p=p->next;
  141. }
  142. cout<<endl<<endl;
  143. }
  144. void DestroyDList(DList head)//销毁双向链表
  145. {
  146. DListNode *p=head;
  147. while(p!=NULL)
  148. {
  149. DListNode *tmp=p;
  150. p=p->next;
  151. free(tmp);
  152. }
  153. }
  154. void Test()
  155. {
  156. DListNode *head=NULL;
  157. for(int i=0;i<10;i++)   /*利用尾部插入来构造双向链表*/
  158. head=InsertNodeToTail(head,i);
  159. PrintDList(head);
  160. int a;
  161. cout<<"输入要查找的结点的值"<<endl;
  162. cin>>a;
  163. if(FindNode(head,a))
  164. cout<<"结点存在!"<<endl<<endl;
  165. else
  166. cout<<"结点不存在!"<<endl<<endl;
  167. cout<<"删除结点4..."<<endl;    /*删除指定节点*/
  168. head=DeleteNode(head,4);
  169. PrintDList(head);
  170. cout<<"插入结点4..."<<endl;     /*按序插入*/
  171. head=InsertDListByOrder(head,4);
  172. PrintDList(head);
  173. cout<<"删除头结点..."<<endl;    /*删除指定节点*/
  174. head=DeleteNode(head,0);
  175. PrintDList(head);
  176. cout<<"删除尾结点..."<<endl;
  177. head=DeleteNode(head,9);
  178. PrintDList(head);
  179. cout<<"插入头结点..."<<endl;     /*按序插入*/
  180. head=InsertDListByOrder(head,0);
  181. PrintDList(head);
  182. cout<<"插入尾结点..."<<endl;     /*按序插入*/
  183. head=InsertDListByOrder(head,10);
  184. PrintDList(head);
  185. DestroyDList(head);
  186. }
  187. int main(void)
  188. {
  189. Test();
  190. }

运行:

双向链表的创建和相关操作相关推荐

  1. ORCL创建用户相关操作

    ORCL创建用户相关操作 -- 0.查询表空间文件保存路径 select * from v$datafile --1. 创建表空间 create tablespace jcsjv1 datafile ...

  2. 关于学习Python的一点学习总结(9->字典创建及相关操作)

    27.创建和使用字典:字典由键及其相应的值组成,这种键值对称为项(item) 方法一: >>> name={'Hongkong':'45','shanghai':'67','gui ...

  3. 数据结构--二叉树的创建和相关操作

    下面给出两个关于二叉树的题目: 1.编写程序任意输入二叉树的结点个数和结点值,构造一棵二叉树,采用三种递归遍历算法(前序.中序.后序)对这棵二叉树进行遍历并计算出二叉树的高度. 2 .编写程序生成下面 ...

  4. 数据结构——双向链表(双向连接的图解、双向链表的创建、操作双向链表)

    目录 一.双向链表 二.双向连接的图解: 三.双向链表的创建 四.操作双向链表 一.双向链表 - 单向链表: - 只能从头遍历到尾或者从尾遍历到头(一般从头到尾)   - 也就是链表相连的过程是单向的 ...

  5. (C++版)链表(一)——实现单向链表创建、插入、删除等相关操作

    http://blog.csdn.net/fisherwan/article/details/25557545 前段时间用C语言实现了链表的相关操作,但是发现当时挺清楚的,过了一段时间又忘的差不多了, ...

  6. 数据库MySQL相关操作||创建数据库、显示所有数据库、切换数据库、显示数据库下的数据库表、删除数据库

    数据库MySQL相关操作||创建数据库.显示所有数据库.切换数据库.显示数据库下的数据库表.删除数据库 1,创建数据库 create databases mydb: 记得加:(分号) 2,显示所有数据 ...

  7. Linux系统编程10:进程入门之系统编程中最重要的概念之进程进程的相关操作使用fork创建进程

    文章目录 (1)进程的概念 (2)如何管理进程 A:描述 B:PCB C:task_struct (3)进程相关操作 A:查看进程 B:进程与父进程 (4)创建进程-fork A:fork的作用:演示 ...

  8. 【环境搭建】Docker镜像相关操作(切换镜像源、查询、获取、查看、创建、上传、保存、删除等)

    目录 1 镜像源查看及设置 2 镜像相关操作 2.1 获取镜像列表 2.2 镜像下载 2.3 查看本地的镜像 2.4 从镜像创建容器 2.5 将容器抽象为镜像--commit 2.6 将容器抽象为镜像 ...

  9. 建工计算机在线使用,建工计算器创建公式的相关操作教程

    很多新手小伙伴还不了解建工计算器创建公式的具体操作,所以下面小编就带来了建工计算器创建公式的详细教程哦. 建工计算器创建公式的相关操作教程 1. 以"2点之间的距离"为例,首先点击 ...

最新文章

  1. python 调用 so 库 需要注意的地方
  2. JS----click3种方法
  3. Android存储Json到本地,和读取本地Json
  4. Linux 下的DMA浅析
  5. python enumerate()
  6. Ubuntu开发者峰会在布拉格举行
  7. 南丁格尔邮票图片大全_【鉴赏】武夷山普通纪念币鉴赏(高清图片)
  8. python游戏编程讲解之凯撒密码
  9. 3V升压5V芯片,3V升压5V电路图
  10. iOS 禁止横屏的解决方案
  11. A*算法————传教士和野人
  12. 在linux4.19内核下的UPD720201驱动里添加固件下载的代码
  13. 最完整的PS快捷键大全(绝对经典)
  14. 保温杯哪种材质最好_玻璃杯材质分为哪几种 玻璃杯什么材质最好
  15. 添加额外jars包到Hive
  16. Java字节码角度分析:Synchronized ——提升硬实力11
  17. mysql 分段执行_mySql 分段查询
  18. Redmine3.3.3 搭建与不完全填坑指南
  19. Linux·信号量全解
  20. 课程笔记之《论文写作》

热门文章

  1. 程序猿果真有前端后端client吗
  2. mysql在mac上的坑
  3. TCP多进程并发服务端 Linux socket编程入门(2)
  4. 努力学习 HTML5 (3)—— 改造传统的 HTML 页面
  5. 基于visual Studio2013解决C语言竞赛题之1049抓牌排序
  6. ParameterizedTypeImpl
  7. 画出的点做交互_设计之下交互设计原型设计之概念设计
  8. mq服务器与客户端消息同步,使用 ActiveMQ 实现JMS 异步调用
  9. C++使用JSON的序列化与反序列化
  10. 【数据结构基础笔记】【队列】