上篇博客分析了单链表:数据结构-01-链表数据结构之单链表,这篇博客将分析链表的其他几种常见形式
本文中的所有代码均在github上的项目中:List_DataStructure

双链表

双链表也叫双向链表,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。
双链表是最常用的一种链表形式,实际应用中双链表一般会被创建成环状形式,即头尾结点分别存储对方的地址,链表形成了一个封闭的环。

1.双链表的基本结构:

双链表的开始是一个头指针,每个结点中都有指向下一结点及上一结点的地址

双链表的C++实现:

1.双链表的结点类

template<typename Type> class DoubleLinkedList;template<typename Type>
class DoubleLinkedListNode
{
private:friend typename DoubleLinkedList<Type>;//构造函数和析构函数DoubleLinkedListNode() :pprior(nullptr), pnext(nullptr) {}DoubleLinkedListNode(const Type item, DoubleLinkedListNode<Type> * next = nullptr, DoubleLinkedListNode<Type> * prior = nullptr):data(item), pnext(next), pprior(prior) {}~DoubleLinkedListNode() {pprior = nullptr;pnext = nullptr;}
public://单链表节点对象的基本方法Type GetData();
private:Type data;DoubleLinkedListNode * pprior;DoubleLinkedListNode * pnext;
};

2.双链表类

template <typename Type>
class DoubleLinkedList
{
public:DoubleLinkedList() :head(new DoubleLinkedListNode<Type>()) {head->pprior = head;head->pnext = head;}~DoubleLinkedList() {MakeEmpty();delete head;}//对双链表的基本操void MakeEmpty();void Insert(Type item, int i = 0);void Remove(int i = 0);void RemoveAll(Type item);//返回双聊表的基本信息int length();Type Get(int i);//查找和排序DoubleLinkedListNode<Type> * SequentialSearch(Type item);//基础功能void Print();
private://链表的头节点是私有的SingleLinkedListNode<Type> *head;
};

2.双链表的初始化:

双链表的空参构造函数:

DoubleLinkedList() :head(new DoubleLinkedListNode<Type>()) {head->pprior = head;head->pnext = head;}

根据双链表在创建时调用空参构造函数,创建了一个结点对象,即链表的头结点,头结点的上一结点的地址pprior 和下一节点的地址pnext 存储均存储头结点地址

3.向双链表中插入数据:

向双向循环链表中插入数据时应注意链表是封闭环状,所以使用循环或递归时要注意结束条件

