双向循环链表

双向循环链表

//
//  双向循环链表
//
//  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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值