单链表

【1】线性表的链式存储

线性表的顺序存储结构特点:

逻辑关系上相邻的两个元素在物理位置上也相邻;

可以随机存取任一元素,它的存储位置可用一个简单直观的公式表示。

然而,从另一个角度来看,这个优点也表明了这种存储结构的弱点:

在做插入或删除操作时,需要移动大量的元素。

 

线性表的链式存储不要求逻辑上相邻的元素在物理位置上也相邻。

因此,它没有顺序存储结构所具有的弱点,但同时也失去随机存取的优点。

另外一点:

链式存储的存储空间采用动态分配,不会存在分配不够用或者浪费的情况。

【2】链式存储结构

链式存储结构如下图:

【3】单链表的实现

1. list.h 头文件

 1 #ifndef _STDAFX_H
 2 #define _STDAFX_H
 3 
 4 #include <iostream>
 5 #include <malloc.h>
 6 #include <assert.h>
 7 
 8 typedef enum { ERROR = 0, OK}  Status;
 9 
10 typedef int ElemType;
11 
12 typedef struct _Node
13 {
14     ElemType data;
15     struct _Node *next;
16 } Node, *PNode, *Position;
17 
18 typedef struct 
19 {
20     PNode head, tail;
21     size_t size;
22 } List, *PList;
23 
24 
25 PList    InitList();
26 void    FreeNode(PNode p);
27 PNode    BuyNode(ElemType x, PNode pN = NULL);
28 
29 void    Print_List(PList _list);
30 void    DestroyList(PList _list);
31 void    ClearList(PList _list);
32 
33 void    Push_Back(PList _list, ElemType x);
34 void    Push_Front(PList _list, ElemType x);
35 void    Pop_Back(PList _list);
36 void    Pop_Front(PList _list);
37 
38 PNode    FindPreValue(PList _list, ElemType x);
39 PNode    FindPos(PList _list, int pos);
40 
41 Status    Remove(PList _list, ElemType x);
42 Status    RemoveAll(PList _list, ElemType x);
43 
44 Status    Erase(PList _list, size_t pos);
45 
46 Status    Insert(PList _list, int pos, ElemType x);
47 
48 void    Sort(PList _list);
49 void    Reverse(PList _list);
50 void    Merge(PList _list, PList _list1, PList _list2);
51 void    Link(PList _list, PList _list1);
52 
53 size_t    Size(PList _list);
54 
55 #endif
View Code

