C++实现双链表的基本功能
2016-08-23 14:13
375 查看
双链表:在单链表的每个结点中,再设置一个指向其前驱结点的指针域
线性表的双向链表存储结构:
通过双链表的存储结构我们发现双链表可以反向查找结点优于单链表 ,实质上双链表就是以空间换取时间,虽然双链表具有可以反向查找数据的优点但是它也存在缺点:在插入和删除一个结点时需要维护两个指针变量,特别是在双链表的插入中指针的指向顺序是不可修改的。
双链表的插入过程:
双链表的删除过程:
C++实现双链表的基本功能:
在C++实现中如果遇到结点结构最好定义为struct,否则就会像上述情况一样需要声明多次友元,反而破坏了类的封装性
测试代码:
OVER
线性表的双向链表存储结构:
typedef struct Node { DataType _data; struct Node *_next; struct Node *_front; }Node;
通过双链表的存储结构我们发现双链表可以反向查找结点优于单链表 ,实质上双链表就是以空间换取时间,虽然双链表具有可以反向查找数据的优点但是它也存在缺点:在插入和删除一个结点时需要维护两个指针变量,特别是在双链表的插入中指针的指向顺序是不可修改的。
双链表的插入过程:
双链表的删除过程:
C++实现双链表的基本功能:
typedef int DataType; class LinkList; class Node { friend LinkList; friend ostream &operator<<(ostream &os,Node &n); friend ostream& operator<<(ostream &os,LinkList &list); public: Node(DataType x) :_data(x) ,_next(NULL) ,_front(NULL) {} private: DataType _data; Node *_next; Node *_front; }; ostream &operator<<(ostream &os,Node &n) { os<<n._data; return os; } class LinkList { friend ostream& operator<<(ostream &os,LinkList &list); public: LinkList() :_head(NULL) ,_tail(NULL) {} LinkList(const LinkList &list) :_head(NULL) ,_tail(NULL) { Node *cur=list._head; while(cur) { Node *tmp=new Node(cur->_data); if(_tail) { _tail->_next=tmp; tmp->_front=_tail; _tail=tmp; } else //空链表 { _head=tmp; _tail=tmp; } cur=cur->_next; } } ~LinkList() { Node *cur=_head; while(cur) { Node *del=cur; cur=cur->_next; delete del; del=NULL; } } public: void PushBack(DataType x) { Node *NewNode=new Node(x); if(_tail) { _tail->_next=NewNode; NewNode->_front=_tail; _tail=NewNode; } else { _head=NewNode; _tail=NewNode; } } void PopBack() { if(!_head && !_tail) //空链表 { cout<<"链表已空不可尾删"<<endl; return ; } else if(_head == _tail) //只有一个节点 { delete _tail; _head=NULL; _tail=NULL; } else //至少存在两个节点 { Node *tmp=_tail; _tail=tmp->_front; _tail->_next=NULL; delete tmp; tmp=NULL; } } void PushFront(DataType x) { Node *NewNode=new Node(x); if(_head) { Node *tmp=_head; NewNode->_next=tmp; tmp->_front=NewNode; } else { _tail=NewNode; } _head=NewNode; //更新头 } void PopFront() { if(!_head && !_tail) //空链表 { cout<<"链表已空不可头删"<<endl; return ; } else if(_head == _tail) //只有一个节点 { delete _head; _head=NULL; _tail=NULL; } else //至少存在两个节点 { Node *del=_head; _head=del->_next; _head->_front=NULL; delete del; del=NULL; } } Node *FindNum(DataType x) { Node *cur=_head; while(cur) { if(cur->_data == x) return cur; cur=cur->_next; } return NULL; } void Insert(Node *pos,DataType x) //在指定位置后插 { Node *NewNode=new Node(x); if(pos->_next) { NewNode->_front=pos; NewNode->_next=pos->_next; pos->_next->_front=NewNode; pos->_next=NewNode; } else //在最后一个结点后插,类似PushBack { pos->_next=NewNode; NewNode->_front=pos; _tail=NewNode; //更新尾 } } void Insert(int,Node *pos,DataType x) //在指定位置前插 { Node *NewNode=new Node(x); if(pos->_front) { NewNode->_next=pos; pos->_front->_next=NewNode; NewNode->_front=pos->_front; pos->_front=NewNode; } else //在第一个结点的前插,类似PushFront { NewNode->_next=pos; pos->_front=NewNode; _head=NewNode; //更新头 } } void Remove(DataType &x) { Node *pos=this->FindNum(x); if(pos != NULL) { if((!(pos->_front)) && pos->_next) //删除第一个结点 { Node *tmp=pos->_next; tmp->_front=NULL; _head=tmp; } else if(pos->_front && (!(pos->_next))) //删除最后一个结点 { Node *tmp=pos->_front; tmp->_next=NULL; _tail=tmp; } else //删除中间节点 { Node *front=pos->_front; Node *next=pos->_next; next->_front=front; front->_next=next; } delete pos; pos=NULL; } } void RemoveAll(DataType &x) { Node *cur=_head; Node *ret=this->FindNum(x); if(ret != _head) //可删除第一个结点不是要删除的元素 { while(cur) { Remove(x); cur=cur->_next; } } } void Sort() { int flag=1; Node *cur=_head; Node *tail=NULL; while(cur != tail) { while(cur->_next != tail) { if(cur->_data > cur->_next->_data) { DataType tmp=cur->_data; cur->_data=cur->_next->_data; cur->_next->_data=tmp; flag=0; } cur=cur->_next; } if(flag == 1) break; tail=cur; cur=_head; } } void Erase(Node *pos) { if((!(pos->_front)) && pos->_next) //删除第一个结点 { Node *tmp=pos->_next; tmp->_front=NULL; _head=tmp; } else if(pos->_front && (!(pos->_next))) //删除最后一个结点 { Node *tmp=pos->_front; tmp->_next=NULL; _tail=tmp; } else //删除中间节点 { Node *front=pos->_front; Node *next=pos->_next; next->_front=front; front->_next=next; } delete pos; pos=NULL; } private: Node *_head; Node *_tail; }; ostream& operator<<(ostream &os,LinkList &list) { Node *cur=list._head; while(cur) { os<<(*cur)<<" "; cur=cur->_next; } return os; }
在C++实现中如果遇到结点结构最好定义为struct,否则就会像上述情况一样需要声明多次友元,反而破坏了类的封装性
测试代码:
void menu() { cout<<"************1.尾插************2.尾删**************"<<endl; cout<<"************3.头插************4.头删**************"<<endl; cout<<"************5.指定位置后插****6.指定位置前插******"<<endl; cout<<"************7.删除指定元素****8.删除所有指定元素**"<<endl; cout<<"************9.排序************0.退出*************"<<endl; cout<<"************11.Erase**********0.退出*************"<<endl; } void test() { LinkList list; Node *ret=NULL; int input=1; DataType x,num; while(input) { menu(); cout<<"请输入您的选择>"; cin>>input; switch(input) { case 1: cout<<"请输入您要插入的数据>"; cin>>x; list.PushBack(x); break; case 2: list.PopBack(); break; case 3: cout<<"请输入您要插入的数据>"; cin>>x; list.PushFront(x); break; case 4: list.PopFront(); break; case 5: cout<<"请输入您要查找的数据>"; cin>>x; ret=list.FindNum(x); if(ret != NULL) { cout<<"请输入您要插入的数据>"; cin>>num; list.Insert(ret,num); } else { cout<<"您所查找的数据不存在"<<endl; } break; case 6: cout<<"请输入您要查找的数据>"; cin>>x; ret=list.FindNum(x); if(ret != NULL) { cout<<"请输入您要插入的数据>"; cin>>num; list.Insert(0,ret,num); //0用于占位,构成重载 } else { cout<<"您所查找的数据不存在"<<endl; } break; case 7: cout<<"请输入您要删除的数据>"; cin>>x; list.Remove(x); break; case 8: cout<<"请输入您要删除的数据>"; cin>>x; list.RemoveAll(x); break; case 9: list.Sort(); break; case 10: cout<<list<<endl; break; case 11: cout<<"请输入您要擦除的数据>"; cin>>x; ret=list.FindNum(x); if(ret != NULL) { list.Erase(ret); } else { cout<<"您所查找的数据不存在"<<endl; } break; case 0: break; default: cout<<"您的输入错误"<<endl; break; } } }
OVER
相关文章推荐
- 数据结构与算法学习 第1季02 链表的基本功能 C++实现
- C++ 实现链表的基本操作之一:链表插入
- C++ 单链表基本操作分析与实现
- 链表的建立和一些基本功能的实现
- C++实现链表的基本操作及测试用例
- 【C++/STL】list的实现(没有采用迭代器和空间配置器所实现的双向链表的基本功能)
- Queue类模板的链表实现(基本功能)
- 用C实现基本链表功能
- 数据结构--单链表基本功能实现程序…
- C++ 实现链表常用功能
- C++实现链表基本操作
- [C++]数据结构:有序链表SortedChain的基本实现与操作
- 使用C++实现链表的基本操作
- C++链式栈的简单实现(只有基本功能)
- 详细的单链表基本操作C/C++实现
- 双链表一些基本功能的简单实现
- C++实现shapefile文件的读写和基本功能的操作
- 【C++数据结构】模版类实现双循环链表的基本操作
- C++链表各功能实现