双向链表又称为双链表,使用双向链表的目的是为了解决在链表中访问直接前驱和后继的问题。其设置前驱后继指针的目的,就是为了节省其时间开销,也就是用空间换时间。

在双向链表的每个节点中应有两个链接指针作为它的数据成员:pred指向其前驱节点,next指向其后继节点。再加上数据域,因此每个双向链表至少包括三个域。

实现代码如下

//header.h
#include<iostream>
using namespace std;
/*
* 双向循环链表头文件,
* 其声明中封装有指向链表附加头节点的头x指针first
*/ template<class T>
struct DbNode
{
T data;
DbNode<T> *pred, *next;
DbNode(T value, DbNode<T> *a = NULL, DbNode<T> *b = NULL):\
data(value), pred(a), next(b){}
DbNode(DbNode<T> *a = NULL, DbNode<T> *b = NULL):pred(a), next(b){}
}; template<class T>
class Dblist
{
private: DbNode<T> *first;
public:
Dblist(T value);
~Dblist(){makeEmpty();}
void makeEmpty();
int Length()const;
bool IsEmpty(){return (this->first->pred == this->pred);}
DbNode<T> *getHead()const{return this->first;}
DbNode<T> *Locate(int i, int d);
DbNode<T> *Search(const T& x);
bool Insert(int i, const T& x, int d);
bool Remove(int i, T& x, int d);
void Print(int d);
};
template<class T>
int Dblist<T>::Length()const
{
DbNode<T> *tmp = this->first;
int i = 1;
while(tmp->next!=this->first)
{
++i;
tmp = tmp->next;
}
return i;
}
template<class T>
bool Dblist<T>::Remove(int i, T& x, int d)
{
DbNode<T> *p = this->Locate(i, d);
if(!p)
return false;
x = p->data;
if(p==this->first && this->Length()>1)
this->first = p->next;
else
cout<<"仅有头节点的双向循环链表已被删除!请勿在没添加新元素前对其调用。"<<endl;
p->pred->next = p->next;
p->next->pred = p->pred;
delete p;
return true;
}
template<class T>
DbNode<T>* Dblist<T>::Search(const T& x)
{
DbNode<T> *tmp = this->first;
do
{
if(tmp->data==x)
{
cout<<"address of x is "<<tmp<<" x = "<<tmp->data<<endl;
return tmp;
}
tmp = tmp->pred;
}while(tmp!=this->first);
return NULL;
}
template<class T>//定位元素,d=0时从头节点向前(pred)查第i个元素,d!=0时,从头节点向后(next)找第i个元素
DbNode<T>* Dblist<T>::Locate(int i, int d)
{
if(this->first->next==this->first || i==0)
return this->first;
int t = 1;
DbNode<T>* tmp = this->first;
if(d) //向后找
{
while(tmp->next!=this->first && t!=i)//查找到的条件为,在没把双向循环链表遍历一遍前,t=i
{
tmp = tmp->next;
++t;
}
if(tmp->next==this->first&&t!=i)
return NULL;
else
return tmp; }
else //向前找
{
while(tmp->pred!=this->first && t!=i)
{
tmp = tmp->pred;
++t;
}
if(tmp->pred==this->first&&t!=i)
return NULL;
else
return tmp;
}
}
template<class T>
bool Dblist<T>::Insert(int i, const T& x, int d)
{
DbNode<T> *p = this->Locate(i, d);
if(!p)
return false;
DbNode<T> *newnode = new DbNode<T>;
if(newnode==NULL)
{
cout<<"申请内存错误!"<<endl;
exit(1);
}
newnode->data = x;
if(d) //p节点后插入
{
p->next->pred = newnode;
newnode->pred = p;
newnode->next = p->next;
p->next = newnode;
}
else //p节点前插入
{
p->pred->next = newnode;
newnode->next = p;
newnode->pred = p->pred;
p->pred = newnode;
}
return true;
}
template<class T>
void Dblist<T>::makeEmpty()
{
DbNode<T> *p, *q = this->first->pred;
while(q != this->first)
{
p = q;
q = q->pred;
delete p;
}
}
template<class T>
void Dblist<T>::Print(int d)
{
if(d) //正序打印
{
cout<<"Positive order: ";
DbNode<T> *tmp = this->first;
while(tmp->next != this->first)
{
cout<<tmp->data<<"->";
tmp = tmp->next;
}
cout<<tmp->data<<"->over."<<endl; }
else //逆序打印
{
DbNode<T> *tmp = this->first;
cout<<"Reverse sequence: ";
while(tmp->pred != this->first)
{
cout<<tmp->data<<"->";
tmp = tmp->pred;
}
cout<<tmp->data<<"->over."<<endl;
}
} template<class T>
Dblist<T>::Dblist(T value)
{
this->first = new DbNode<T>(value);
if(this->first == NULL)
{
cerr<<"内存分配错误!"<<endl;
exit(1);
}
this->first->next = this->first->pred = this->first;
}
//main.cpp
#include"header.h" int main()
{
Dblist<int> dl(888);
dl.Print(0);
for(int i=1; i<=4; ++i)
{
dl.Insert(1, i, 0);
}
dl.Print(1);
int l = 999, k = 0;
dl.Insert(0, l, 0);
//int k = 0;
dl.Print(1);
dl.Remove(0, k, 0);
dl.Print(1);
k = 5;
     dl.Search(k);
     dl.Print(0);
return 0;
}

