双向循环链表

关于双向循环链表可以先阅读这篇文章这里就不再赘述:双向链表(DoubleLinkList)

Node

template<typename T>
class Node {
public:
T e;
Node *prev;
Node *next; Node() : e(0), prev(nullptr), next(nullptr) {} Node(const T &E) : e(E), prev(nullptr), next(nullptr) {} Node(const T &E, Node<T> *Prev, Node<T> *Next) : e(E), prev(Prev), next(Next) {}
};

构造函数

DoubleLoopLinkList() : size(0) {
//看图得:前驱后继都指向虚拟头节点
dummyHead = new Node<T>(0, dummyHead, dummyHead);
}

添加

头添加

    void addFirst(const T &e) {
dummyHead->next = new Node<T>(e, dummyHead, dummyHead->next);
dummyHead->next->next->prev = dummyHead->next;
++size;
}

指定节点添加

void add(const int index, const T &e) {
assert(index >= 0 && index <= size);
Node<T> *prevNode = dummyHead;
for (int i = 0; i < index; ++i) {
prevNode = prevNode->next;
}
prevNode->next = new Node<T>(e, prevNode, prevNode->next);
prevNode->next->next->prev = prevNode->prev;
++size;
}

尾添加


void addLast(const T &e) {
dummyHead->prev = new Node<T>(e, dummyHead->prev, dummyHead);
dummyHead->prev->prev->next = dummyHead->prev;
++size;
}

删除

头删除

T removeFirst() {
remove(0);
}

指定节点删除

T remove(int index) {
assert(index >= 0 && index < size);
Node<T> *prevNode = dummyHead;
for (int i = 0; i < index; ++i) {
prevNode = prevNode->next;
}
Node<T> *retNode = prevNode->next;
prevNode->next = retNode->next;
retNode->next->prev = retNode->prev;
retNode->next = nullptr;
retNode->prev = nullptr;
--size;
T temp = retNode->e;
delete retNode;
retNode = nullptr;
return temp;
}

尾删除

T removeLast() {
Node<T> *retNode = dummyHead->prev;
T temp = retNode->e;
dummyHead->prev = retNode->prev;
retNode->prev->next = dummyHead;
retNode->next = nullptr;
retNode->prev = nullptr;
delete retNode;
retNode = nullptr;
--size;
return temp;
}

Code

