文字描述

  之前的链表(单链表、循环链表)的链式存储结构中只有一个指示直接后继的指针域。由此,从某个结点出发只能顺指针往后寻查其他结点。若要寻查结点的直接前驱,则需从表头指针出发。即单链表中,NextElem的执行时间为1,而PriorElem的执行时间为n。为了克服单链表这种缺点,可利用双向链表。

  在双向链表中,每个节点有两个指针域,一个指向其直接后继,一个指向其直接前驱。

示意图

算法分析

插入、删除、查找、求后继等同单链表。但是求前驱不一样,其时间复杂度为1。

代码实现

  1. //
  2. // Created by lady on 19-1-31.
  3. //
  4.  
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8.  
  9. //线性表的双向循环链表存储结构
  10. typedef struct ElemType{
  11. char data[];
  12. }ElemType;
  13. typedef struct DuLNode{
  14. ElemType e;
  15. struct DuLNode *prior;
  16. struct DuLNode *next;
  17. }DuLNode, *DuLinkList;
  18.  
  19. //构造一个空的双向循环链表
  20. static int InitList_DuL(DuLinkList *L)
  21. {
  22. (*L) = (DuLinkList)malloc(sizeof(DuLNode));
  23. (*L)->prior = (*L);
  24. (*L)->next = (*L);
  25. memset((*L)->e.data, , sizeof((*L)->e.data));
  26. return ;
  27. }
  28.  
  29. //销毁L
  30. static int Destory_DuL(DuLinkList *L)
  31. {
  32. DuLNode *p = NULL;
  33. DuLNode *q = NULL;
  34. p = (*L)->next;
  35. while(p){
  36. q = p;
  37. p = p->next;
  38. free(q);
  39. if(p == (*L))
  40. break;
  41. }
  42. free(*L);
  43. (*L) = NULL;
  44. return ;
  45. }
  46.  
  47. //返回双向链表L中的第i个位置的元素
  48. static DuLNode *GetElemP_DuL(DuLinkList *L, int i)
  49. {
  50. if(L == NULL){
  51. return NULL;
  52. }
  53. DuLNode *p = (*L)->next;
  54. int index = ;
  55. while(index<i && p){
  56. index += ;
  57. p = p->next;
  58. }
  59. if(index == i && p){
  60. return p;
  61. }else{
  62. return NULL;
  63. }
  64. }
  65.  
  66. //在L的指定位置i的元素前面插入元素e
  67. static int ListInsert_DuL(DuLinkList *L, int i, ElemType e)
  68. {
  69. DuLNode *p = NULL;
  70. DuLNode *new = NULL;
  71. if((p=GetElemP_DuL(L, i)) == NULL){
  72. return -;
  73. }
  74. if((new = (DuLNode*)malloc(sizeof(DuLNode))) == NULL){
  75. return -;
  76. }
  77. new->e = e;
  78. new->prior = p->prior;
  79. p->prior->next = new;
  80. new->next = p;
  81. p->prior = new;
  82. return ;
  83. }
  84.  
  85. //删除L中的第loc个数据元素,并将被删元素的值存放在e中
  86. static int ListDelete_DuL(DuLinkList *L, int i, ElemType *e)
  87. {
  88. DuLNode *p = NULL;
  89. if((p=GetElemP_DuL(L, i)) == NULL){
  90. return -;
  91. }
  92. (*e) = p->e;
  93. p->prior->next = p->next;
  94. p->next->prior = p->prior;
  95. free(p);
  96. return ;
  97. }
  98.  
  99. //依次对L的每个数据元素调用函数fun
  100. static int listTraverse_DuL(DuLinkList *L, int (*fun)(ElemType,int), char note[])
  101. {
  102. printf("遍历双向循环链表%s:", note);
  103. DuLNode *p = NULL;
  104. p = (*L)->next;
  105. int i = ;
  106. while(p){
  107. fun(p->e, i);
  108. i+=;
  109. p = p->next;
  110. if(p == (*L))
  111. break;
  112. }
  113. printf("\n");
  114. return ;
  115. }
  116.  
  117. static int print(ElemType e, int loc)
  118. {
  119. printf("%3d=%-10s", loc, e.data);
  120. }
  121.  
  122. //创建一个长度为n的双向链表
  123. static int CreateList_DuL(DuLinkList *L, int n, char note[])
  124. {
  125. printf("创建一个长度为%d的双向循环链表%s!\n", n, note);
  126. InitList_DuL(L);
  127. ElemType e;
  128. int i = ;
  129. for(i=; i<n; i++){
  130. printf("输入第%d个元素:", i+);
  131. scanf("%s[^\\n]", e.data);
  132. ListInsert_DuL(L, i+, e);
  133. }
  134. return ;
  135. }
  136.  
  137. int main(int argc, char *argv[])
  138. {
  139. ElemType e;
  140. DuLinkList L;
  141. int location=;
  142.  
  143. CreateList_DuL(&L, , "L");
  144.  
  145. listTraverse_DuL(&L, print, "L");
  146.  
  147. printf("输入插入元素的位置:");
  148. scanf("%d", &location);
  149. printf("输入插入元素的数据:");
  150. scanf("%s[^\\n]", e.data);
  151. ListInsert_DuL(&L, location, e);
  152. listTraverse_DuL(&L, print, "L");
  153.  
  154. printf("输入删除元素的位置:");
  155. scanf("%d", &location);
  156. ListDelete_DuL(&L, location, &e);
  157.  
  158. printf("位于%d的元素%s已经从双向循环链表中被删除!\n", location, e.data);
  159. listTraverse_DuL(&L, print, "L");
  160.  
  161. Destory_DuL(&L);
  162. printf("双向链表已经被销毁!\n");
  163. return ;
  164. }

