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

在双向链表的每个节点中应有两个链接指针作为它的数据成员: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;
}

完成效果

最新文章

  1. xpath定位中starts-with、contains和text()的用法
  2. Different Approaches for MVCC
  3. ExtJS入门教程01,Window如此简单,你怎能不会?
  4. 使用注解来构造IoC容器
  5. 常用的Linux终端
  6. Use Eclipse to develop groovy[docs.codehaus.org]
  7. SLIC superpixel实现分析
  8. Server from URL
  9. ES6-字符串的扩展-模板字符串
  10. android:自己定义组合控件Weight(高仿猫眼底部菜单条)
  11. javascript原型与原型链,prototype、__proto__、constructor
  12. vue组件导航栏动态添加class
  13. Unity3D中的高级摄像机跟随
  14. 如何对CentOS FTP服务配置
  15. spring boot 集成 shiro
  16. unity3d中的自定义模型的顶点法线和建模软件中的术语“软硬边”和立方体
  17. Loadrunner常用操作
  18. adb shell dumpsys的用法
  19. Python基础笔记系列十:模块
  20. JavaScript内存泄漏知多少?

热门文章

  1. 【Azure 应用服务】App Service for Linux 中实现 WebSocket 功能 (Python SocketIO)
  2. 子查询 &amp; 联合查询
  3. webpack 提取css成单独文件
  4. 【JAVA】笔记(3)---封装;如何选择声明静态变量还是实例变量;如何选择声明静态方法还是实例方法;静态代码块与实例代码块的执行顺序与用途;
  5. Ubuntu1804命令行安装vmtool
  6. Handler处理器&amp;&amp;使用代理服务器urllib.request.ProxyHandler
  7. [51nod1237]最大公约数之和V3
  8. [atARC109E]1D Reversi Builder
  9. [noi795]保镖
  10. [loj3276]遗迹