双向循环链表(DoubleLoopLinkList)
双向循环链表

关于双向循环链表可以先阅读这篇文章这里就不再赘述:双向链表(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)的更多相关文章
- 双向链表、双向循环链表的JS实现
关于链表简介.单链表.单向循环链表.JS中的使用以及扩充方法: 单链表.循环链表的JS实现 关于四种链表的完整封装: https://github.com/zhuwq585/Data-Structu ...
- C语言通用双向循环链表操作函数集
说明 相比Linux内核链表宿主结构可有多个链表结构的优点,本函数集侧重封装性和易用性,而灵活性和效率有所降低. 可基于该函数集方便地构造栈或队列集. 本函数集暂未考虑并发保护. 一 ...
- 双向循环链表的Java版本实现
1.单项循环列表 单向循环链表是单链表的另一种形式,其结构特点是链表中最后一个结点的指针不再是结束标记,而是指向整个链表的第一个结点,从而使单链表形成一个环.和单链表相比,循环单链表的长处是从链尾到链 ...
- c语言编程之双向循环链表
双向循环链表就是形成两个环,注意每个环的首尾相连基本就可以了. 程序中采用尾插法进行添加节点. #include<stdio.h> #include<stdlib.h> #de ...
- Linux内核中的通用双向循环链表
开发中接触Linux越来越多,休息放松之余,免不了翻看翻看神秘的Linux的内核.看到双向链表时,觉得挺有意思的,此文记下. 作为众多基础数据结构中的一员,双向循环链表在各种“教科书”中的实现是相当的 ...
- java与数据结构(4)---java实现双向循环链表
线性表之链式存储结构双向循环链表 双向循环链表:每个结点包含了数据.直接前驱地址指针和直接后驱地址指针,头结点的直接前驱指向尾结点,尾结点的直接后驱指向头结点,头尾相连构成一个可正可反的圆环.可以形象 ...
- 基于visual Studio2013解决算法导论之025双向循环链表
题目 双向循环链表 解决代码及点评 #include <stdio.h> #include <stdlib.h> #include <time.h> #in ...
- 双向循环链表(C语言描述)(四)
下面以一个电子英汉词典程序(以下简称电子词典)为例,应用双向循环链表.分离数据结构,可以使逻辑代码独立于数据结构操作代码,程序结构更清晰,代码更简洁:电子词典的增.删.查.改操作分别对应于链表的插入. ...
- 双向循环链表(C语言描述)(一)
双向循环链表是链表的一种,它的每个节点也包含数据域和指针域.为了方便程序维护,可以单独为数据域定义一种数据类型,这里以整型为例: typedef int LinkedListData; 双向循环链表( ...
- python实现 双向循环链表
最近身边的朋友在研究用python来实现数据结构.遇到一个问题就是双向循环链表的实现,改指向的时候总是发蒙. 我自己尝实现了一个python的双向循环链表.附上代码,希望对大家有帮助. 如果不懂什么是 ...
随机推荐
- P3374 【模板】树状数组 1(线段树)
[模板]树状数组 1 题目描述 如题,已知一个数列,你需要进行下面两种操作: 将某一个数加上 x 求出某区间每一个数的和 输入格式 第一行包含两个正整数 n,m ,分别表示该数列数字的个数和操作的总个 ...
- 发送HTML模板邮件
概述 为了增强邮件内容展示的样式,可以将普通的文本邮件转换为HTML内容格式. 在Java中,可以通过页面模板技术来实现.具体来说,可以使用Thymeleaf模板. 具体实现 首先,在项目中引入Thy ...
- pwd模块
# pwd模块提供了获取UNIX平台用户的账户与密码信息(通过文件/etc/passwd),在所有的UNIX版本平台都可以用. # pwd模块返回的是一个类似元组的对象,该对象的各个属性对应于pass ...
- 别再低效筛选数据了!试试pandas query函数
数据过滤在数据分析过程中具有极其重要的地位,因为在真实世界的数据集中,往往存在重复.缺失或异常的数据.pandas提供的数据过滤功能可以帮助我们轻松地识别和处理这些问题数据,从而确保数据的质量和准确性 ...
- Java 设计模式----单例模式--懒汉式
1 package com.bytezreo.singleton; 2 3 /** 4 * 5 * @Description 单例模式 ---懒汉式 6 * @author Bytezero·zhen ...
- Java 四种不同的权限修饰
private 私有属性 只在同一个包下 同一个类中可以调用 同一个包下,不同的类中,可以调用 缺省,保护(protected),公共(public)可以调用, 不同的包下的类中,继承关系,可以调用 ...
- 通过debug搞清楚.vue文件怎么变成.js文件
前言 我们每天写的vue代码都是写在vue文件中,但是浏览器却只认识html.css.js等文件类型.所以这个时候就需要一个工具将vue文件转换为浏览器能够认识的js文件,想必你第一时间就想到了web ...
- 虚拟机和开发板之间通过NFS互联
简介 NFS是Network File System的首字母缩写.它是一种分布式协议,使客户端可以访问远程服务器上的共享文件.它允许网络中的计算机之间通过TCP/IP网络共享资源. 配置过程 安装NF ...
- zabbix“专家坐诊”第178期问答汇总
大家好,我是乐乐.早在三年前,我们就在社区举办了zabbix公益问答活动,并且定在每周三邀请资深的zabbix技术工程师,为社群的小伙伴进行免费的答疑.到现在已经178期了.后续我将会把每期的答疑汇总 ...
- 真实开发中-redis在项目中的应用场景
一.需求描述 从自己当前负责参与开发的一个项目中来看,redis主要的应用场景有如下几个,第一个是保存用户信息,这个需要频繁的获取.比如 在打开某一个页面进行查询时,就先需要获取用户信息,看用户是否具 ...