双向链表

代码运行

  1. /home/lady/CLionProjects/untitled/cmake-build-debug/untitled
  2. 创建一个长度为5的双向循环链表L!
  3. 输入第1个元素:c
  4. 输入第2个元素:b
  5. 输入第3个元素:e
  6. 输入第4个元素:g
  7. 输入第5个元素:f
  8. 遍历双向循环链表L: 1=c 2=b 3=e 4=g 5=f
  9. 输入插入元素的位置:3
  10. 输入插入元素的数据:test
  11. 遍历双向循环链表L: 1=c 2=b 3=test 4=e 5=g 6=f
  12. 输入删除元素的位置:4
  13. 位于4的元素e已经从双向循环链表中被删除!
  14. 遍历双向循环链表L: 1=c 2=b 3=test 4=g 5=f
  15. 双向链表已经被销毁!
  16.  
  17. Process finished with exit code 0

线性表->链式存储->双向链表的更多相关文章

  1. 线性表->链式存储->循环链表

    文字描述 循环链表是另一种形式的链式存储结构.它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环.由此,从表中任一结点出发均可找到表中其他结点. 示意图 算法分析 插入.删除.查找等同单 ...

  2. 线性表->链式存储->线形链表(单链表)

    文字描述: 为了表示前后两个数据元素的逻辑关系,对于每个数据元素,除了存储其本身的信息之外(数据域),还需存储一个指示其直接后继的信息(即直接后继的存储位置,指针域). 示意图: 算法分析: 在单链表 ...

  3. C语言实现线性表(链式存储方式)

    #include <stdio.h> #include <stdlib.h> //提供malloc()原型 typedef struct LNode *List; typede ...

  4. C语言 线性表 链式表结构 实现

    一个单链式实现的线性表 mList (GCC编译). /** * @brief 线性表的链式实现 (单链表) * @author wid * @date 2013-10-21 * * @note 若代 ...

  5. javascript实现数据结构:线性表--线性链表(链式存储结构)

    上一节中, 线性表的顺序存储结构的特点是逻辑关系上相邻的两个元素在物理位置上也相邻,因此可以随机存取表中任一元素,它的存储位置可用一个简单,直观的公式来表示.然后,另一方面来看,这个特点也造成这种存储 ...

  6. 算法与数据结构(一) 线性表的顺序存储与链式存储(Swift版)

    温故而知新,在接下来的几篇博客中,将会系统的对数据结构的相关内容进行回顾并总结.数据结构乃编程的基础呢,还是要不时拿出来翻一翻回顾一下.当然数据结构相关博客中我们以Swift语言来实现.因为Swift ...

  7. c数据结构 -- 线性表之 复杂的链式存储结构

    复杂的链式存储结构 循环链表 定义:是一种头尾相接的链表(即表中最后一个结点的指针域指向头结点,整个链表形成一个环) 优点:从表中任一节点出发均可找到表中其他结点 注意:涉及遍历操作时,终止条件是判断 ...

  8. [置顶] ※数据结构※→☆线性表结构(queue)☆============优先队列 链式存储结构(queue priority list)(十二)

    优先队列(priority queue) 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除.在优先队列中,元素被赋予优先级.当访问元素时,具有最高优先级的元素最先删除.优先队列具有 ...

  9. C++编程练习(2)----“实现简单的线性表的链式存储结构“

    单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素. 对于查找操作,单链表的时间复杂度为O(n). 对于插入和删除操作,单链表在确定位置后,插入和删除时间仅为O(1). 单链表不需要分配存储 ...

随机推荐

  1. Misc杂项隐写题writeup

    MISC-1 提示:if you want to find the flag, this hint may be useful: the text files within each zip cons ...

  2. 详解HTTPS、TLS、SSL

    HTTPS.TLS.SSL HTTP也称作HTTP over TLS.TLS的前身是SSL,TLS 1.0通常被标示为SSL 3.1,TLS 1.1为SSL 3.2,TLS 1.2为SSL 3.3.下 ...

  3. ios 给微信开发一个插件并安装到未越狱的手机上教程

    现来整体说一下思路,首先给越狱的手机开发一个插件并安装上去,然后去越狱手机上找到相应的动态库和对应的微信APP安装包,拷贝出来,然后重新签名,就可以安装到未越狱的手机上了 1.首先你的电脑需要安装th ...

  4. SpringBoot配置分析、获取到SpringBoot配置文件信息以及几种获取配置文件信息的方式

    Spring入门篇:https://www.cnblogs.com/biehongli/p/10170241.html SpringBoot的默认的配置文件application.properties ...

  5. Pylon5 SDK搭配OpenCV使用入门

    本文假设已经安装了Basler官网提供的Pylon 目前最新的版本是5.0.5,如果上述链接打不开,请直接所有Basler官网下载,需要注意的是在安装Pylon5时要选择Developer模式,这样才 ...

  6. JSONP ---------跨域

    什么是跨域 JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象.但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦.这里把涉及到跨域的一些问题简单地整理一下: 首 ...

  7. P1265 公路修建 最小生成树

    题目描述 某国有n个城市,它们互相之间没有公路相通,因此交通十分不便.为解决这一“行路难”的问题,政府决定修建公路.修建公路的任务由各城市共同完成. 修建工程分若干轮完成.在每一轮中,每个城市选择一个 ...

  8. DDoS攻击与防御(3)

    3.攻击应用资源网络应用和服务在处理数据时,通常需要消耗一定的网络连接.计算和存储资源,这些资源是由应用程序向系统进行申请并自行管理和维护的.消耗应用资源的DDoS攻击就是通过向应用提交大量消耗资源的 ...

  9. Tomcat Getshell

    安装环境 账号密码路径:Tomcat6.0/conf/tomcat-users.xml 弱口令扫描工具 后台默认登陆地址:html://xx.xx.xx.xx/manager/html 后台war f ...

  10. django中models field详解

    本文参考自:django官方文档models/field 在model中添加字段的格式一般为:  field_name = field_type(**field_options) 一  field o ...