//
// Created by cheng on 2021/7/5.
// #ifndef LINKEDLIST_DOUBLELOOPLINKLIST_H
#define LINKEDLIST_DOUBLELOOPLINKLIST_H #include <assert.h> template<typename T>
class Node {
public:
T e;
Node *prev;
Node *next; Node() : e(0), prev(nullptr), next(nullptr) {} Node(const T &E) : e(E), prev(nullptr), next(nullptr) {} Node(const T &E, Node<T> *Prev, Node<T> *Next) : e(E), prev(Prev), next(Next) {}
}; template<typename T>
class DoubleLoopLinkList {
public:
DoubleLoopLinkList() : size(0) {
dummyHead = new Node<T>(0, dummyHead, dummyHead);
} constexpr int getSize() const {
return size;
} constexpr bool isEmpty() const {
return size == 0;
} void add(const int index, const T &e) {
assert(index >= 0 && index <= size);
Node<T> *prevNode = dummyHead;
for (int i = 0; i < index; ++i) {
prevNode = prevNode->next;
}
prevNode->next = new Node<T>(e, prevNode, prevNode->next);
prevNode->next->next->prev = prevNode->prev;
++size;
} void addFirst(const T &e) {
dummyHead->next = new Node<T>(e, dummyHead, dummyHead->next);
dummyHead->next->next->prev = dummyHead->next;
++size;
} void addLast(const T &e) {
dummyHead->prev = new Node<T>(e, dummyHead->prev, dummyHead);
dummyHead->prev->prev->next = dummyHead->prev;
++size;
} void set(const int index, const T &e) {
assert(index >= 0 && index < size);
Node<T> *cur = dummyHead->next;
for (int i = 0; i < index; ++i) {
cur = cur->next;
}
cur->e = e;
} void setFirst(const T &e) {
assert(!isEmpty());
dummyHead->next->e = e;
} void setLast(const T &e) {
assert(!isEmpty());
dummyHead->prev->e = e;
} bool contains(const T &e) const {
Node<T> *cur = dummyHead->next;
while (cur != dummyHead) {
if (cur->e = e) {
return true;
}
cur = cur->next;
}
return false;
} T get(const int index) const {
assert(index >= 0 && index < size);
Node<T> *cur = dummyHead->next;
for (int i = 0; i < index; ++i) {
cur = cur->next;
}
return cur->e;
} T getFirst() const {
assert(!isEmpty());
return dummyHead->next->e;
} T getLast() const {
assert(!isEmpty());
return dummyHead->prev->e;
} T remove(int index) {
assert(index >= 0 && index < size);
Node<T> *prevNode = dummyHead;
for (int i = 0; i < index; ++i) {
prevNode = prevNode->next;
}
Node<T> *retNode = prevNode->next;
prevNode->next = retNode->next;
retNode->next->prev = retNode->prev;
retNode->next = nullptr;
retNode->prev = nullptr;
--size;
T temp = retNode->e;
delete retNode;
retNode = nullptr;
return temp;
} T removeFirst() {
remove(0);
} T removeLast() {
Node<T> *retNode = dummyHead->prev;
T temp = retNode->e;
dummyHead->prev = retNode->prev;
retNode->prev->next = dummyHead;
retNode->next = nullptr;
retNode->prev = nullptr;
delete retNode;
retNode = nullptr;
--size;
return temp;
} ~DoubleLoopLinkList() {
Node<T> *cur = dummyHead->next;
Node<T> *temp;
while (cur != nullptr) {
temp = cur->next;
delete cur;
cur = temp;
}
dummyHead->next = nullptr;
dummyHead->prev = nullptr;
delete dummyHead;
dummyHead = nullptr;
} void print() {
Node<T> *prev = dummyHead;
std::cout << "LinkedList: size = " << size << std::endl;
std::cout << "[";
for (int i = 0; i < size; ++i) {
prev = prev->next;
std::cout << prev->e;
if (i < size - 1) {
std::cout << ", ";
}
}
std::cout << "]" << std::endl;
} private:
Node<T> *dummyHead;
int size;
}; #endif //LINKEDLIST_DOUBLELOOPLINKLIST_H

