数据结构与算法——线性表链式存储(双向循环链表)
2015-05-09 08:53
351 查看
今天总结线性表中的双向循环链表。
什么是双向循环链表?
看名字估计也就知道了,首相他是一个循环链表,也就是最后一个结点的指针域不为空,而是指向头结点,其次与单向循环链表相比,它是双向的。所谓双向,就是给每个结点再增加一个指针域,这个指针域指向前一个结点。
即是下面这样(来自百度图片):
为什么要用双向循环链表?
无论单链表还是单向循环链表,都只有一个指针域,它们都是直接指向后继结点的,如果要查找当前结点的后继结点,会很方便。但是如果给定一个结点,要得到它的前继结点,就会很麻烦,必须从第一个元素开始遍历,然后判断当某个结点的指针域指向的是当前结点时,就判断该结点为当前结点的前继结点,时间复杂度为O(n)。而如果给每个结点增加一个指针域,指向其前继结点,那么给定一个结点时,直接就可以得到它的前继结点。
如何实现双向循环链表?
什么是双向循环链表?
看名字估计也就知道了,首相他是一个循环链表,也就是最后一个结点的指针域不为空,而是指向头结点,其次与单向循环链表相比,它是双向的。所谓双向,就是给每个结点再增加一个指针域,这个指针域指向前一个结点。
即是下面这样(来自百度图片):
为什么要用双向循环链表?
无论单链表还是单向循环链表,都只有一个指针域,它们都是直接指向后继结点的,如果要查找当前结点的后继结点,会很方便。但是如果给定一个结点,要得到它的前继结点,就会很麻烦,必须从第一个元素开始遍历,然后判断当某个结点的指针域指向的是当前结点时,就判断该结点为当前结点的前继结点,时间复杂度为O(n)。而如果给每个结点增加一个指针域,指向其前继结点,那么给定一个结点时,直接就可以得到它的前继结点。
如何实现双向循环链表?
<span style="font-family:Courier New;font-size:14px;">#include <iostream> using namespace std; template <class T> struct Node { T data; //数据域 struct Node<T> *pre; //指向前一个结点 struct Node<T> *next; //指向后一个结点 }; template <class T> //双向循环链表 模板类 class DoubleLinkList { private: Node<T> *front; //头指针 public: //空的循环链表 DoubleLinkList() { front = new Node<T>; //头结点 front->next = front; front->pre = front; } ~DoubleLinkList(); //析构函数 释放节点空间 DoubleLinkList(T a[],int n); //用数组a初始化链表 void Insert(int i,T x); //插入元毒到指定位置 T Delete(int i); //删除指定位置的元素 Node<T> *GetNode(int i); //返回指定位置的结点 int GetLength(); //获取链表的长度 void PrintLinkList(); //遍历链表 }; template <class T> //尾插法 DoubleLinkList<T>::DoubleLinkList(T a[],int n) { front = new Node<T>; front->next = front->pre = front; //初始化空表 for(int i=0;i<n;i++) { Node<T> *s = new Node<T>; s->next = front->next; //让当前结点指向头结点 s->data = a[i]; s->pre = front; //当前结点pre指针指向前一个结点 front->next = s; //前一个结点指向当前结点 front->pre = s; front = front->next; //指针后移 } } template <class T> DoubleLinkList<T>::~DoubleLinkList() { Node<T> *p = front->next; //获取头结点 while(p!=front->next) { Node<T> *q = p; //保存待删结点地址 p=p->next; delete q; } } template <class T> int DoubleLinkList<T>::GetLength() { Node<T> *p = front->next; int count = 1; while(p!=front->pre) { count++; p = p->next; } return count; } template <class T> void DoubleLinkList<T>::PrintLinkList() { Node<T> *p = front->next->next; //得到第一个结点 for(int i=0;i<GetLength();i++) { cout<<p->data<<" "; p = p->next; } cout<<endl; } template <class T> Node<T> * DoubleLinkList<T>::GetNode(int i) { Node<T> * p = front->next; for(int j=0;j<i;j++) { p = p->next; } return p; } template <class T> T DoubleLinkList<T>::Delete(int i) { Node<T> *p = front; if(i!=1) p = GetNode(i-1); //获取待删结点的前一个结点 if(p) { Node<T> *q = p->next; //保存待删结点 T x = q->data; //待删元素 p->next->next->pre = p; //使待删结点的后继结点的pre指针域指向前一个结点 p->next = p->next->next; //前一个结点next指针域指向待删结点后面的那个元素 delete q; return x; } return 0; } /** 插入操作实现 思路: 1.获取待插位置的前一个结点 2.新建一个结点,将待插结点元素保存到其数据域中 3.将待插结点指向插入位置后面的那个结点,其pre指向前面的那个结点 4.将后面结点的pre指向待插结点,将前面结点指向待插结点 技巧:这里可能结点指向操作的顺序容易弄混,导致出错. 我的办法是,只要先把当前结点先分别指向后继结点和前继结点,然后再使前继结点和后继结点指向当前结点 就一句话,记住先处理当前结点的指针域,顺序基本就不会错了。 */ template <class T> void DoubleLinkList<T>::Insert(int i,T x) { Node<T> *p = front; if(i!=1) p = GetNode(i-1); if(p) { Node<T> *s = new Node<T>; s->data = x; s->next = p->next; //指向后继结点 s->pre = p; //pre指针域指向前一结点 p->next->pre = s; //后继结点pre指向待插结点 p->next = s; //前一结点指向待插结点 } } int main() { int a[6] = {1,3,6,7,4,8}; DoubleLinkList<int> list(a,6); cout<<"双向循环链表的长度为:"<<endl; cout<<list.GetLength()<<endl; cout<<"遍历双向循环链表"<<endl; list.PrintLinkList(); cout<<"删除位置3的元素:"<<endl; cout<<"删除的元素为:"<<list.Delete(3)<<endl; list.PrintLinkList(); cout<<"在位置3插入元素5"<<endl; list.Insert(3,5); list.PrintLinkList(); return 0; } </span>运行结果:
相关文章推荐
- 数据结构和算法笔记 lesson4 线性表链式存储结构 单链表
- 数据结构_线性表_链式存储_双向循环链表的基本操作
- 数据结构_线性表_链式存储_单向循环链表的基本操作
- 数据结构_线性表_顺序存储之1顺序栈2共享栈_链式存储之链栈_栈的应用举例
- 【数据结构】线性表之双向链式线性表
- 头疼的算法与数据结构——双向循环链表
- 数据结构-链式存储线性表
- java常用数据结构---线性表---链式存储
- 数据结构与算法——线性表链式存储(单循环链表)
- 数据结构-双向循环链表(无头结点)相关算法
- 要完整准确的 均以单链表作存储结构 试编写算法将A表和B表归并成一个按元素值递减有序的线性表C 【数据结构】假设有两个按元素值递增有序的线性表A和B 并要求利用原表的空间存放C。谁会么
- 2015年考研核心考点命题思路解密——数据结构 第二章 线性表 考点3 线性表的链式存储(选择题部分)
- 【线性表】链式存储结构之:循环链表
- 数据结构_线性表_顺序/链式存储优缺点比较
- 2-8-双循环链表链式存储结构-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- 2-8-双循环链表链式存储结构-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- 2-4-单链表链式存储结构-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- [置顶] 数据结构——线性表链式存储
- 2-5-归并链式存储的单链表-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- 线性表16:双向链表 – 数据结构和算法21