一、单向循环链表

(一)概念

  • 将单链表尾节点的指针域置为起始节点的地址,而不再是NULL,这样从表中任一节点出发,均可访问到链表中的所有节点

(二)单向循环链表的结构图

(三)程序封装单向循环链表

1.创建链表类和节点类

 //节点的结构class Cnode {constructor(data) {this.data = datathis.next = null}}
//链表的结构class CycleLinkList {constructor() {this.head = nullthis.length = 0}}

2.单向循环链表的操作(方法)

1)append() 向链表尾部添加一个节点

append(ele) {let newnode = new Cnode(ele)if(this.head==null){//空链表this.head=newnodenewnode.next=this.head }else{//非空链表//需要找到最后一个节点let current=this.headwhile(current.next!=this.head){current=current.next}//找到了current表示最后一个节点current.next=newnodenewnode.next=this.head}this.length++}

2)toString()  将链表中的数据连接为字符串

toString(){let current=this.head,index=0,str=""while(index<this.length){str+="-"+current.datacurrent=current.nextindex++}return str.slice(1)}

3)insert() 向链表中插入元素

 insert(position, ele) {if (position < 0 || position > this.length || Number.isInteger(position)) {return false}let newnode = new Cnode(ele)let current = this.head,index = 0if (position == 0) {//在头部插入if (this.length == 0) {//空链表this.head = newnodenewnode.next = this.head} else {//非空链表while (current.next != this.head) {current = current.next}newnode.next = this.headcurrent.next = newnodethis.head = newnode}this.length++} else if (position == this.length) {//在尾部插入this.append(ele)} else {//在中间插入while (index < position - 1) {current = current.nextindex++}newnode.next = current.nextcurrent.next = newnodethis.length++}}

4)removeAt() 移除在指定位置的元素

removeAt(position) {//判断位置是否合法(越界判断)if (position < 0 || position > this.length - 1 || !Number.isInteger(position)) {return false}//非空链表let current = this.head,index = 0if (position == 0) {//移除头部if (this.length == 1) {//只有一个节点this.head = null} else {//找到最后一个节点 最后一个节点的next指向新头部while (current.next != this.head) {current = current.next}this.head = this.head.nextcurrent.next = this.head}} else {//移除任意位置(包括末尾)while (index < position - 1) {current = current.nextindex++}current.next = current.next.next}this.length--}

5)indexOf() 查找指定元素

indexOf(ele) {let current = this.head,index = 0while (index < this.length) {if (current.data == ele) {return index} else {current = current.nextindex++}}return -1}

6)remove() 移除指定元素

remove(ele) {let index = this.indexOf(ele)this.removeAt(index)}

(四)完整代码&操作示例

        //节点的结构class Cnode {constructor(data) {this.data = datathis.next = null}}//链表的结构class CycleLinkList {constructor() {this.head = nullthis.length = 0}//1.append() 向链表尾部添加一个元素append(ele) {let newnode = new Cnode(ele)if (this.head == null) {//空链表this.head = newnodenewnode.next = this.head} else {//非空链表//需要找到最后一个节点 最后一个节点的next指向头结点let current = this.headwhile (current.next != this.head) {//继续往下找current = current.next}//找到了current表示最后一个节点current.next = newnodenewnode.next = this.head}this.length++}//2.toString()  将链表中的数据链接为字符串toString() {let current = this.head,index = 0,str = ""while (index < this.length) {str += "-" + current.datacurrent = current.nextindex++}return str.slice(1)}//3.向链表中插入元素insert(position, ele) {if (position < 0 || position > this.length || !Number.isInteger(position)) {return false}let newnode = new Cnode(ele)let current = this.head,index = 0if (position == 0) {//在头部插入if (this.length == 0) {//空链表this.head = newnodenewnode.next = this.head} else {//非空链表while (current.next != this.head) {current = current.next}newnode.next = this.headcurrent.next = newnodethis.head = newnode}this.length++} else if (position == this.length) {//在尾部插入this.append(ele)} else {//在中间插入while (index < position - 1) {current = current.nextindex++}newnode.next = current.nextcurrent.next = newnodethis.length++}}//4.移除在指定位置的元素removeAt(position) {//判断位置是否合法(越界判断)if (position < 0 || position > this.length - 1 || !Number.isInteger(position)) {return false}//非空链表let current = this.head,index = 0if (position == 0) {//移除头部if (this.length == 1) {//只有一个节点this.head = null} else {//找到最后一个节点 最后一个节点的next指向新头部while (current.next != this.head) {current = current.next}this.head = this.head.nextcurrent.next = this.head}} else {//移除任意位置(包括末尾)while (index < position - 1) {current = current.nextindex++}current.next = current.next.next}this.length--}//5.查找指定元素indexOf(ele) {let current = this.head,index = 0while (index < this.length) {if (current.data == ele) {return index} else {current = current.nextindex++}}return -1}//6.移除指定元素remove(ele) {let index = this.indexOf(ele)this.removeAt(index)}}let clist = new CycleLinkList()//链表操作//在末尾添加元素for (let i = 0; i < 9; i++) {clist.append(i)}console.log(clist.toString(),"添加了元素")//在指定位置插入元素clist.insert(3, "newnode")console.log(clist.toString(),"在3的位置插入了newnode")//移除指定位置的元素clist.removeAt(4)console.log(clist.toString(),"移除了第4个节点--3")//查找元素console.log(clist.indexOf(3),"查找3,已经被移除了所以返回-1")console.log(clist.indexOf(5),"存在,返回下标")//移除指定元素clist.remove(8)console.log(clist.toString(),"删除了8")