双向循环链表(DoubleLoopLinkList)的更多相关文章

  1. 双向链表、双向循环链表的JS实现

    关于链表简介.单链表.单向循环链表.JS中的使用以及扩充方法:  单链表.循环链表的JS实现 关于四种链表的完整封装: https://github.com/zhuwq585/Data-Structu ...

  2. C语言通用双向循环链表操作函数集

    说明 相比Linux内核链表宿主结构可有多个链表结构的优点,本函数集侧重封装性和易用性,而灵活性和效率有所降低.     可基于该函数集方便地构造栈或队列集.     本函数集暂未考虑并发保护. 一  ...

  3. 双向循环链表的Java版本实现

    1.单项循环列表 单向循环链表是单链表的另一种形式,其结构特点是链表中最后一个结点的指针不再是结束标记,而是指向整个链表的第一个结点,从而使单链表形成一个环.和单链表相比,循环单链表的长处是从链尾到链 ...

  4. c语言编程之双向循环链表

    双向循环链表就是形成两个环,注意每个环的首尾相连基本就可以了. 程序中采用尾插法进行添加节点. #include<stdio.h> #include<stdlib.h> #de ...

  5. Linux内核中的通用双向循环链表

    开发中接触Linux越来越多,休息放松之余,免不了翻看翻看神秘的Linux的内核.看到双向链表时,觉得挺有意思的,此文记下. 作为众多基础数据结构中的一员,双向循环链表在各种“教科书”中的实现是相当的 ...

  6. java与数据结构(4)---java实现双向循环链表

    线性表之链式存储结构双向循环链表 双向循环链表:每个结点包含了数据.直接前驱地址指针和直接后驱地址指针,头结点的直接前驱指向尾结点,尾结点的直接后驱指向头结点,头尾相连构成一个可正可反的圆环.可以形象 ...

  7. 基于visual Studio2013解决算法导论之025双向循环链表

     题目 双向循环链表 解决代码及点评 #include <stdio.h> #include <stdlib.h> #include <time.h> #in ...

  8. 双向循环链表(C语言描述)(四)

    下面以一个电子英汉词典程序(以下简称电子词典)为例,应用双向循环链表.分离数据结构,可以使逻辑代码独立于数据结构操作代码,程序结构更清晰,代码更简洁:电子词典的增.删.查.改操作分别对应于链表的插入. ...

  9. 双向循环链表(C语言描述)(一)

    双向循环链表是链表的一种,它的每个节点也包含数据域和指针域.为了方便程序维护,可以单独为数据域定义一种数据类型,这里以整型为例: typedef int LinkedListData; 双向循环链表( ...

  10. python实现 双向循环链表

    最近身边的朋友在研究用python来实现数据结构.遇到一个问题就是双向循环链表的实现,改指向的时候总是发蒙. 我自己尝实现了一个python的双向循环链表.附上代码,希望对大家有帮助. 如果不懂什么是 ...

随机推荐

  1. SpringBoot整合aspectj实现面向切面编程(即AOP)

    前言 "面向切面编程",这样的名字并不是非常容易理解,且容易产生一些误导.但在实际业务中,AOP有着广泛的用途,比如日志记录,性能统计,安全控制,事务处理,异常处理等等. 举些栗子 ...

  2. 【LeetCode贪心#07】分糖果(两个维度)

    发糖果 力扣题目链接(opens new window) 老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分. 你需要按照以下要求,帮助老师给这些孩子分发糖 ...

  3. 简化Simulink的建模与模型重构

    简化Simulink的建模与模型重构 模型重构 Simulink作为汽车和自动化领域中经典的模型工程必备工具,不管是专业的汽车控制器的开发还是自动化控制的专业应用编程,都会使用到Simulink进行图 ...

  4. 第120篇: DOM编程(常用操作、动态脚本、样式及动态表格)

    好家伙,我回来了, 本篇为<JS高级程序设计>第十四章"DOM编程"学习笔记   1.DOM编程 我们知道DOM是HTML文档的编程接口, 我们可以通过HTML代码实现 ...

  5. 【Azure Developer】Go语言调用Azure SDK如何登录到中国区Azure环境

    问题描述 在 "使用 Azure SDK for Go 进行 Azure 身份验证" 文章中的 Go 示例代码进行登录Azure时,默认指向的是Globa Azure.当只修改AA ...

  6. [杂项] 抢单可能需要的API

    淘宝时间戳 http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp 京东库存查询 http://c0.3.cn/stock? ...

  7. Java 多线程------创建多线程的方式二:实现 Runnable接口 + 比较创建线程的两种方式:

    1 package com.bytezero.threadexer; 2 3 /** 4 * 5 * 创建多线程的方式二:实现 Runnable接口 6 * 1.创建一个实现了Runnable接口类 ...

  8. C++ //类模板中成员函数创建时机 //类模板中成员函数和普通类中成员函数创建时机是有区别的: //1.普通类中的成员函数一开始就可以创建 //2.类模板中的成员函数在调用时才创建

    1 //类模板中成员函数创建时机 2 //类模板中成员函数和普通类中成员函数创建时机是有区别的: 3 //1.普通类中的成员函数一开始就可以创建 4 //2.类模板中的成员函数在调用时才创建 5 6 ...

  9. 关于Java并发多线程的一点思考

    写在开头 在过去的2023年双11活动中,天猫的累计访问人次达到了8亿,京东超60个品牌销售破10亿,直播观看人数3.0亿人次,订单支付频率1分钟之内可达百万级峰值,这样的瞬间高并发活动,给服务端带来 ...

  10. picgo+gitee+typora实现博客图床

    背景 在微信公众号编写了推文后,从推文里面复制内容出来在其他平台发布,会出现图片展示不出来的情况,原因是因为该图片是微信的链接,被限制在其他平台显示. 诉求 编写的推文在多个平台都能进行发布,图片在多 ...