数据结构-02-链表数据结构之双链表和循环链表
上篇博客分析了单链表:数据结构-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-链表数据结构之双链表和循环链表相关推荐
- 【数据结构】线性表的链式表示-循环单链表、循环双链表、静态链表
循环单链表 从任何一个结点出发都能访问到链表的每一个元素 判空条件不是头节点的后继指针是否为空,而是它是否等于头指针 有时对单链表常做的操作实在表头和表尾进行的,此时可对循环单链表不设头指针而仅设尾指 ...
- Linux内核链表之共享双链表
说明 共享双链表意义在于,可以用一套函数维护不同数据类型的双链表 准备 定义双链表 #include <iostream> #include <string>using nam ...
- 链表之删除双链表倒数第K个节点
链表之删除双链表倒数第K个节点 题目: 链表之删除双链表倒数第K个节点 思路: 之前写过 http://blog.csdn.net/u011068702/article/details/50280 ...
- 数据结构思维 第五章 双链表
第五章 双链表 原文:Chapter 5 Doubly-linked list 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 本章回顾了上一个练习的结果,并介绍了List接口的 ...
- java中的列表栈链表_Java数据结构(栈,队列,双链表)
(1)栈package ChapterOne; public class Stack { //栈数组 long stackArr[]; //栈的大小 int maxSize; //栈的顶部 int t ...
- (王道408考研数据结构)第二章线性表-第三节3:循环单链表和循环双链表
文章目录 一:循环链表定义 二:循环单链表 三:循环双链表 一:循环链表定义 循环链表:规定好头尾结点的指向形成成环状 循环单链表:其尾节点的next指针由原本的空改为指向头结点 循环双链表:其尾节点 ...
- 数据结构 2-3-2 线性表的双链表实现
一.概念 单链表实现线性表时,在增删节点时的确很方便,但是在访问某个节点的前驱节点时,由于其内部只有从前驱指向后继的指针,所以在这种情况下只能从头遍历.为了解决这个问题,引入了双链表,即在每个节点中, ...
- 数据结构与算法 完整版双链表
上一篇单链表博主已经讲的很详细了,相信掌握单链表的朋友搞定双链表并不困难,所以博主就之给出代码了,如果实在感觉理解困难可以留言,博主会加gif的 #include<stdio.h> #in ...
- Algorithms_基础数据结构(02)_线性表之链表_单向链表
文章目录 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 约瑟夫问题 顺序表VS 链表 链表的定义 链表的特点 常见的链表结 单向链表 单向链表的查找 单向链表的插入 头插 尾部插入 中间 ...
- leetcode142. 环形链表 II(暴力+双链表)
一:题目 二:思路 1.双指针 快慢指针(快指针一次一个结点,慢指针一次两个结点) 2.如果有环的话,那么快慢指针肯定会相遇 3.那么相遇的地点一定在环中 因为如果没有环的话慢指针是永远追不到快指针的 ...
最新文章
- 20154312曾林 - Exp1 PC平台逆向破解
- 【java】java反射机制,动态获取对象的属性和对应的参数值,并属性按照字典序排序,Field.setAccessible()方法的说明【可用于微信支付 签名生成】...
- HDU4846Task treap + 贪心
- SQLSERVER使用CLR Stored Procedure导出数据到Excel
- 基于谱减法的声音去噪
- 四级计算机基础知识,全国计算机等级考试四级通关攻略
- pku 1925 Spiderman DP
- 详解Objective-C的meta-class
- 构造函数 构造代码块_构造函数必须没有代码
- [javaME]摩托罗拉V300-V500-V600同时播放音乐的讲究
- 测试 软通动力软件测试机试_5000字长文,计算机保研机试介绍及准备策略!高分过过过!...
- python 抓取搜狗微信出现的问题,求大神解决
- [团队项目]典型用户 - 场景(用户故事) - 任务 - 具体工作流程
- fatal error: krb5.h: 没有那个文件或目录
- python必背100源代码-python 100例 (持续更新)
- 使用JMeter进行接口压力测试
- 声纹识别之Alize入门教程(四):matlab代码读取Spro工具提取的mfcc特征
- win10 ISO文件下载
- 一个人一个微博、一个App一个故事:通过微博草根账号做英语学习App的“爱卡微口语”获晨脉创投天使投资
- 关于计算机未来理想,坚持理想向往未来的励志说说
热门文章
- 高级python_高级Python功能
- 计算机硬件无法启动不能读取文件,修复Windows出现的“文件或目录已损坏且无法读取”问题...
- Java编程:获取输入的三种方法
- Javascript:各种定位clientX、pageY、screenX、offsetY区别
- log explorer for sql 不存在或访问被拒绝_原创干货 | 未授权访问漏洞批量化
- 论文阅读-可变形卷积v2: More Deformable, Better Results
- 多GPU环境运行实验的一点经验
- ID3、C4.5、CART决策树算法解析(关键内容讲解)
- yolov3中如何进行聚类得到anchor box的
- Introducing to Spring Framework