双向链表的C++实现

来源:互联网 发布:手机缩小图片尺寸软件 编辑:程序博客网 时间:2024/04/28 08:45

双向链表的C++实现

 

        双向链表与单向链表相比,各个结点多了一个指向前一个结点的指针。结构如图所示:

 

        双向链表的结点定义如下:

#ifndef SIMPLENODE_HPP#define SIMPLENODE_HPPtemplate<typename T>        //再定义一个模板  写双链表 class DoubleNode{public:T element;DoubleNode* prev;DoubleNode* next;DoubleNode(const T& theElement,DoubleNode* thePrev=NULL,DoubleNode* theNext=NULL)       :element(theElement),prev(thePrev),next(theNext) {}//这里已经创建了一个双链表 }; #endif


       

        在组成一个双向链表后,还需要补充一些功能,以便后续实现,模仿之前的单向链表:

        1.定义这个双向链表类的构造函数及析构函数

        2.清空链表内所有元素

        3.给出元素位置再返回对应结点

        4.返回链表内部元素个数

        5.判断这个链表是否为空

        6.返回链表首尾的元素值

        7.查找元素是否在此链表内,如果在则返回所在位置

        8.从首端到尾端输出链表上的各元素,以及反序输出链表上各元素

        9.对链表插入元素以及删除元素

 

         给出这个双向链表类框架,就像这样:

#ifndef DOUBLELINKLIST_HPP#define DOUBLELINKLIST_HPP#include<iostream>#include"simplenode.hpp"template<typename T>class DoubleLinkList{private:DoubleNode<T>* head;DoubleNode<T>* tail;int size;DoubleNode<T>* GetPointAt(int pos){...}   //给出元素位置再返回其对应结点public:DoubleLinkList():head(),tail(),size(0) {}~DoubleLinkList() {Clear();}void Clear(){...}int Size() {...}   //返回元素个数bool isempty() {... }T GetHeadVal() {...} T GetTailVal(){...}int Find(T val){...}void ShowAllVal(){...}void ReverseShowAllVal(){...}void AddBack(T val){...}void AddFront(T val){...}bool AddAt(T val,int pos){DoubleNode<T>* pNode=NULL;if (pos<=0 || pos>size){...}if (pos==size)AddBack(size);else if (pos==1)AddFront(1);else{...}size++;return true;}bool RemoveBack(){return RemoveAt(size);}bool RemoveFront(){return RemoveAt(1);}bool RemoveAt(int pos){DoubleNode<T>* pNode=NULL;if (isempty()){...}if (pos<=0 || pos>size){...}if (size==1){Clear();}if (pos==1){...}else{DoubleNode<T>* pPreNode=GetPointAt(pos-1);pNode=pPreNode->next;if (pos==size){ ...} else{...}delete pNode;}size--;return true;}};#endif

 

          双向链表具体实现如下:

        1.构造函数和析构函数:

DoubleLinkList():head(),tail(),size(0) {}~DoubleLinkList() {Clear();}

        2.清空链表内所有元素:

void Clear(){//从链表头到链表尾的方式逐个删除 const int nums=Size();if (!isempty()){for (int k=1;k<=nums;++k){DoubleNode<T>* temp=head->next;delete head;head=temp;size--;}}//如果链表本来就为空,就没必要再进for循环了 }

 

        3.给出元素位置再返回对应结点:

DoubleNode<T>* GetPointAt(int pos){DoubleNode<T>* pNode=NULL;if (pos<=0 || pos>size)std::cout<<"out of range"<<std::endl;else{pNode=head;for (int i=1;i<=pos-1;++i)pNode=pNode->next;}return pNode;}

        要注意的是,遍历元素位置时避免pNode所获得的值越界,队首元素进不了for循环,改变不了pNode;队尾元素如果设置成i=1;i<=pos;++i,pNode会读取队尾的下一个值,那个值越界。最后就会返回一个未定义的元素。

        4.返回首尾端元素、查找元素、正序反序输出链表所有元素、返回元素个数、判断链表是否为空:

T GetHeadVal() {if (isempty()){std::cout<<"the link list is empty"<<std::endl;return NULL;}return head->element;} T GetTailVal(){if (isempty()){std::cout<<"the link list is empty"<<std::endl;return NULL;}return tail->element;}
int Find(T val){int pos=1;    //从1号位,也就是链表首开始DoubleNode<T>* findNode=head;while (findNode!=NULL){if (findNode->element==val)return pos;findNode=findNode->next;pos++;} std::cout<<"we can't find it.return -1"<<std::endl;return -1;}
void ShowAllVal(){DoubleNode<T>* findNode=head;while (findNode!=NULL){std::cout<<findNode->element<<" ";findNode=findNode->next;}std::cout<<std::endl;}void ReverseShowAllVal(){DoubleNode<T>* findNode=tail;while (findNode!=NULL){std::cout<<findNode->element<<" ";findNode=findNode->prev; }std::cout<<std::endl;}
int Size() {return size;}   //返回元素个数bool isempty() {return size==0?true:false; }


 

        5.链表中加入元素:

        这里分四种情况讨论:

                ①插入元素位置越界                               

                ②在尾部插入元素                                   

                ③在头部插入元素                           

                ④在其他位置插入元素                   

        若插入元素成功,记得元素个数+1。这里用图示例非空链表尾部插入元素,其他情况读者们可以自己试着画图:

 

          代码如下:

void AddBack(T val){DoubleNode<T>* pNode=new DoubleNode<T>(val);if (isempty()){head=pNode;tail=pNode;}else{tail->next=pNode;pNode->prev=tail;tail=pNode;}size++;}void AddFront(T val){DoubleNode<T>* pNode=new DoubleNode<T>(val);if (isempty()){head=pNode;tail=pNode;}else{head->prev=pNode;pNode->next=head;head=pNode;}size++;}bool AddAt(T val,int pos){DoubleNode<T>* pNode=NULL;if (pos<=0 || pos>size){std::cout<<"out of range"<<std::endl;return false;}if (pos==size)AddBack(size);else if (pos==1)AddFront(1);else{DoubleNode<T>* pPreNode=GetPointAt(pos-1);pNode=new DoubleNode<T>(val);pNode->next=pPreNode->next;pNode->prev=pPreNode;pPreNode->next->prev=pNode;  pPreNode->next=pNode;}size++;return true;}

 

        6.链表中删除元素:

        这里分五种情况讨论:

                ①链表为空                                

                ②删除元素位置越界                               

                ③在尾部删除元素

                ④在头部删除元素

                ⑤在其他位置删除元素

        若删除元素成功,记得元素个数-1。这里用图示例非空链表其他位置删除元素,其他情况读者们可以自己试着画图:

 

          代码如下:

bool RemoveBack(){return RemoveAt(size);}bool RemoveFront(){return RemoveAt(1);}bool RemoveAt(int pos){DoubleNode<T>* pNode=NULL;if (isempty()){std::cout<<"the link list is empty"<<std::endl;return false;}if (pos<=0 || pos>size){std::cout<<"out of range"<<std::endl;return false;}if (size==1){Clear();}if (pos==1){pNode=head;head=head->next;head->prev=NULL;delete pNode;}else{DoubleNode<T>* pPreNode=GetPointAt(pos-1);pNode=pPreNode->next;if (pos==size){ pPreNode->next=NULL;tail=pPreNode;} else{pPreNode->next=pNode->next;pNode->next->prev=pPreNode;}delete pNode;}size--;return true;}

 

         最后将上述实现放入之前的框架中,就完成了最后双向链表的C++实现。

 

 

 

参考文献及链接:

1.《算法导论》2nd   Thomas H.Cormen , Charles E.Leiserson , Ronald L.Rivest , Cliford Stein 著,潘金贵、顾铁成、李成法、叶懋译
2.《数据结构与算法分析 C++描述》 第3版  Mark Allen Weiss著,张怀勇等译
3.《C++标准模板库 -自修教程及参考手册-》  Nicolai M.Josuttis著,侯捷/孟岩译

4.http://blog.csdn.net/weiwenhp/article/details/8634984

5.http://blog.csdn.net/mourinho_my_idol/article/details/12570609

原创粉丝点击