单链表
【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
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 */
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 << "\t\t*********************菜单********************* " << endl;
32 cout << "\t\t** 1.输入数据r 2.输入数据h " << endl;
33 cout << "\t\t** 3.打印数据 4.位置删除 " << endl;
34 cout << "\t\t** 5.删除某值 6.前面弹出 " << endl;
35 cout << "\t\t** 7.后面弹出 8.位置插入 " << endl;
36 cout << "\t\t** 9.逆置链表 10.合并链表 " << endl;
37 cout << "\t\t** 11.连接链表 0.退出 " << endl;
38 cout << "\t\t**********************************************\t\t\t\t" << 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 }
以上代码分为三部分:头文件,实现文件,测试文件。
当时运行环境为VS2010。
Good Good Study, Day Day Up.
顺序 选择 循环 总结