当前位置: 首页 > news >正文

数据结构与算法-循环链表、双向链表

我们这里接着上一篇单链表继续往下深入学习循环链表、双向链表

链表

  • 🎈3.循环链表
    • 🔭3.1循环链表的概念
    • 🔭3.2循环链表的基本操作
      • 🔎3.2.1创建空表
      • 🔎3.2.2插入操作
      • 🔎3.2.3删除操作
  • 🎈4.双向链表
    • 🔭4.1类型定义
    • 🔭4.2头插法创建双向链表
    • 🔭4.3尾插法创建双向链表
    • 🔭4.4插入操作
    • 🔭4.5删除操作

🎈3.循环链表

🔭3.1循环链表的概念

循环链表是一种头尾相接的链表。它的特点是由链表的尾结点的指针域不为空,而是指向头结点,整个链表形成一个环。由此,从表中任何一个结点出发均可找到链表的其他结点。在单链表中,将终端结点的指针域NULL改为指向表头结点的或开始结点,就得到了单链形式的循环链表,并简称为单循环链表。与单链表一样,为了使空表和非空表处理一致,循环链表也可以设置一个头结点。空循环链表和非空循环链表如图所示:
在这里插入图片描述

🏆单循环链表的基本算法与非循环单链表的算法基本相同,只需对表尾的判断条件做出修改即可,例如,判断表尾结点的条件为:p->next==head.

🔭3.2循环链表的基本操作

在这里插入图片描述

🔎对于上述这个非空单循环链表:

✅当我们用头指针表示单循环链表:找a1的时间复杂度为:O(1),找an的时间复杂度为:O(n).
✅当我们用尾指针表示单循环链表:找a1的时间复杂度为:O(1)(R->next->next),找an的时间复杂度为:O(1)(R).
🏆因此,我们通常采用尾指针的单循环链表。

🔎3.2.1创建空表

void InitList(LNode *&rear)
{rear = new LNode;//创建头结点rear->next = rear;
}

🔎3.2.2插入操作

void InsertList(LNode *&rear, ElemType e)
{//在表尾插入一个结点LNode* s = new LNode;s->data = e;s->next = rear->next;rear->next = s;rear = s;
}

🔎3.2.3删除操作

void Delete(LNode*& rear, ElemType& e)
{//删除链表的第一个结点if (rear->next == rear)return;//空表,无法删除元素LNode* p = rear->next->next;//p指向第一个元素e = p->data;rear->next->next = p->next;if (p == rear)rear = p->next;delete p;
}

🎈4.双向链表

双向链表是在单链表的每一个结点里再增加一个指向其直接前驱的指针域prior,这样形成的链表有两个方向不同的链,故称为双向链表。
在这里插入图片描述

🔭4.1类型定义

typedef int ElemType;
typedef struct DNode
{ElemType data;//存放数据元素信息DNode* next;//存放后继结点的地址信息DNode* prior;//存放前驱结点的地址信息
}DNode;

🔭4.2头插法创建双向链表

void CreatList_h(DNode*& head, int n)
{DNode* s;head = new DNode;//创建头结点head->next = head->prior = NULL;//前后指针置为NULLint i = 0;for (i = 0; i < n; i++)//循环创建数据结点{s = new DNode;cin >> s->data;//读入数据s->next = head->next;//连接s的两个指针s->prior = head;if (head->next != NULL)head->next->prior = s;head->next = s;}
}

🔭4.3尾插法创建双向链表

void CreatList_t(DNode*& head, int n)
{DNode* s, * rear;head = new DNode;//创建头结点head->next = head->prior = NULL;//前后指针置为NULLrear = head;int i = 0;for (i = 0; i < n; i++)//循环创建数据结点{s = new DNode;//创建新的数据结点cin >> s->data;//读入数据s->prior = rear;//s插在rear后面rear->next = s;rear = s;}rear->next = NULL;
}

🔭4.4插入操作

在这里插入图片描述

void InsertDlist(DNode*& head, int i, ElemType e)
{int j = 0;//计数器DNode* p = head,*s;while (p && j < i - 1){p = p->next;j++;}if (!p || j > i - 1)return;else//找到第i-1个结点{s = new DNode;s->data = e;s->next = p->next;//p结点后插入s结点s->prior = p;if (p->next)p->next->prior = s;}
}

🔭4.5删除操作

DeleteDList()函数在双向链表中,结点的删除操作涉及前驱结点和后继结点两个指针域的变化。设在双向链表中删除指针p所指向结点的后继结点q,需要修改两个指针域,删除操作指针变化过程如图所示:
在这里插入图片描述

void DeleteDList(DNode*& head, int i, ElemType& e)
{int j = 0;//计数器DNode* p = head, * q;while (p->next && j < i - 1){p = p->next;j++;}if (!(p->next) || j > i - 1)return;else{q = p->next;e = q->data;p->next = q->next;//删除q所指结点if (q->next != NULL)q->next->prior = p;delete q;}
}

好啦,关于循环链表和双向链表的知识点到这里就结束啦,后期会继续更新数据结构与算法的相关知识,欢迎大家持续关注、点赞和评论!❤️❤️❤️

http://www.lryc.cn/news/184662.html

相关文章:

  • javascript中依次输出元素并不断循环实现echarts柱图动画效果
  • 互联网Java工程师面试题·Memcached篇·第一弹
  • git 详解-提升篇
  • RPA的安全风险及应对策略
  • 数据结构与算法--贪心算法
  • 【Unity3D】UGUI物体世界坐标转屏幕坐标问题
  • 代码随想录二刷day51
  • 接口自动化测试框架(pytest+allure+aiohttp+ 用例自动生成)
  • [Python入门教程]01 Python开发环境搭建
  • 第四章:最新版零基础学习 PYTHON 教程(第二节 - Python 数据类型—Python 字符串、列表、元组、迭代)
  • react框架与vue框架的区别
  • C++_pen_静态与常量
  • ToDoList使用自定义事件传值
  • 基于SSM的家庭财务管理系统设计与实现
  • OpenHarmony Trace的使用
  • 文件上传笔记
  • 计算机网络 第三章数据链路层
  • 浅析如何在抖音快速通过新手期并积累粉丝
  • 英文论文实例赏析——如何写前言?
  • springBoot -md
  • 从0开始学go第五天
  • 大厂技术面试中的手撕代码应该如何准备?
  • 阿里影业+大麦,开启大文娱新纪元?
  • springboot整合mybatis入门程序
  • 【BI看板】Superset2.0+图表二次开发初探
  • 微服务学习--1入门
  • docker系列6:docker安装redis
  • 计算机网络(三):数据链路层
  • 【计算机组成 课程笔记】7.2 DRAM和SRAM
  • 1802_在Linux系统上开发ARM单机片机嵌入式软件