2. list.cpp 实现文件

  1 #include "List.h"
  2 using namespace std;
  3 
  4 // 购买节点    
  5 PNode BuyNode(ElemType x, PNode n)
  6 {
  7     PNode s = (PNode)malloc(sizeof(Node));
  8     assert(NULL != s); //断言函数
  9     s->data = x;
 10     s->next = n;
 11     return s;
 12 }
 13 // 释放节点
 14 void FreeNode(PNode p)
 15 {
 16     free(p);
 17     p = NULL;
 18 }
 19 // 初始化链表
 20 PList InitList()
 21 {
 22     PList p = (PList)malloc(sizeof(List));
 23     assert(p != NULL);
 24     p->size = 0;
 25     p->head = p->tail = BuyNode(0, NULL); //表明是有头结点的单链表
 26     return p;
 27 }
 28 // 后面插入数据
 29 void Push_Back(PList _list, ElemType x)
 30 {
 31     _list->tail = _list->tail->next = BuyNode(x, NULL);
 32     _list->size += 1;
 33 }
 34 // 前面插入数据
 35 void Push_Front(PList _list, ElemType x)
 36 {
 37     PNode s =_list->head->next = BuyNode(x, _list->head->next);
 38     if (NULL == s->next)
 39     {
 40         _list->tail = s;
 41     }
 42     _list->size += 1;
 43 }
 44 // 打印链表
 45 void Print_List(PList _list)
 46 {
 47     PNode p = _list->head->next;
 48     cout << "元素个数: " << _list->size << endl;
 49     while (p != NULL)
 50     {
 51         cout << p->data << " ";
 52         p = p->next;
 53     }
 54     cout << endl;
 55 }
 56 // 清空链表
 57 void ClearList(PList _list)
 58 {
 59     PNode q = NULL;
 60     PNode s = _list->head->next;
 61     while (s != NULL)
 62     {
 63         q = s;
 64         s = s->next;
 65         free(q);    //FreeNode(q);
 66     }
 67     _list->size = 0;
 68     _list->head->next = NULL;
 69     _list->tail = _list->head;
 70 }
 71 // 摧毁链表
 72 void DestroyList(PList _list)
 73 {
 74     ClearList(_list);
 75     free(_list->head);
 76     free(_list);
 77 }
 78 // 后面弹出
 79 void Pop_Back(PList _list)
 80 {
 81     PNode p = _list->head;
 82     //循环定位找最后节点的前驱
 83     while (p->next != NULL && p->next->next != NULL)
 84     {
 85         p = p->next;
 86     }
 87 
 88     if (p->next != NULL)
 89     {
 90         PNode q = p->next;
 91         p->next = NULL;
 92         _list->tail = p;
 93         free(q);    //FreeNode(q);
 94         _list->size -= 1;
 95     }
 96 }
 97 // 前面弹出
 98 void Pop_Front(PList _list)
 99 {
100     if (_list->head->next != NULL)
101     {
102         PNode q = _list->head->next;
103         _list->head->next = q->next;
104         free(q);    // FreeNode(p);
105         _list->size -= 1;
106         // 链表仅有一个元素
107         if (NULL == _list->head->next)
108         {
109             _list->tail = _list->head;
110         }
111     }
112 } 
113 // 查找某值前驱
114 PNode FindPreValue(PList _list, ElemType x)
115 {
116     PNode p = _list->head;
117     while (p->next != NULL && p->next->data != x)
118     {  
119         p = p->next;
120     }
121     
122     if (NULL == p->next)
123     {
124         p = NULL;
125     }
126 
127     return p;
128 }
129 // 删除某值
130 Status Remove(PList _list, ElemType x)
131 {
132     PNode p = FindPreValue(_list, x);  //找到前驱
133     if (NULL == p) 
134     {
135         return ERROR;
136     }
137 
138     PNode q = p->next;
139     p->next = q->next;
140 
141     _list->size -= 1;
142     return OK;
143 }
144 // 找某位置的节点
145 PNode FindPos(PList _list, int pos)
146 {
147     if (pos < -1) 
148         return NULL;
149     if (-1 == pos) 
150         return _list->head;
151 
152     int j = 0;
153     PNode p = _list->head->next;
154     while (j < pos && p != NULL)
155     {
156         p = p->next;
157         ++j;
158     }
159     return p;
160 }
161 // 删除某位置的值
162 Status Erase(PList _list, size_t pos)
163 {
164     if (pos >= _list->size)
165     {
166       cout<<"输入位置有误!!!"<<endl;
167     }
168     PNode p = FindPos(_list, pos - 1);   //找位置前驱
169     if (p == NULL || p->next == NULL)   //前者说明空链表//后者说明末节点
170     {
171         return ERROR;
172     }
173 
174     PNode q = p->next;
175     p->next = q->next;
176 
177     if (p->next == NULL)
178     {
179         _list->tail = p;
180     }
181     FreeNode(q);
182     --_list->size;
183     return OK;
184 }
185 // 按位置插入数据
186 Status Insert(PList _list, int pos, ElemType x)
187 {
188     PNode p = FindPos(_list, pos-1);
189     if (NULL == p)
190     {
191         return ERROR;
192     }
193     p->next = BuyNode(x, p->next);//顺利衔接
194     PNode s = p->next;
195     if (s->next == NULL)
196     {
197         _list->tail = s;
198     }
199     ++_list->size;
200     return OK;
201 }
202 // 逆置链表
203 void Reverse(PList _list)
204 {
205     if (_list->size >= 2)
206     {
207         PNode s = _list->head->next;
208         _list->tail = s;
209         PNode p = s->next;
210         s->next = NULL;
211         while (p != NULL)
212         {
213             s = p;
214             p = p->next;
215             s->next = _list->head->next;
216             _list->head->next = s;
217         }
218     }
219 }
220 // 合并
221 void Merge(PList _list, PList _list1, PList _list2)
222 {
223     PNode r = _list->head;
224     PNode p1 = _list1->head->next;
225     PNode p2 = _list2->head->next;
226     // 执行合并
227     while (p1 != NULL && p2 != NULL)
228     {
229         if (p1->data <= p2->data)
230         {
231             r->next = p1;
232             p1 = p1->next;
233         }
234         else
235         {
236             r->next = p2;
237             p2 = p2->next;
238         }
239         r = r->next;
240     }
241     // _list2先合并完成
242     if (p1 != NULL)
243     {
244         r->next = p1;
245         _list->tail = _list1->tail;
246     }
247     // _list1先合并完成
248     if (p2 != NULL)
249     {
250         r->next = p2;
251         _list->tail = _list2->tail;
252     }
253     // 合并数量
254     _list->size = _list1->size + _list2->size;
255     // 收尾
256     _list1->head->next = NULL;
257     _list1->tail = _list1->head;
258     _list1->size = 0;
259 
260     _list2->head->next = NULL;
261     _list2->tail = _list2->head;
262     _list2->size = 0;
263 }
264 //连接
265 void Link(PList _list, PList _list1)
266 {
267     _list->tail->next = _list1->head->next;
268     _list->tail = _list1->tail;
269     _list->size += _list1->size;
270 
271     _list1->head->next = NULL;
272     _list1->tail = _list1->head;
273     _list1->size = 0;
274 }
275 
276 /*
277  * 逆置方式2
278 void Reverse(PList _list)
279 {
280     PNode r = _list->head->next;
281     PNode s = r->next;
282     PNode p = s->next;
283     r->next = NULL;
284     _list->tail = r;
285     while (p != NULL)
286     {
287         s->next = r;
288         r = s;
289         s = p;
290         p = p->next;
291     }
292     s->next = r;
293     _list->head->next = s;
294 }
295 */
View Code