//向双链表中插入元素
template <typename Type>
void DoubleLinkedList<Type>::Insert(Type item, int i = 0) {if (i < 0){cout << "请输入一个大于0的数" << endl;}DoubleLinkedListNode<Type> *pmove = head;DoubleLinkedListNode<Type> *pnode = new DoubleLinkedListNode<Type>(item);for (int j = 0; j < i; j++){pmove = pmove->pnext;if (pmove == head) {cout << "i值越界,链表没有那么长!" << endl;//结束程序exit(1);}}pnode->pnext = pmove->pnext;pnode->pnext = pmove;pmove->pnext = pnode;pnode->pnext->pprior = pnode;
}

1.初始化一个结点类的对象pnode
2.创建一个结点类型指针pmove,用于遍历找到插入点位置
3.循环找到插入点位置,若pmove == head说明指定的插入点位置超过了链表长度
4.执行插入

    pnode->pnext = pmove->pnext; //步骤一pnode->pprior= pmove; //步骤二pmove->pnext = pnode; //步骤三pnode->pnext->pprior = pnode; //步骤四

如下图所示,pnode为x,即待插入节点
pmove指向节点ai
步骤一:将ai+1的地址(即ai->pnext也是pmove->pnext)赋值给pnode的下一结点地址pnext
步骤二:将ai的地址(即pmove)赋值给pnode的上一结点地址pprior
步骤三:将pnode的地址赋值给ai(即pmove)的下一结点地址pnext
步骤四:将pnode的地址赋值给ai+1(即ai+1->pprior也是pnode->pnext->pprior)的上一结点地址pprior

4.删除双链表中的数据:

//删除双链表中的元素
template <typename Type>
void DoubleLinkedList<Type>::Remove(int i = 0) {if (i < 0) {cout << "请输入一个大于0的数" << endl;}DoubleLinkedListNode<Type> *pmove = head, *pdel;for (int j = 0; j < i; j++) {pmove = pmove->pnext;//当pmove == head,说明pmove移动了一个链表长度,又绕回了链表起始点if (pmove == head) {cout << "i值越界,链表没有那么长!" << endl;//结束程序exit(1);}}pdel = pmove;pmove->pprior->pnext = pdel->pnext;pmove->pnext->pprior = pdel->pprior;Type temp = pdel->data;cout << "删除的结点中保存的数据是:" << temp << endl;delete pdel;
}

删除链表的结点必须要两个指向待删除结点的指针配合
1.创建两个结点类型指针pmove,和pdel,pmove用于遍历找到待删除结点
2.循环找到插入点位置,若pmove == head说明指定的待删除结点位置超过了链表长度
3.执行删除

    pdel = pmove; //步骤一pmove->pprior->pnext = pdel->pnext; //步骤二pmove->pnext->pprior = pdel->pprior; //步骤三

如下图所示,pmove指向节点ai,即待删除节点
步骤一:通过赋值使pdel指向节点ai
步骤二:将ai+1的地址赋给ai-1的下一结点地址pnext(即ai-1->pnext也是pmove->pprior->pnext)
步骤三:将ai-1的地址赋给ai+1的上一结点地址pprior(即ai+1->pprior也是pmove->pnext->pprior)

数据结构-02-链表数据结构之双链表和循环链表相关推荐

  1. 【数据结构】线性表的链式表示-循环单链表、循环双链表、静态链表

    循环单链表 从任何一个结点出发都能访问到链表的每一个元素 判空条件不是头节点的后继指针是否为空,而是它是否等于头指针 有时对单链表常做的操作实在表头和表尾进行的,此时可对循环单链表不设头指针而仅设尾指 ...

  2. Linux内核链表之共享双链表

    说明 共享双链表意义在于,可以用一套函数维护不同数据类型的双链表 准备 定义双链表 #include <iostream> #include <string>using nam ...

  3. 链表之删除双链表倒数第K个节点

    链表之删除双链表倒数第K个节点 题目: 链表之删除双链表倒数第K个节点   思路: 之前写过 http://blog.csdn.net/u011068702/article/details/50280 ...

  4. 数据结构思维 第五章 双链表

    第五章 双链表 原文:Chapter 5 Doubly-linked list 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 本章回顾了上一个练习的结果,并介绍了List接口的 ...

  5. java中的列表栈链表_Java数据结构(栈,队列,双链表)

    (1)栈package ChapterOne; public class Stack { //栈数组 long stackArr[]; //栈的大小 int maxSize; //栈的顶部 int t ...

  6. (王道408考研数据结构)第二章线性表-第三节3:循环单链表和循环双链表

    文章目录 一:循环链表定义 二:循环单链表 三:循环双链表 一:循环链表定义 循环链表:规定好头尾结点的指向形成成环状 循环单链表:其尾节点的next指针由原本的空改为指向头结点 循环双链表:其尾节点 ...

  7. 数据结构 2-3-2 线性表的双链表实现

    一.概念 单链表实现线性表时,在增删节点时的确很方便,但是在访问某个节点的前驱节点时,由于其内部只有从前驱指向后继的指针,所以在这种情况下只能从头遍历.为了解决这个问题,引入了双链表,即在每个节点中, ...

  8. 数据结构与算法 完整版双链表

    上一篇单链表博主已经讲的很详细了,相信掌握单链表的朋友搞定双链表并不困难,所以博主就之给出代码了,如果实在感觉理解困难可以留言,博主会加gif的 #include<stdio.h> #in ...

  9. Algorithms_基础数据结构(02)_线性表之链表_单向链表

    文章目录 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 约瑟夫问题 顺序表VS 链表 链表的定义 链表的特点 常见的链表结 单向链表 单向链表的查找 单向链表的插入 头插 尾部插入 中间 ...

  10. leetcode142. 环形链表 II(暴力+双链表)

    一:题目 二:思路 1.双指针 快慢指针(快指针一次一个结点,慢指针一次两个结点) 2.如果有环的话,那么快慢指针肯定会相遇 3.那么相遇的地点一定在环中 因为如果没有环的话慢指针是永远追不到快指针的 ...

最新文章

  1. 20154312曾林 - Exp1 PC平台逆向破解
  2. 【java】java反射机制,动态获取对象的属性和对应的参数值,并属性按照字典序排序,Field.setAccessible()方法的说明【可用于微信支付 签名生成】...
  3. HDU4846Task treap + 贪心
  4. SQLSERVER使用CLR Stored Procedure导出数据到Excel
  5. 基于谱减法的声音去噪
  6. 四级计算机基础知识,全国计算机等级考试四级通关攻略
  7. pku 1925 Spiderman DP
  8. 详解Objective-C的meta-class
  9. 构造函数 构造代码块_构造函数必须没有代码
  10. [javaME]摩托罗拉V300-V500-V600同时播放音乐的讲究
  11. 测试 软通动力软件测试机试_5000字长文,计算机保研机试介绍及准备策略!高分过过过!...
  12. python 抓取搜狗微信出现的问题,求大神解决
  13. [团队项目]典型用户 - 场景(用户故事) - 任务 - 具体工作流程
  14. fatal error: krb5.h: 没有那个文件或目录
  15. python必背100源代码-python 100例 (持续更新)
  16. 使用JMeter进行接口压力测试
  17. 声纹识别之Alize入门教程(四):matlab代码读取Spro工具提取的mfcc特征
  18. win10 ISO文件下载
  19. 一个人一个微博、一个App一个故事:通过微博草根账号做英语学习App的“爱卡微口语”获晨脉创投天使投资
  20. 关于计算机未来理想,坚持理想向往未来的励志说说

热门文章

  1. 高级python_高级Python功能
  2. 计算机硬件无法启动不能读取文件,修复Windows出现的“文件或目录已损坏且无法读取”问题...
  3. Java编程:获取输入的三种方法
  4. Javascript:各种定位clientX、pageY、screenX、offsetY区别
  5. log explorer for sql 不存在或访问被拒绝_原创干货 | 未授权访问漏洞批量化
  6. 论文阅读-可变形卷积v2: More Deformable, Better Results
  7. 多GPU环境运行实验的一点经验
  8. ID3、C4.5、CART决策树算法解析(关键内容讲解)
  9. yolov3中如何进行聚类得到anchor box的
  10. Introducing to Spring Framework