双向循环链表
//
// 双向循环链表
//
// Created by chenshang on 14-2-6.
// Copyright (c) 2014年 chenshang. All rights reserved.
//
#ifndef TestList_DoublyList_h
#define TestList_DoublyList_h
#include <iostream>
using namespace std;
typedef int T;
//创建一个节点
class ListNode
{
public:
ListNode():prior(NULL),next(NULL){}//构造方法,初始化,目的为了创建头结点
ListNode(const T &d) :data(d), prior(NULL),next(NULL){} //构造方法,初始化,创建结点
T data;
ListNode* prior;
ListNode* next;
};
//创建双向循环链表
class DoublyList{
public:
//初始化双向循环链表,并创建一个头结点
DoublyList():head(new ListNode())
{
head->prior= head;
head->next = head;
}
~DoublyList()
{
MakeEmpty();
delete head;
}
public:
void MakeEmpty();//清除
int Length(); //链表的长度
ListNode* FindData(T value);//找到与value值相等的结点
ListNode* Find(int n);//找到第n个结点
bool Insert(T item, int n=0);//往第n个结点的后面插入一个结点,如果要插入第一个结点,就应该在第零个之后
T Remove(int n=0); //删除第n个结点,这是与单项循环链表是有区别的。
T Get(int n);//得到第n个结点的数据
void Print(); //打印链表
private:
ListNode *head;
};
void DoublyList::MakeEmpty(){
ListNode *pdel,*pmove =head;
//算法解释:pmove不动,移动pdel
while (pmove->next!=head) {
pdel=pmove->next;
pmove->next=pdel->next;
delete pdel;
//注意这句话非常的重要,为什么要加入这句话?
//使用这种方法在删除双向循环链表的时候,已经破坏了顺序,此时要恢复顺序,以便在Length函数时不出错!
head->prior = head;
}
}
//由于是双向循环链表,我们采用前后指针同时移动的方法,从而提高效率。
int DoublyList::Length(){
ListNode* pprior=head->prior, *pnext =head->next;
int count =0;
while (1) {
//如果两个指针走过了,就要终止循环
if (pprior->next==pnext) {
break;
}
//相遇了,再加一次计数
if (pprior==pnext&&pprior!=head) {
count++;
break;
}
count+=2;
pprior=pprior->prior; //前移
pnext=pnext->next; //后移
}
return count;
}
//因为已经知道了 第几个结点,所以我们就不采用双向查找的方法了。效率都是一样的
ListNode* DoublyList::Find(int n){
if (n<0) {
cout<<"The n is out of boundary"<<endl;
return NULL;
}
ListNode* pmove=head;
for(int i=0;i<n;i++){
pmove=pmove->next;
if (pmove==head) {
cout<<"The n is out of boundary"<<endl;
return NULL;
}
}
return pmove;
}
//此时我们要采用双向查找的办法,从而提高效率
ListNode* DoublyList::FindData(T value){
ListNode* pprior = head->prior;
ListNode* pnext = head->next;
while (pprior->next!=pnext && pprior!=pnext) {
if (pprior->data==value) {
return pprior;
}
if (pnext->data==value) {
return pnext;
}
pprior = pprior->prior;
pnext = pnext ->next;
}
cout<<"can not find the element"<<endl;
return NULL;
}
//往第n个结点后面插入一个结点,如果我们要插入第一个结点 n=0,即在头结点后插入一个结点。
bool DoublyList::Insert(T item,int n){
if (n<0) {
cout<<"The n is out of boundary"<<endl;
return 0;
}
ListNode *pmove = head;
ListNode *pnode = new ListNode(item);
if (pnode==NULL) {
cout<<"Appliaction error!"<<endl;
return false;
}
for (int i=0; i<n; i++) {
pmove = pmove->next;
if (pmove==head) {
cout<<"The n is out of boundary" <<endl;
}
}
//插入数据,并维持双向循环链表的特点。
pnode->next = pmove ->next;
pmove->next = pnode;
pnode->prior = pmove;
pnode->next->prior=pnode;
return true;
}
//删除第n个结点,注意这和单项循环链表是有区别的,单项循环链表获取当前结点指针后,只能删除下一个结点,但是双向链表却不一样。
T DoublyList::Remove(int n){
if (n<0) {
cout<<"can not find the element"<<endl;
return false;
}
ListNode* pmove = head;
ListNode* pdel;
for (int i=0; i<n&&pmove->next!=head; i++) {
//n次循环后,指向当前第n个结点的指针
pmove=pmove->next;
}
if (pmove->next==head) {
cout<<"can not find the element"<<endl;
return false;
}
//删除数据,并维持循环链表的关系
//指向当前结点,并删除当前结点,注意与单项循环链表的区别。
pdel = pmove;
pmove->prior->next = pdel->next;
pmove->next->prior = pdel->prior;
T temp =pdel->data;
delete pdel;
return temp;
}
//已经知道结点位置,不需要双向循环,只需要单项查询即可!
T DoublyList::Get(int n){
if (n<0) {
cout<<"The n is out of boundary"<<endl;
exit(1);
}
ListNode* pmove = head;
for (int i=0; i<n; i++) {
pmove=pmove->next;
if (pmove==head) {
cout<<"The n is out of boundary"<<endl;
exit(1);
}
}
return pmove->data;
}
//打印函数
void DoublyList::Print(){
ListNode* pmove=head->next;
cout<<"head";
while(pmove!=head){
cout<<"--->"<<pmove->data;
pmove=pmove->next;
}
cout<<"--->over"<<endl<<endl<<endl;
}
#endif