在写链表反转的时候很苦恼,感谢这位博主的图http://blog.csdn.net/u013271921/article/details/46382345
然后自己画了几遍,终于是理解了
/* 类模板双向链表,通过一个节点类node和一个链表类chlist来实现,node中包含前驱指针pr,后继指针nx,和数据域data,并且data可接受任意类型的数据 链表类chlist包含逆序创建链表操作,指定位置插入操作,指定位置删除操作,寻找指定位置元素操作和翻转链表等操作,并且包含指向链表的头指针、尾指针和表长 chlist中的成员函数: 1.Createlist逆序创建链表 2.insertz指定位置插入 3.erasez指定位置删除 4.findz输出并返回指定位置的元素 5.reversal反转链表 6.chlist创建空链表 7.~chlist析构函数 8.push_front头插 9.push_back尾插 10.pop_front头删 11.pop_back尾删 12.length输出并返回表长 13.clear清空链表 在下面的代码中 1.e代表T类型的元素 2.i代表位置 作者:chczy 2017/10/16 星期一 下午9:08 */ #include<iostream> #include<algorithm> #include<new> using namespace std; template<class T> struct node { node *pr;//前驱指针 node *nx;//后继指针 T data;//数据 };//节点类 //双向链表类 template<class T> class chlist { public: chlist(); ~chlist() { cout <<"destroy chlist. "<< endl; }; chlist& operator=(const chlist&); bool Createlist(int n);//创建空链表 node<T>* insertz(int i, T e);//在i位置插入元素d node<T>* erasez(int i);//删除i位置的元素 node<T>* findz(int i);//寻找i位置的元素 node<T>* reversal();//反转链表 node<T>* push_front(T e);//头插 node<T>* push_back(T e);//尾插 node<T>* pop_front();//头删 node<T>* pop_back();//尾删 bool empty();//检查链表是否为空 void clear();//将链表置空 void display();//输出链表的所有元素 int length(); private: node<T> *head;//头指针 node<T> *tail;//尾指针 int len;//表长 }; template<class T> chlist<T>::chlist()//creat a null list { head = NULL; tail = NULL; len = 0; } template<class T> bool chlist<T>::Createlist(int n)//不断在表头添加元素,逆序建立链表 { if (empty()) { node<T> *L = new node<T>; L->pr = NULL; L->nx = NULL; int i = n; while (n--) { node<T> *p = new node<T>; cin >> p->data; p->nx = L->nx;//接到后一个节点 p->pr = L; //反连接到头结点L L->nx = p; //L链接到新节点 if (i > n + 1)//当连接了2个节点以上时 p->nx->pr = p;//旧节点反链接到新节点 if (i == n + 1)//将第一个接入的节点设置为尾节点 tail = p; } head = L;//head指向头结点(第一个节点之前的节点) len = i;//存表长 return 1;//创建成功返回1 } else return 0;//否则返回0 } template<class T> node<T>* chlist<T>::insertz(int i, T e) { if (i > len+1) { throw"out of range!\n"; } if (i == 1&&len!=0)//如果要插入第一个位置 { node<T>* s=push_front(e);//则执行头插 return s; } else if (i == len+1&&len!=0)//如果要插入最后一个位置 { node<T>* s = push_back(e);//则执行尾插 return s; } else if (len == 0) { node<T> *s = new node<T>; s->data = e; head->nx = s; s->pr = head; s->nx = NULL; tail = s; ++len; } else { node<T>* p = head; int j = 0; while (p&&j <= i - 1) { p = p->nx; ++j; } node<T> *s = new node<T>; s->data = e; (p->pr)->nx = s; s->nx = p; s->pr = p->pr; p->pr = s; ++len; return s; } } template<class T> node<T>* chlist<T>::erasez(int i) { if (i > len&&i < 0) { throw"out of range!\n"; } if (i == 1&&len!=1) { node<T>* s = pop_front(); return s; } else if (i == len&&len != 1) { node<T>* s = pop_back(); return s; } if (len == 1) { node<T>* s = head->nx; head->nx = NULL; tail = NULL; delete s; --len; return head; } else//长度不为1,且删除位置不为头尾,即一般情况 { int j = 0; node<T> *p = head; while (p&&j <= i - 1)//寻找待删除节点 { p = p->nx; ++j; } node<T>* s = p->nx;//s为删除节点的后一节点 (p->pr)->nx = s;//删除节点的前一节点的后继更新为s s->pr = p->pr;//s的前驱更新为删除节点的前一节点 delete p;//删除p --len;//更新长度 return s;//返回删除节点的后一节点 } } template<class T> node<T>* chlist<T>::findz(int i) { if (i > len) { throw"out of range!\n"; } node<T> *p=head; int j = 0; while (p&&j <= i - 1) { p = p->nx; ++j; } cout <<i<< "位置的元素为:" << endl; cout << p->data << endl; return p; } template<class T> chlist<T>& chlist<T>::operator=(const chlist<T>& rhs) { head = rhs.head; tail = rhs.tail; len = rhs.len; return *this; } template<class T> node<T>* chlist<T>::reversal()//有问题 { node<T> *NH = NULL;//新头节点指针 node<T> *Prev = NULL;//前一个指针 node<T> *Node = head->nx;//节点指针 tail = head->nx;//原来的头指针变为尾指针 while (Node != NULL)//不遍历到最后一个(尾空) { node<T> *Next = Node->nx; if (Next == NULL)//Next指向了尾后 { node<T> *p = new node<T>; p->pr = NULL; p->nx = Node; NH = p; head = p;//更新头指针,为新的第一节点之前的指针 } Node->nx = Prev;//把Node的后继指针指向Node的元前一位元素 Node->pr = Next;//把Node的前驱指向Node的元后一位元素 Prev = Node;//更新Prev Node = Next;//更新Next } return NH;//返回头结点 } template<class T> bool chlist<T>::empty() { if (len == 0) return 1; else return 0; } template<class T> void chlist<T>::display() { if (len == 0) { cout << "null list!" << endl; return; } node<T> *p = head->nx; cout << "表中元素为:" << endl; while (p != tail) { cout << p->data << endl; p = p->nx; } cout << p->data << endl; cout << "表长为" << len << endl; } template<class T> void chlist<T>::clear() { while (!empty()) { erasez(1);} } template<class T> node<T>* chlist<T>::push_front(T e)//头插 { node<T>* s = new node<T>; s->data = e; s->nx = head->nx; head->nx = s; s->pr = head; (s->nx)->pr = s; ++len; return s; } template<class T> node<T>* chlist<T>::push_back(T e)//尾插 { node<T>* s = new node<T>; s->data = e; tail->nx = s; s->pr = tail; s->nx = NULL; tail = s; ++len; return s; } template<class T> node<T>* chlist<T>::pop_front()//头删 { node<T>* p = head->nx;//p指向第一个节点 node<T>* s = p->nx;//s指向第二个节点 head->nx = p->nx;//头结点的后继更新为第二个节点 (p->nx)->pr = head;//第二个节点的前驱更新为头结点 delete p;//删除第一个节点 --len;//更新长度 return s;//返回删除后的第一个节点的指针 } template<class T> node<T>* chlist<T>::pop_back()//尾删 { node<T> *p = tail;//p为最后一个节点 node<T> *s = tail->pr;//s为倒数第二个节点 s->nx = NULL;//s节点指向空,变为最后一个节点 tail = s;//尾节点更新为s delete p;//删除p --len;//更新长度 return s;//返回删除后的尾节点的指针s,此时s==tail } template<class T> int chlist<T>::length() { cout << "表长为:" << endl; cout << len << endl; return len; } //by chczy