双向链表(C++实现)

wKioL1busLOTWsqhAAAI3EcuKqo751.png

//////////////////////////////////////////////////////////////////////////////////////
///////  这里建立两个类,一个节点类和一个List类,与单链表不同的是双向链表的节点要多一
//////   个前驱指针,相应的,双向链表函数实现要与单链表实现有所差异
 
    typedef int DataType;
 
    //struct LinkNode     //节点类(复合形态)
    //{
    //  friend class SList;
                  //将SList设为友元,便于SList类可以访问节点类的私有成员
    //public:
    //  LinkNode(const DataType x);  
    //private:
    //  DataType _data;    //节点的数据
    //  LinkNode* _next;    //指向该节点的下一个节点
    //      LinkNode* _prev;    //指向该节点的前一个节点
    //};
 
    //直接用struct定义LinkNode类,因为struct的成员默认为公有数据成员,所以可直接访问
    struct LinkNode      //节点类(建议写法)
    {
        LinkNode(const DataType x);
        DataType _data;    //节点的数据
        LinkNode* _next;    //后继指针
        LinkNode* _prev;      //前驱指针
    };
 
    class List    //链表类
    {
    public:
        List();         //构造函数
        List(const List& s);        //拷贝构造
        List &operator=(List& s);    //赋值运算符的重载
        ~List();
 
    public:
        void Reverse();
        void Swap(List& s);
        void PrintSList();   //打印链表
        void PushBack(const DataType& x);    //在尾部插入一个节点
        void Clear();         //链表置空
        void PopBack();
        void PushFront(DataType x);  //头插
        void PopFront();    //删除首节点
        void Insert(LinkNode* pos, DataType x);//固定位置插入一个节点
        void Erase(LinkNode* pos);        //删除某一节点
        LinkNode* Find(DataType x);       //查找节点并返回这个节点的地址
        int Amount();   //计算链表节点的数目
        void Remove(DataType x);     //查找某节点并删除
 
    private:
        LinkNode* _head;    //指向头结点
        LinkNode* _tail;    //指向尾节点
    };
