date: 2018-09-27 12:42:30+00:00
原标题: 自己动手实现数据结构模板(1):双向链表
原链接: https://www.dreamoftime0.com/2018/09/27/%e8%87%aa%e5%b7%b1%e5%8a%a8%e6%89%8b%e5%ae%9e%e7%8e%b0%e5%8f%8c%e5%90%91%e9%93%be%e8%a1%a8/
今天忽然心血来潮,自己动手实现了一个简单的双向链表和基本功能,大致实现了如下功能
dtsListNode为结点类,包括值value、前向指针pre和后向指针next。
dtsList为双向链表,能够通过begin和end函数获得首地址指针和指向最后一个元素之后一个的尾指针,使用empty函数判断是否为空,size返回数据结点个数,print和print_rev输出当前所有结点,以及使用add2Head、add2End、deleteFromHead、deleteFromEnd从首尾增加或删除结点,并能够在删除结点或析构时及时释放占用的内存。
以下为源代码:
#ifndef DTS_LIST_HPP
#define DTS_LIST_HPP
#include
using namespace std;
template
class dtsListNode{
public:
T value;
dtsListNode* next;
dtsListNode* pre;
dtsListNode(T v,dtsListNode* nextPointer=NULL,dtsListNode* prePointer=NULL)
:value(v),next(nextPointer),pre(prePointer){}
dtsListNode():next(NULL),pre(NULL){}
};
template
class dtsList{
protected:
dtsListNode* pHead;//空的头结点
dtsListNode* pBegin;//链表第一个数据结点
dtsListNode* pTail;//链表最后一个数据结点
dtsListNode* pEnd;//空的尾结点
inline dtsListNode* insertAfter(dtsListNode* first,T val){
dtsListNode* second = new dtsListNode(val);
dtsListNode* third = first->next;
if(first==pHead)
pBegin=second;
if(first==pTail)
pTail=second;
first->next=second;
second->pre=first;
second->next=third;
third->pre=second;
return second;
}
inline T deleteAfter(dtsListNode* first){
T ret;
if(!first || !first->next || !first->next->next)
return ret;
dtsListNode* second=first->next;
dtsListNode* third=second->next;
ret=second->value;
if(first==pHead){//删除结点为pBegin时
pBegin=third;
}
if(second==pTail){//删除结点为pTail时
if(first!=pHead){
pTail=first;
}
else {//删除最后一个结点时
pBegin=NULL;
pTail=NULL;
}
}
delete second;
first->next=third;
third->pre=first;
return ret;
}
public:
dtsList(){
pHead = new dtsListNode();
pEnd = new dtsListNode();
pBegin = NULL;
pTail = NULL;
pHead->next=pEnd;
pEnd->pre=pHead;
}
inline bool empty(){
return pBegin==NULL;
}
int size(){
if(empty())
return 0;
int ret=0;
for(dtsListNode* it=pBegin;it!=pEnd;it=it->next){
++ret;
}
return ret;
}
dtsListNode* begin(){
return pBegin;
}
dtsListNode* end(){
return pEnd();
}
dtsList& add2End(T val){
if(!pTail || !pBegin){//当前无数据时
pBegin=insertAfter(pHead,val);
pTail=pBegin;
//print();
} else {//已有至少一个数据结点,将它加在最后
insertAfter(pTail,val);
//print();
}
//cout<<"node "<<val<<" added"<<endl;
return *this;
}
dtsList& add2Head(T val){
if(!pBegin || !pTail){//当前无数据时
pBegin=insertAfter(pHead,val);
pTail=pBegin;
//print();
} else {//已有至少一个数据结点,将它加在最前面
insertAfter(pHead,val);//新的第一个数据结点
//print();
}
//cout<<"node "<<val<<" added"<<endl; return *this; } T deleteFromEnd(){ if(pTail){ return deleteAfter(pTail->pre);
}
T ret;
return ret;
}
T deleteFromHead(){
return deleteAfter(pHead);
}
void print(const char* separator="->",const char* null_str="空链表"){
if(pHead->next==pEnd){
cout<<null_str<<endl;
return;
}
for( dtsListNode* it=pBegin;it!=pEnd;it=it->next ){
cout<value;
if(it!=pEnd->pre)
cout<<separator;
}
cout<<endl;
}
void print_rev(const char* separator="<-",const char* null_str="空链表"){ if(pHead->next==pEnd){
cout<<null_str<<endl;
return;
}
for( dtsListNode* it=pTail;it!=pHead;it=it->pre ){
cout<value;
if(it!=pHead->next)
cout<<separator;
}
cout<<endl;
}
virtual ~dtsList(){
dtsListNode* node2Delete=pHead;
dtsListNode* nextNode2Delete;
while(node2Delete){
nextNode2Delete=node2Delete->next;
//cout<<"node "<value<<" deleted."<<endl;
delete node2Delete;
node2Delete=nextNode2Delete;
}
//cout<<"list freed"<<endl;
}
};
#endif // !DTS_LIST_HPP
以下为测试主函数
#include<iostream>
#include<string>
#include"dtsList.hpp"
using namespace std;
int main(){
dtsList<string> l;
l.add2Head("one");
l.add2End("two");
l.add2End("three");
l.add2Head("zero");
l.print("->");
l.print_rev();
cout<<"size:"<<l.size()<<endl;
cout<<l.deleteFromEnd()<<" 被删除"<<endl;
l.print("->");
cout<<"size:"<<l.size()<<endl;
cout<<l.deleteFromHead()<<" 被删除"<<endl;
l.print("->");
cout<<"size:"<<l.size()<<endl;
cout<<l.deleteFromHead()<<" 被删除"<<endl;
l.print("->");
cout<<"size:"<<l.size()<<endl;
cout<<l.deleteFromHead()<<" 被删除"<<endl;
l.print("->");
cout<<"size:"<<l.size()<<endl;
}
输出:
zero->one->two->three
three<-two<-one<-zero
size:4
three 被删除 zero->one->two
size:3
zero 被删除
one->two
size:2
one 被删除
two
size:1
two 被删除
空链表
size:0
按任意键继续