基础要义

双向链表的节点结构

双向链表的插入

要先把插入位置的后继节点重新绑定,否则容易丢失后继节点

双向链表的删除

同样是先绑定后继节点

C++代码

#include "stdio.h"    #define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0#define MAXSIZE 20 /* 存储空间初始分配量 */typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int */Status visit(ElemType c)
{printf("%d ", c);return OK;
}typedef struct DulNode
{ElemType data;struct DulNode* prior;//前驱struct DulNode* next; //后继
}DulNode, *DuLinkList;Status InitList(DuLinkList* L)
{*L = new DulNode();if (!(*L)) //存储分配失败return ERROR;//前驱 后继都是自己(*L)->next = (*L);(*L)->prior = (*L);
}//判断链表是否为空
const Status ListEmpty(DuLinkList *L)
{if ((*L)->next == (*L))return TRUE;return ERROR;
}//将L重置为空表
Status ClearList(DuLinkList* L)
{DuLinkList p;DuLinkList q;p = (*L)->next;while (p != (*L)){q = p->next;delete p;p = q;}(*L)->next = (*L);return OK;
}//返回L中的元素个数
const int ListLength(DuLinkList* L)
{int i = 0;DuLinkList p = (*L)->next;while (p != (*L)){i++;p = p->next;}return i;
}// 用e返回L中第i个元素的值
Status GetElem(DuLinkList* L, int i, ElemType* e)
{int j = 1;DuLinkList p;p = (*L)->next;while ((p != (*L)) && j < i){p = p->next;j++;}if ((p == (*L)) || j > i)return ERROR;*e = p->data;return OK;}// 寻找第 1个 与e满足关系的数据元素的位置
int LocateElem(DuLinkList* L, ElemType e)
{int i = 0;DuLinkList p = (*L)->next;while (p != (*L)){i++;if (p->data == e)return i;p = p->next;}return 0; //没有这个元素
}//在第i个位置中插入新的数据元素
Status ListInsert(DuLinkList* L, int i, ElemType e)
{DuLinkList N = new DulNode();N->data = e;int j = 1;DuLinkList p = *L;//要找到待插入节点的前驱while ((j < i) && (p->next != (*L))){p = p->next;j++;}//没有这么长的链表if ((j < i) && (p == (*L)))return ERROR; // 没有这么长的表//插入操作N->next = p->next;N->next->prior = N;N->prior = p;p->next = N;
}//删除L的第i个元素 并用e返回其值Status ListDelete(DuLinkList* L, int i, ElemType* e)
{int j = 1;DuLinkList p = (*L);DuLinkList q;while ((p->next != (*L)) && (j < i)){p = p->next;j++;}if (p->next == (*L))return ERROR;*e = p->next->data; //取出将要删除的元素的值//更新要删除的元素的前驱元素的后继,以及后继元素的前驱q = p->next;p->next = p->next->next;p->next->prior = p;delete q;return OK;
}//依次输出L的每个数据元素const Status ListTraverse(DuLinkList* L)
{DuLinkList p = (*L)->next;while (p != (*L)){visit(p->data);p = p->next;}printf("\n");return OK;
}//随机产生n个元素的值,建立带表头节点的单链线性表 L(尾插法)
void CreateListTail(DuLinkList* L, int n)
{//生成1-10 数字并且存入到链表中DuLinkList p = *L;for (int i = 0; i < n; i++){DuLinkList N = new DulNode();N->data = i;p->next = N; //将新的数据加入到尾巴N->prior = p;p = p->next; //当前指针往后走一步p->next = *L;  //表示当前链表结束}
}//随机产生n个元素的值,建立带表头节点的单链线性表 L(头插法)
void CreateListHead(DuLinkList* L, int n)
{//生成1-10 数字并且存入到链表中DuLinkList p = (*L)->next;for (int i = 0; i < n; i++){DulNode* N = new DulNode();N->data = i;N->next = p; //将第一个指针放到后面p->prior = N;(*L)->next = N; //新的第一个元素N->prior = (*L);p = N; //表头指针}
}//获得元素e的前驱元素
const ElemType GetElemIPrior(DuLinkList* L, ElemType e)
{int j = 1;DuLinkList p = (*L);while ((p->next != (*L))){if (p->next->data == e)return p->next->prior->data; //这一步操作只是验证p = p->next;}return ERROR;
}int main()
{DuLinkList L = NULL;ElemType e;Status i;int j;int k;i = InitList(&L);printf("初始化后:ListLength(L) = %d \n", ListLength(&L));for (int j = 1; j <= 5; j++){int i = ListInsert(&L, 1, j);}printf("在L的表头依次插入1~5后:ListLength(L) = %d \n", ListLength(&L));ListTraverse(&L);printf("ListLength(L)=%d \n", ListLength(&L));i = ListEmpty(&L);printf("L是否空:i=%d(1:是 0:否)\n", i);i = ClearList(&L);printf("清空L后:ListLength(L)=%d\n", ListLength(&L));i = ListEmpty(&L);printf("L是否空:i=%d(1:是 0:否)\n", i);for (int j = 1; j <= 10; j++)ListInsert(&L, j, j);printf("在L的表尾依次插入1~10后:L.data=");ListTraverse(&L);printf("ListLength(L)=%d \n", ListLength(&L));ListInsert(&L, 1, 0);printf("在L的表头插入0后:L.data=");ListTraverse(&L);printf("ListLength(L)=%d \n", ListLength(&L));GetElem(&L, 5, &e);printf("第5个元素的值为:%d\n", e);for (int j = 3; j <= 4; j++){k = LocateElem(&L, j);if (k)printf("第%d个元素的值为%d\n", k, j);elseprintf("没有值为%d的元素\n", j);}for (int j = 3; j <= 4; j++){k = LocateElem(&L, j);if (k)printf("第%d个元素的值为%d\n", k, j);elseprintf("没有值为%d的元素\n", j);}k = ListLength(&L); /* k为表长 */for (int j = k + 1; j >= k; j--){i = ListDelete(&L, j, &e); /* 删除第j个数据 */if (i == ERROR)printf("删除第%d个数据失败\n", j);elseprintf("删除第%d个的元素值为:%d\n", j, e);}printf("依次输出L的元素:");ListTraverse(&L);j = 5;ListDelete(&L, j, &e); /* 删除第5个数据 */printf("删除第%d个的元素值为:%d\n", j, e);printf("依次输出L的元素:");ListTraverse(&L);i = ClearList(&L);printf("\n清空L后:ListLength(L)=%d\n", ListLength(&L));CreateListHead(&L, 20);printf("整体创建L的元素(头插法):");ListTraverse(&L);i = ClearList(&L);printf("\n删除L后:ListLength(L)=%d\n", ListLength(&L));CreateListTail(&L, 20);printf("整体创建L的元素(尾插法):");ListTraverse(&L);ElemType ee = GetElemIPrior(&L, 5);printf("元素5的前驱是%d \n:", ee);
}

大话数据结构05: 双向链表相关推荐

  1. 《大话数据结构》3、4、5线性表、栈与队列、串

    第3章线性表 41 线性表:零个或多个数据元素的有限序列. 3.1开场白 42 门外家长都挤在大门口与门里的小孩子的井然有序,形成了鲜明对比.哎,有时大人的所作所为,其实还不如孩子. 3.2线性表的定 ...

  2. 《大话数据结构》读书笔记-线性表

    写在前面:本文仅供个人学习使用.<大话数据结构>通俗易懂,适合整体做笔记输出,构建体系.并且文中很多图片来源于该书. 文章目录 3.2 线性表的定义 3.3 线性表的抽象数据类型 3.4 ...

  3. 《大话数据结构》简体中文版勘误

    尽管已经很仔细的检查和审核,但错误还是没有能避免.以下的错误,有些是作者的笔误或者表述不清,有些是编辑审稿时不理解造成的错误,有些是美编改图时的错误,有些是印刷厂印刷时的错误.虽然出错的原因很多,但总 ...

  4. 《大话数据结构》读书笔记-树

    写在前面:本文仅供个人学习使用.<大话数据结构>通俗易懂,适合整体做笔记输出,构建体系.并且文中很多图片来源于该书,如有侵权,请联系删除. 文章目录 6.2 树的定义 6.2.1 结点分类 ...

  5. 大话数据结构读书笔记艾提拉总结 查找算法 和排序算法比较好 第1章数据结构绪论 1 第2章算法 17 第3章线性表 41 第4章栈与队列 87 第5章串 123 第6章树 149 第7章图 21

    大话数据结构读书笔记艾提拉总结 查找算法 和排序算法比较好 第1章数据结构绪论 1 第2章算法 17 第3章线性表 41 第4章栈与队列 87 第5章串 123 第6章树 149 第7章图 211 第 ...

  6. 《大话数据结构》1、2数据结构、算法

    大话数据结构 大话设计模式 head first设计模式 Java核心技术 卷1 深入理解Java虚拟机(JVM高级特性与最佳实践) 图解HTTP 大话数据结构 数据结构介绍, 算法推导大O阶的方法, ...

  7. 《大话数据结构》框要

    随着复习的不断深入,发现数据结构的基础并不牢固,找到了一本相对经典的数据结构书籍--大话数据结构,网上的资源很多,很容易找到PDF版,下面对这本书的知识点做整体性的梳理,主要为之后再回头看找到方向. ...

  8. 大话数据结构-迪杰斯特拉算法(Dijkstra)和弗洛伊德算法(Floyd)

    6 最短路径   最短路径,对于图来说,是两顶点之间经过的边数最少的路径:对于网来说,是指两顶点之间经过的边上权值之和最小的路径.路径上第一个顶点为源点,最后一个顶点是终点. 6.1 迪杰斯特拉(Di ...

  9. 大话数据结构-栈与队列

    文章知识点来至于大话数据结构里边章节知识, 这篇主要介绍栈与队列在计算机中存储形式, 以及在某些算法领域中对栈和队列的相关应用.章节最后介绍了著名的逆波兰表达式, 以及通过算法来实现该表达式的运算过程 ...

最新文章

  1. 如何创建一个最小的区块链
  2. 怎样实现关闭connection时自动关闭Statement和ResultSet
  3. 看看C# 6.0中那些语法糖都干了些什么(上篇)
  4. 手动创建线程池 效果会更好_创建更好的,可访问的焦点效果
  5. 微软的.NET Core开始支持Raspberry Pi 3
  6. 借助Java 8和lambdas,可以一起使用AssertJ和Awaitility
  7. Android Service被系统回收的解决方法
  8. 华硕飞马3S,日常使用续航测试
  9. DBeaver 导出EXCEL文件
  10. 杨辉三角形(简明易懂)
  11. 发电厂计算机监控课,那比水利发电厂监控系统课件.ppt
  12. 稀疏光流python_《稀》字意思读音、组词解释及笔画数 - 新华字典 - 911查询
  13. 美化牙齿的几大方式,护牙剂省钱省力
  14. 钉钉页面跳转_钉钉统一跳转协议
  15. 小米html查看器 联网,小米摄像机如何连接无线路由器通过手机查看
  16. EAP通讯基础之SECS/GEM/GEM300mm
  17. golang 打桩,mock 数据怎么玩?
  18. Android安卓麻将识别源码Demo( 三)
  19. 适合Web开发人员的10个CSS代码生成器
  20. 省钱技巧有那些?省钱小分队

热门文章

  1. Timus 1018 树形DP
  2. 英特尔nuc能代替主机吗_终于圆满了!最新款的Intel NUC迷你主机上线
  3. PHP中的错误控制运算符
  4. Springboot注册Servlet
  5. 前端用Sass实现星级评定效果,简单快捷实现星级切换。
  6. 3亿Docker容器部署的挑战及应对方案
  7. 模式识别两种方法:知识和数据
  8. ZHS16GBK的数据库导入到字符集为AL32UTF8的数据库
  9. [Array]217.Contains Duplicate
  10. nagios错误: 无法打开要更新的命令文件