3. listmain.cpp 测试文件

  1 #include "List.h"
  2 using namespace std;
  3 
  4 #define UM_QUIT          0
  5 #define UM_INPUTR     1
  6 #define UM_INPUTH     2
  7 #define UM_PRINT      3
  8 #define UM_ERASE      4
  9 #define UM_REMOVE     5
 10 #define UM_POPFRONT   6
 11 #define UM_POPBACK    7
 12 #define UM_INSERT     8
 13 #define UM_REVERSE    9
 14 #define UM_MERGE      10
 15 #define UM_LINK          11
 16 
 17 #define ListNum0      0
 18 #define ListNum1      1
 19 #define ListNum2      2
 20 
 21 void main()
 22 {
 23     PList mylist, mylist1, mylist2;
 24     int select = 1, pos = 0, num = 0;
 25     ElemType item;
 26     mylist = InitList();
 27     mylist1 = InitList();
 28     mylist2 = InitList();
 29     while (select != 0)
 30     {
 31         cout << "		*********************菜单********************* " << endl;
 32         cout << "		**    1.输入数据r    2.输入数据h " << endl;
 33         cout << "		**    3.打印数据     4.位置删除 " << endl;
 34         cout << "		**    5.删除某值     6.前面弹出 " << endl;
 35         cout << "		**    7.后面弹出     8.位置插入 " << endl;
 36         cout << "		**    9.逆置链表     10.合并链表 " << endl;
 37         cout << "		**    11.连接链表    0.退出         " << endl;
 38         cout << "		**********************************************				" << endl;
 39         cout << "请选择" << endl;
 40         cin >> select;
 41         switch (select)
 42         {
 43         case UM_QUIT:
 44             break;
 45         case UM_INPUTR:
 46             {
 47                 cout << "请输入要操作的链表:" << endl;
 48                 cin >> num;
 49                 switch (num)
 50                 {
 51                 case ListNum0:
 52                     cout << "请输入数据并以-1结束" << endl;
 53                     while (cin >> item, item != -1)
 54                     {
 55                         Push_Back(mylist, item);
 56                     }
 57                     break;
 58                 case ListNum1:
 59                     cout << "请输入数据并以-1结束" <<endl;
 60                     while(cin >> item, item != -1)
 61                     {
 62                         Push_Back(mylist1, item);
 63                     }
 64                     break;
 65                 case ListNum2:
 66                     cout << "请输入数据并以-1结束" << endl;
 67                     while(cin >> item, item != -1)
 68                     {
 69                         Push_Back(mylist2,item);
 70                     }
 71                     break;
 72                 default:
 73                     cout << "选择错误 请重新选择" << endl;
 74                     break;
 75                 }
 76             }
 77             break;
 78         case UM_INPUTH:
 79             {
 80                 cout << "请输入要操作的链表:" << endl;
 81                 cin >> num;
 82                 switch (num)
 83                 {
 84                 case ListNum0:
 85                     cout << "请输入数据并以-1结束" << endl;
 86                     while(cin  >>item, item != -1)
 87                     {
 88                         Push_Front(mylist, item);
 89                     }
 90                     break;
 91                 case ListNum1:
 92                     cout << "请输入数据并以-1结束" <<endl;
 93                     while(cin>>item, item != -1)
 94                     {
 95                         Push_Front(mylist1, item);
 96                     }
 97                     break;
 98                 case ListNum2:
 99                     cout << "请输入数据并以-1结束" << endl;
100                     while(cin >> item, item != -1)
101                     {
102                         Push_Front(mylist2, item);
103                     }
104                     break;
105                 default:
106                     cout << "选择错误 请重新选择" <<endl;
107                     break;
108                 }
109             }
110             break;
111         case UM_PRINT:
112             {
113                 cout << "请输入要操作的链表:" << endl;
114                 cin >> num;
115                 switch (num)
116                 {
117                 case ListNum0:
118                     Print_List(mylist);
119                     break;
120                 case ListNum1:
121                     Print_List(mylist1);
122                     break;
123                 case ListNum2:
124                     Print_List(mylist2);
125                     break;
126                 default:
127                     cout << "选择错误 请重新选择" << endl;
128                     break;
129                 }
130             }
131             break;
132         case UM_ERASE:
133             cout << "请输入位置:" << endl;
134             cin >> pos;
135             Erase(mylist, pos);
136             break;
137         case UM_REMOVE:
138             cout << "请输入要删除的数据:" <<endl;
139             cin >> item;
140             Remove(mylist, item);
141             break;
142         case UM_POPFRONT:
143             Pop_Front(mylist);
144             break;
145         case UM_POPBACK:
146             Pop_Back(mylist);
147             break;
148         case UM_INSERT:
149             cout << "请输入要插入的数据及位置信息:" << endl;
150             cin >> item, pos;
151             Insert(mylist, pos, item);
152             break;
153         case UM_REVERSE:
154             Reverse(mylist);
155             break;
156         case UM_MERGE:
157             Merge(mylist, mylist1, mylist2);
158             break;
159         case UM_LINK:
160             Link(mylist, mylist1);
161             break;
162         default:
163             cout << "选择错误! 请重新选择" << endl;
164             break;
165         }
166     }
167     DestroyList(mylist);
168 }
View Code

以上代码分为三部分:头文件,实现文件,测试文件。

当时运行环境为VS2010。

Good Good Study, Day Day Up.

顺序  选择  循环  总结 

原文地址:https://www.cnblogs.com/Braveliu/p/3452258.html