打印结果:

二、双向循环链表

(一)概念

  • 可以从两个方向进行遍历,可以利用中间的一个节点推出下一个节点和上一个节点

(二)双向循环链表的结构图

(三)程序封装双向循环链表

1.创建链表类和节点类

 //节点的结构class Dnode {constructor(data) {this.prev = null;this.data = data;this.next = null;}}
//链表的结构class DoubleCycleLinkList {constructor() {this.head = null;this.tail = null;this.length = 0}}

2.单向循环链表的操作(方法)

1)append() 向链表尾部添加一个节点

append(ele) {let newnode = new Dnode(ele);if (this.length == 0) { //空链表this.head = newnode;this.tail = newnode;newnode.prev = newnode;newnode.next = newnode; //自己连自己} else {//将新节点连接newnode.prev = this.tail; //新节点.prev = 尾节点newnode.next = this.head; //新节点的next指向头结点//断开原来的指向,重新指向新节点this.tail.next = newnode; //尾节点.next指向新节点this.head.prev = newnode; //头结点的prev指向新节点this.tail = newnode; //将尾节点指向新节点}this.length++;}

2)insert() 向链表中插入元素

insert(position, ele) {// 位置是否合法if (position < 0 || position > this.length || !Number.isInteger(position)) {return false}let newnode = new Dnode(ele);if (position == 0) {//在头部插入if (this.length == 0) { //空链表this.head = newnode;this.tail = newnode;newnode.prev = this.tailnewnode.next = this.head} else {//将新节点连接newnode.next = this.head; //新节点.next指向头节点newnode.prev = this.tail; //新节点的prev指向尾结点//断开原来的指向this.head.prev = newnode; //头节点.prev指向新节点this.tail.next = newnode //尾节点的next指向新节点this.head = newnode; //头节点指向新节点}this.length++} else if (position == this.length) {//在尾部插入this.append(ele)} else {//在中间任意位置let current = this.head,index = 0;while (index < position - 1) {current = current.next;index++;}// 1.将新节点连上去newnode.prev = current;newnode.next = current.next;// 2.断开原来的指向current.next = newnode;newnode.next.prev = newnode;this.length++;}}

3)removeAt() 移除在指定位置的元素

 removeAt(position) {//判断位置的合法性(越界判断)if (position < 0 || position > this.length - 1 || !Number.isInteger(position)) {return false}if (this.length == 0) {//空链表return} else {if (position == 0) {//移除头节点if (this.length == 1) {this.head = nullthis.tail = null} else {this.head = this.head.nextthis.tail.prev=this.headthis.head.prev = this.head}} else if (position == this.length - 1) {//移除尾结点this.tail = this.tail.prevthis.tail.next = this.headthis.head.prev=this.tail} else {//移除中间任意位置的节点let current = this.head,index = 0while (index < position - 1) {current = current.nextindex++}current.next = current.next.nextcurrent.next.prev = current}this.length--}}

4)indexOf() 查找指定元素

indexOf(ele) {let current = this.head,index = 0while (index < this.length) {if (current.data == ele) {return index} else {current = current.nextindex++}}return -1}

5)remove() 移除指定元素

remove(ele) {let index = this.indexOf(ele)this.removeAt(index)}

6)正向遍历

 forwardString() {let current = this.head,index = 0,str = "";while (index < this.length) {str += "-" + current.datacurrent = current.nextindex++}return str.slice(1)}