完成效果

双向循环链表模板类(C++)的更多相关文章

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

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

  2. C++实现双向循环链表

    本次博文是关于利用C++模板的方式实现的双向循环链表以及双向循环链表的基本操作,在之前的博文C++语言实现双向链表中,已经给大家分析了双向循环链表的结构,并以图示的方式给大家解释了双向循环链表的基本操 ...

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

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

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

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

  5. python实现 双向循环链表

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

  6. "《算法导论》之‘线性表’":双向循环链表

    本文双链表介绍部分参考自博文数组.单链表和双链表介绍 以及 双向链表的C/C++/Java实现. 1 双链表介绍 双向链表(双链表)是链表的一种.和单链表一样,双链表也是由节点组成,它的每个数据结点中 ...

  7. java实现双向循环链表

    java实现循环链表:http://www.cnblogs.com/lixiaolun/p/4643911.html 在单链表中,查询下一个元素的时间是O(1).查询上一个元素的时间却是O(n). 为 ...

  8. Linux内核2.6.14源码分析-双向循环链表代码分析(巨详细)

    Linux内核源码分析-链表代码分析 分析人:余旭 分析时间:2005年11月17日星期四 11:40:10 AM 雨 温度:10-11度 编号:1-4 类别:准备工作 Email:yuxu97101 ...

  9. 数据结构8: 双向链表(双向循环链表)的建立及C语言实现

    之前接触到的链表都只有一个指针,指向直接后继,整个链表只能单方向从表头访问到表尾,这种结构的链表统称为 “单向链表”或“单链表”. 如果算法中需要频繁地找某结点的前趋结点,单链表的解决方式是遍历整个链 ...

随机推荐

  1. hdu 5093 Battle ships(二分图最大匹配)

    题意: M*N的矩阵,每个格子上是三个之一:*.o.#.                     (1 <= m, n <= 50) *:海洋,战船可以停在上面.      o:浮冰,战船 ...

  2. hdu 2586 How far away? (LCA模板)

    题意: N个点,形成一棵树,边有长度. M个询问,每个询问(a,b),询问a和b的距离 思路: 模板题,看代码.DFS预处理算出每个结点离根结点的距离. 注意: qhead[maxn],而不是qhea ...

  3. swoole、swoft环境配置

    一.服务器环境 1.lnmp wget http://soft.vpser.net/lnmp/lnmp1.5.tar.gz -cO lnmp1.5.tar.gz && tar zxf ...

  4. WebRTC概念介绍

    WebRTC WebRTC(Web Real-Time Communication).Real-Time Communication,实时通讯. WebRTC能让web应用和站点之间选择性地分享音视频 ...

  5. 第一天 python入门 基础 “”“Hello World”和if-elif的使用、数据类型

    (1)第一个程序"""Hello World" 实现python环境打印输出:Hello World 程序: print("Hello World&q ...

  6. 个人网站迁移之旅:从博客到知识库,从 Hexo 到 Docusaurus

    或是出于跟风,或是为了简历能好看点,2020 年 2 月,在翻看了中文互联网大量的「免费个人网页搭建教程」后,我选择了 Hexo + Github Pages 的方案,找了一款看上去还不错的主题,搭建 ...

  7. Python基础(普通函数及参数)

    # def my_abs(x): # if not isinstance(x,(int,float)):#参数类型做检查,只允许整数和浮点数类型的参数.数据类型检查可以用内置函数isinstance( ...

  8. Django笔记&教程 3-4 模板继承

    Django 自学笔记兼学习教程第3章第4节--模板继承 点击查看教程总目录 在介绍具体的技术之前,先介绍在什么样的场景中,需要使用这样的技术,我觉得这对于新手理解起来很重要. 一般来说,要渲染一个页 ...

  9. 单元测试NUnit,mock组件NSubstitute,信号量SemaphoreSlim,异步lock等例子

    public class LockTest { private IDatabase _database; private readonly Random _random = new Random(); ...

  10. 国内首家!腾讯云正式成为 FinOps 基金会顶级会员

    11月24日,腾讯云正式宣布加入FinOps基金会,作为国内首家FinOps基金会顶级会员,腾讯云将联合FinOps基金会,全面推进对FinOps标准和最佳实践的贡献,为企业提供云财务管理的最佳解决方 ...