List.h
  1   #include<iostream>
  2     using namespace std;
  3     #include<assert.h>
  4     #include"List.h"
  5  
  6     //节点类构造函数*
  7     LinkNode::LinkNode(const DataType x)
  8     :_data(x)
  9     , _next(NULL)
 10     , _prev(NULL)
 11     {}
 12  
 13     //链表类*
 14     List::List()         //构造函数
 15     : _head(NULL)
 16     , _tail(NULL)
 17     {}
 18      
 19     List::List(const List& s)          //拷贝构造
 20     : _head(NULL)
 21     , _tail(NULL)
 22     {
 23         if (s._head == NULL)
 24         {
 25             return;
 26         }
 27         LinkNode* tmp = s._head;
 28         while (tmp)
 29         {
 30             PushBack(tmp->_data);
 31             tmp = tmp->_next;
 32         } 
 33  
 34     }
 35      
 36     //赋值运算符的重载(传统方法)
 37     //SList & SList::operator=(const SList& s)    
 38     //{
 39     //  if (this != &s)
 40     //  {
 41     //      _head = NULL;
 42     //      _tail = NULL;
 43     //      LinkNode* tmp = s._head;
 44     //  do{
 45     //      PushBack(tmp->_data);
 46     //      tmp = tmp->_next;
 47     //       } while (tmp != s._head);
 48     //  }
 49     //  return *this; 
 50     //}
 51  
 52     //赋值运算符的重载(高效写法)*
 53     /*void SList::Swap(SList& s)
 54     {
 55     swap(_head, s._head);
 56     swap(_tail, s._tail);
 57  
 58     }
 59     SList&  SList::operator=(SList &s)
 60     {
 61     if (this != &s)
 62     {
 63     SList tmp(s);
 64     Swap(tmp);
 65     }
 66     return *this;
 67     }*/
 68  
 69     List&  List::operator=(List &s)     //赋值运算符的重载再优化(推荐写法)
 70     {
 71         if (this != &s)
 72         {
 73             swap(_head, s._head);
 74             swap(_tail, s._tail);
 75         }
 76         return *this;
 77     }
 78     List::~List()    //析构
 79     {
 80         Clear();
 81     }
 82  
 83     void List::Reverse()   //链表逆置(利用头插新节点的方法)
 84     {
 85         if (_head == NULL || _head== _tail)
 86         {
 87             return;
 88         }
 89         int ret = Amount();
 90  
 91     /*  //  方法一(相当于用头插的方式重新建立链表)
 92      _tail = new LinkNode(_head->_data);
 93         LinkNode* begin = NULL;
 94         LinkNode* tmp = _tail;
 95         while (--ret)
 96         {
 97             LinkNode* del = _head;
 98             _head = _head->_next;
 99             delete del;           
100             begin = new LinkNode(_head->_data);
101             begin->_next = tmp;
102             tmp->_prev = begin;
103             tmp = begin;
104         }
105         _head = begin;*/
106  
107     //////  方法二(只是交换对称位置节点的数据)**(高效)
108         LinkNode* begin = _head;
109         LinkNode* end = _tail;
110         while (ret)
111         {
112             if (end->_next == begin)
113                 break;
114             ret /= 2;
115             swap(begin->_data, end->_data);
116             begin = begin->_next;
117             end = end->_prev;
118         }
119      
120          /*// 方法三  交换前驱和后继指针
121           swap(_head, _tail);
122           LinkNode* cur = _head;
123           while (cur)
124           {
125               swap(cur->_prev,cur->_next);
126               cur = cur->_next;
127           }
128           */
129          
130     }
131  
132     //打印链表*
133     void List::PrintSList()
134     {
135         //头结点为空时,无需打印链表
136         if (_head == NULL)
137         {
138             cout << "This SList is Empty !" << endl;
139             return;
140         }
141         else
142         {
143             LinkNode* tmp = _head;  
144            while (tmp)
145            {
146                 cout << tmp->_data << "-->";
147                 tmp = tmp->_next;
148             } 
149             cout <<"NULL"<< endl;
150         }
151     }
152      
153     void List::PushBack(const DataType& x)    //在尾部插入一个节点*
154     {
155         //如果链表为空,插入节点后只有一个节点,此时_head=_tail
156         if (_head == NULL)
157         {
158             _head = new LinkNode(x);
159             _tail = _head;
160         }
161         else
162         {
163             _tail->_next = new LinkNode(x);
164             _tail->_next->_prev=_tail;
165             _tail = _tail->_next;
166         }
167     }
168      
169     void List::Clear()         //链表置空*
170     {
171         LinkNode* begin = _head;
172         while (begin != _tail)
173         {
174             _head = _head->_next;
175             delete begin;
176             begin = _head;
177         }
178         _head = NULL;
179         _tail = NULL;
180     }
181      
182     void List::PopBack()    //尾删
183     {
184         if (_head == NULL)
185         {
186             cout << "This SList is empty !" << endl;
187         }
188         else if (_head == _tail)
189         {
190             delete _head;
191             _head = NULL;
192             _tail = NULL;
193         }
194         else
195         {
196             LinkNode* cur = _head;
197             while (cur->_next != _tail)
198             {
199                 cur = cur->_next;
200             }
201             delete _tail;
202             _tail = cur;
203             _tail->_prev = cur->_prev;
204             _tail->_next = NULL;
205         }
206     }
207      
208     void List::PushFront(DataType x)  //头插*
209     {
210         if (_head == NULL)
211         {
212             PushBack(x);
213         }
214         else
215         {
216             LinkNode* tmp = _head;
217             _head = new LinkNode(x);
218             _head->_next = tmp;
219             tmp->_prev = _head;
220         }
221     }
222      
223     void List::PopFront()    //删除首节点
224     {
225         if (_head == NULL)
226         {
227             cout << "This SList is empty !" << endl;
228             return;
229         }
230         LinkNode* tmp = _head;
231         _head = _head->_next;
232         _head->_prev = NULL;
233         delete tmp;
234     }
235  
236     //固定位置插入一个节点(这个函数需和Find函数搭配使用)
237     //先用Find函数找到新节点需要插入的位置
238     //(将Find函数的返回值传给Insert函数的参数pos),再在pos节点后面插入新节点x
239     void List::Insert(LinkNode* pos, DataType x)   //*
240     {
241         assert(pos);
242         if (pos == _tail)
243         {
244             PushBack(x);
245         }
246         else
247         {
248             LinkNode* tmp = new LinkNode(x);
249             tmp->_next = pos->_next;
250             pos->_next = tmp;
251             tmp->_next->_prev = tmp;
252             tmp->_prev = pos;
253         }
254     }
255      
256         //删除某一节点,同样,要先找到该节点并传参给Erase函数
257     void List::Erase(LinkNode* pos)        
258     {
259         assert(pos);
260         if (pos == _tail)
261         {
262             PopBack();
263         }
264         else if (pos == _head)
265         {
266             PopFront();
267         }
268         else
269         {
270             pos->_prev->_next = pos->_next;
271             pos->_next->_prev = pos->_prev;
272             delete pos;
273         }
274     }
275      
276     //查找节点并返回这个节点的地址
277     LinkNode* List::Find(DataType x)       
278     {
279         if (_head == NULL)
280         {
281             cout << "This SList is empty !" << endl;
282             return NULL;
283         }
284         else
285         {
286             LinkNode* tmp = _head;
287             while (tmp != NULL)
288             {
289                 if (tmp->_data == x)
290                 {
291                     return tmp;
292                 }
293                 tmp = tmp->_next;
294             } 
295             return NULL;
296         }
297     }
298      
299     int List::Amount()   //计算链表节点的数目
300     {
301         if (_head == NULL)
302         {
303             return 0;
304         }
305         else
306         {
307             int count = 0;
308             LinkNode* cur = _head;
309             while (cur != _tail)
310             {
311                 count++;
312                 cur = cur->_next;
313             }
314             return ++count;
315         }
316     }
317      
318     void List::Remove(DataType x)      //查找某节点并删除
319     {
320         if (_head == NULL)
321         {
322             cout << "This SList is empty !" << endl;
323         }
324         else
325         {
326             LinkNode* tmp = Find(x);
327             if (tmp != NULL)
328             {
329                 Erase(tmp);
330             }
331         }
332     }
List.cpp
 1 #include"List.h"
 2 #include<stdlib.h>
 3 #include<iostream>
 4 using namespace std;
 5  
 6     void Test1()
 7     {
 8         List list1;
 9         list1.PushBack(1);
10         list1.PushBack(2);
11         list1.PushBack(3);
12         list1.PushBack(4);
13         list1.PushBack(5);
14         list1.PushBack(6);
15         list1.PrintSList();
16  
17     /*  List list2(list1);
18         list2.PrintSList();*/
19  
20         List list2=list1;
21         list2.PrintSList();
22         //list2.PopBack();
23         //list2.Clear();
24         //list2.PushFront(0);
25         //list2.PopFront();
26  
27         //////检验Find函数
28         ////LinkNode* ret=list2.Find(4);
29         ////if (ret != NULL)
30         ////{
31         ////    cout << "ret:" << ret << " " << ret->_data << endl;
32         ////}
33         ////else
34         ////{
35         ////    cout << "Not exit !" << endl;
36         ////}
37          
38     /*  int ret=list2.Amount();
39         cout << ret << endl;*/
40  
41         //list2.Erase(list2.Find(5));
42         //list2.Insert(list2.Find(2), 0);
43         //list2.Remove(3);
44         list2.Reverse();
45         list2.PrintSList();
46     }
47  
48     int main()
49     {
50         Test1();
51         system("pause");
52     }
Test.cpp

 

posted @ 2016-04-16 14:15  ProLyn  阅读(6228)  评论(0编辑  收藏  举报