7)反向遍历

 reverseString() {let current = this.tail,index = this.length - 1,str = "";while (index >= 0) {str += "-" + current.datacurrent = current.previndex--}return str.slice(1)}

(四)完整代码&操作示例

        //节点的结构class Dnode {constructor(data) {this.prev = null;this.data = data;this.next = null;}}//链表的结构class DoubleCycleLinkList {constructor() {this.head = null;this.tail = null;this.length = 0}//1.在链表尾部添加元素append(ele) {let newnode = new Dnode(ele);if (this.length == 0) { //空链表this.head = newnode;this.tail = newnode;newnode.prev = newnode;newnode.next = newnode; //自己连自己} else {//将新节点连接newnode.prev = this.tail; //新节点.prev = 尾节点newnode.next = this.head; //新节点的next指向头结点//断开原来的指向,重新指向新节点this.tail.next = newnode; //尾节点.next指向新节点this.head.prev = newnode; //头结点的prev指向新节点this.tail = newnode; //将尾节点指向新节点}this.length++;}// 2.向链表指定位置插入元素insert(position, ele) {// 位置是否合法if (position < 0 || position > this.length || !Number.isInteger(position)) {return false}let newnode = new Dnode(ele);if (position == 0) {//在头部插入if (this.length == 0) { //空链表this.head = newnode;this.tail = newnode;newnode.prev = this.tailnewnode.next = this.head} else {//将新节点连接newnode.next = this.head; //新节点.next指向头节点newnode.prev = this.tail; //新节点的prev指向尾结点//断开原来的指向this.head.prev = newnode; //头节点.prev指向新节点this.tail.next = newnode //尾节点的next指向新节点this.head = newnode; //头节点指向新节点}this.length++} else if (position == this.length) {//在尾部插入this.append(ele)} else {//在中间任意位置let current = this.head,index = 0;while (index < position - 1) {current = current.next;index++;}// 1.将新节点连上去newnode.prev = current;newnode.next = current.next;// 2.断开原来的指向current.next = newnode;newnode.next.prev = newnode;this.length++;}}//3.移除指定位置的节点removeAt(position) {//判断位置的合法性(越界判断)if (position < 0 || position > this.length - 1 || !Number.isInteger(position)) {return false}if (this.length == 0) {//空链表return} else {if (position == 0) {//移除头节点if (this.length == 1) {this.head = nullthis.tail = null} else {this.head = this.head.nextthis.tail.prev=this.headthis.head.prev = this.head}} else if (position == this.length - 1) {//移除尾结点this.tail = this.tail.prevthis.tail.next = this.headthis.head.prev=this.tail} else {//移除中间任意位置的节点let current = this.head,index = 0while (index < position - 1) {current = current.nextindex++}current.next = current.next.nextcurrent.next.prev = current}this.length--}}//4.查找指定元素的位置indexOf(ele) {let current = this.head,index = 0while (index < this.length) {if (current.data == ele) {return index} else {current = current.nextindex++}}return -1}//5.移除指定元素remove(ele) {let index = this.indexOf(ele)this.removeAt(index)}//6.正向遍历forwardString() {let current = this.head,index = 0,str = "";while (index < this.length) {str += "-" + current.datacurrent = current.nextindex++}return str.slice(1)}//7.反向遍历reverseString() {let current = this.tail,index = this.length - 1,str = "";while (index >= 0) {str += "-" + current.datacurrent = current.previndex--}return str.slice(1)}}let clist = new DoubleCycleLinkList()//向链表尾部添加元素for (let i = 0; i < 9; i++) {clist.append(i)}console.log(clist.forwardString(),"向链表尾部添加元素后的链表")//向链表中的3的位置插入元素clist.insert(3,"newnode")console.log(clist.forwardString(),"插入元素后的链表")//移除指定位置的元素clist.removeAt(5)console.log(clist.forwardString(),"移除位置为5的元素(4)的链表")//查找指定元素console.log(clist.indexOf(4),"4已经被移除,不存在返回-1")console.log(clist.indexOf(6),"6存在返回下标")//移除指定元素clist.remove(8)console.log(clist.reverseString(),"移除元素8后的反向遍历的链表")

打印结果:

数据结构——单向循环链表双向循环链表相关推荐

  1. 初阶数据结构之带头+双向+循环链表增删查实现(三)

    文章目录 @[TOC](文章目录) 前言 一.带头双向循环链表的初始化 1.1带头双向循环链表的结构体定义 1.2初始化代码的实现 二.带头+双向+循环链表的增功能实现 2.1头插代码的实现 2.2尾 ...

  2. 数据结构:带头双向循环链表——增加、删除、查找、修改,详细解析

    读者可以先阅读这一篇:数据结构--单链表的增加.删除.查找.修改,详细解析_昵称就是昵称吧的博客-CSDN博客,可以更好的理解带头双向循环链表. 目录 一.带头双向循环链表的处理和介绍 1.带头双向循 ...

  3. 【数据结构】带头双向循环链表的增删查改(C语言实现)

    文章目录 前言 一.什么是带头双向循环链表 二.带头双向循环链表的实现 1.结构的定义 2.链表的初始化 3.开辟新节点 4.在头部插入数据 5.在尾部插入数据 6.查找数据 7.在pos位置之前插入 ...

  4. 数据结构基础(12) --双向循环链表的设计与实现

    双向链表的操作特点: (1) "查询" 和单链表相同; (2)"插入" 和"删除"时需要同时修改两个方向上的指针. 但是对于双向循环链表则在 ...

  5. 【数据结构】带头双向循环链表

    各位读者们好久不见了,咋们接着上一期链表来,今天来实现一下链表最难的结构,同时也是实现起来最简单的结构--带头双向循环链表.话不多说,进入主题 文章目录 前言 实现带头双向循环链表 DList.h头文 ...

  6. 【数据结构】带头+双向+循环链表的 增,删,查,改 的实现

    #include <iostream>using namespace std;int main() {typedef int ListType;typedef struct ListNod ...

  7. 数据结构——带头结点双向循环链表

    相比较与单链表,双向循环链表每个结点多了一个prev指针域,用于指向该结点的前驱,并且链表的头尾结点也用指针域相连.所以对于带头结点的双向循环链表的判空条件为head->next=head;除此 ...

  8. 【数据结构】带头+双向+循环链表(增、删、查、改)的实现_【附源码、图片示例】_ [初阶篇_ 复习专用]

  9. 【数据结构-C】双向循环链表基本操作及图解分析

    目录

  10. 《恋上数据结构第1季》单向循环链表、双向循环链表以及约瑟夫环问题

    循环链表(CircleList) 链表的接口设计 单向循环链表 单向循环链表完整源码 双向循环链表 双向循环链表完整源码 双向循环链表解决约瑟夫环问题 如何发挥循环链表的最大威力? 静态链表 数据结构 ...

最新文章

  1. iis 7 php_Windows server 2008 下基于IIS7配置php7.2运行环境
  2. 我在 SUN TECH DAY
  3. crtsiii型无砟轨道板_为什么高铁轨道不像普快列车轨道那样铺碎石?
  4. 怎么查看python是否安装好了pyinstaller_Python PyInstaller安装和使用教程(详解版)...
  5. nssl1210-质数【素数筛】
  6. Mybatis分页中遇到的坑3
  7. 微服务主见传递ID还是json_后台管理系统之微服务搭建
  8. Python学习_4_if_while_for
  9. 漫威蜘蛛侠Mac动态壁纸
  10. php foreach 传值还是传引用
  11. 【图像隐写】基于matlab GUI DWT+DCT+SVD数字水印嵌入提取攻击(带面板)【含Matlab源码 1664期】
  12. echarts 加载优化_【第1615期】React Native 图表性能优化实践
  13. To C、To G、To B,数字化转型
  14. SDN技术的十个关键因素
  15. 【JavaSE基础 】Eclipse教程
  16. autocomplete触发事件_如何防止onSelect事件在DevBridge jQuery Autocomplete中触发两次
  17. 哪些人需要发表期刊论文
  18. 整合营销成功案例-卫龙辣条的逆袭路
  19. python 使用while循环输出*组成的菱形_python实现while循环打印星星的四种形状
  20. 看完一本青春小说后的感悟。

热门文章

  1. Anaconda3安装及opencv配置
  2. 离散数学 - 04 图论
  3. Android11安装谷歌,Android 11正式版
  4. 学习笔记(12):Google开发专家带你学 AI:入门到实战(Keras/Tensorflow)(附源码)-深度学习“四件套”:数据、模型、损失函数与优化器
  5. 上海学计算机编程,上海自学计算机编程入门
  6. Unity使用Remote直接在手机上调试游戏
  7. Uubuntu20.04配置openpose
  8. android接收红外传感器发送的脉冲信号,Arduino红外传感器-IR Receiver Module红外接收模块...
  9. 华为盒子EC6108V9/V9U/V92/V97-HI3798MV100(免拆机-通刷固件)卡刷固件及教程
  10. 6. lcd驱动1-硬件原理