标签:
博客介绍了C语言,以及C++的单向链表。那么我们今天介绍的双向链表,顾名思义,就是数据本身具备了左边和右边的双向指针。双向链表相比较单向链表,主要有下面几个特点:
(1)在数据结构中具有双向指针
(2)插入数据的时候需要考虑前后的方向的操作
(3)同样,删除数据的是有也需要考虑前后方向的操作
那么,一个非循环的双向链表操作应该是怎么样的呢?我们可以自己尝试一下:
源代码:
#include <iostream> using namespace std; typedef int DataType; class LinkNode { friend class List; public: LinkNode(const DataType& x) :_data(x) ,_next(NULL) ,_prev(NULL) {} ~LinkNode() { } protected: DataType _data; // 数据 private: LinkNode* _prev; // 前驱 LinkNode* _next; // 后继 }; class List { public: List() :_head(NULL) ,_tail(NULL) {} ~List() {} List(const List& l) {} List& operator=(const List& l); public: void Print() { LinkNode *begin=_head; while (begin) { cout<<begin->_data<<"->"; begin=begin->_next; } cout<<"NULL"<<endl; } void PushBack(const DataType& x) { // 1.空链表 // 2.一个或以上节点 if(_head == NULL) { _head=new LinkNode(x); _tail=_head; } else { _tail->_next=new LinkNode(x); _tail->_next->_prev=_tail; _tail=_tail->_next; } } void PopBack() { // 1.空链表 // 2.一个节点 // 3.两个及以上节点 if (_head ==NULL) { return ; } if (_head == _tail) { delete _head; _head = NULL; _tail = NULL; } else { LinkNode* del=_tail; _tail=_tail->_prev; _tail->_next=NULL; //_tail->_prev=_tail->_prev; 此句功能包含在_tail=_tail->_prev;中!! delete del; /*tail=_tail->_prev; delete _tail->_next; _tail->_next=NULL;*/ } } void PushFront(const DataType& x) { //1.空链表 //2.非空链表 if(_head == NULL) { _head=new LinkNode(x); _tail=_head; } else { LinkNode *tmp = new LinkNode(x); tmp->_next=_head; _head->_prev=tmp; tmp->_prev = NULL; _head=tmp; } } void PopFront() { // 1.空链表 // 2.一个节点 // 3.两个及以上节点 if (_head == NULL) { return ; } if (_head == _tail) { delete _head; _head = NULL; _tail = NULL; } if(_head != _tail) //链表清空之后的判断,否则出现内存访问冲突 { LinkNode *del =(_head); _head=_head->_next; _head->_prev=NULL; delete del; } } //插入 void Insert(LinkNode* pos, const DataType& x) { // 1.空链表 // 2.尾部插入 // 3.中间插入 if (_head == NULL) { _head=new LinkNode(x); _tail=_head; } if(pos == _tail) { PushBack(x); } else { LinkNode *tmp=new LinkNode(x); pos->_prev->_next=tmp; pos->_next->_prev=tmp; tmp->_prev=pos->_prev; tmp->_next=pos->_next; } } //查找 LinkNode* Find(const DataType& x) { if (_head == NULL) { return NULL; } LinkNode* begin = _head; while(begin != NULL) { if(begin->_data == x) { return begin; } else { begin = begin->_next ; } } return NULL; cout<<"没有找到该节点"<<endl; } //删除 void Erase(LinkNode* del) { //1.空链表 if(_head == NULL) { return ; } else { //2.一个节点且是删除节点 if ((_head == _tail) && (_head == del)) { delete _head; _head=NULL; _tail=NULL; } else {//3.多个节点 //del为头 if (_head == del) { PopFront(); /*_head=_head->_next; _head->_prev=NULL; delete _head->_prev;*/ } else { //del在尾 if(del == _tail) { PopBack(); /*del->_prev->_next=NULL; _tail=del->_prev; delete del;*/ } //del在中 else { del->_prev->_next=del->_next; del->_next->_prev=del->_prev; delete del; } } } } } void remove(DataType * x) { LinkNode *ret=Find(*x); Erase(ret); } //逆置 void Reverse() { LinkNode* tmp1 = _head; LinkNode* tmp2 = _tail; while(tmp1 != tmp2 && tmp2->_next != tmp1) { DataType a = tmp1->_data ; tmp1->_data = tmp2->_data ; tmp2->_data = a; tmp1 = tmp1->_next ; tmp2 = tmp2->_prev ; } } private: LinkNode* _head; LinkNode* _tail; }; void Test1() { List l1; l1.PushBack(1); l1.PushBack(2); l1.PushBack(3); l1.PushBack(4); l1.Print(); LinkNode* ret = l1.Find(4); //cout<<"ret:"<<ret->_data<<endl; //测试失败“LinkNode::_data”: 无法访问 protected 成员(在“LinkNode”类中声明) //l1.PopBack(); //l1.PopBack(); //l1.PopBack(); //l1.PopBack(); //l1.PopBack(); //l1.Insert(s,3); //l1.PopFront(); //l1.PopFront(); //l1.PopFront(); //l1.PopFront(); //l1.PopFront(); /*l1.PushFront(0); l1.Print();*/ //l1.Erase(ret); //l1.Reverse(); /*DataType x=3; l1.remove(&x);*/ l1.Print(); } void Test2() { List l1; l1.PushFront(1); l1.PushFront(2); l1.PushFront(3); l1.PushFront(4); l1.Print(); l1.PopFront(); l1.PopFront(); l1.PopFront(); l1.PopFront(); l1.PopFront(); l1.Print(); } int main() { Test1(); //Test2(); getchar(); return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/zhangchaoq/article/details/48135799