1 //单链表:通过各结点的链接指针来表示结点间的逻辑关系,长度可扩充,遍历或查找
2 //只能从指针的指示的首元结点开始,跟随链接指针逐个结点进行访问,进行删除或插
3 //入时,只需修改相关结点的指针域,但链接表比顺序表需要的存储空间多
4
5
6 //单链表的结构定义
7 typedef int DataType;
8 typedef struct node
9 {
10 DataType data;//链表结点
11 struct node* link;//数据域
12 }LinkNode, *LinkList;//链接指针域
13
//头指针,包含0个或多个结点,空表为0个结点
14 //单链表中的插入与删除
15 //单链表插入算法
16 int Insert(LinkList& first, int i, DataType x)
17 {
18 //将新元素x插入到第i个结点位置,i从1开始,i=1表示插入到原首元结点之前
19 if(!first || i==1)//插入到空表或非空表首元结点前
20 {
21 LinkNode *newNode = new LinkNode;//建立一个新结点
22 if(!newNode)
23 {
24 cerr<<"存储分配错误!\n";
25 exit(1);
26 }
27 newNode->data = x;
28 newNode->link = first;//新结点成为第一个结点
29 first = newNode;
30 }
31 else//插入到链中间或尾部
32 {
33 LinkNode *p = first;//从第一个结点开始检测
34 int k = 1;
35 while(p != NULL && k<i-1)//循环找第i-1个结点
36 {
37 p = p->link;
38 k++;
39 }
40 if(p == NULL && first)//非空表且链太短
41 {
42 cerr<<"无效的插入位置!"<<endl;
43 return 0;
44 }
45 else
46 {
47 LinkNode *newNode = new LinkNode;//建立一个新结点
48 if(!newNode)
49 {
50 cerr<<"存储分配错误!"<<endl;
51 exit(1);
52 }
53 newNode->data = x;
54 newNode->link = p->link;
55 p->link = newNode;
56 }
57 }
58 return 1;//正常插入
59 }
60
61 //单链表删除算法
62 int Remove(LinkList& first, int i, DataType& x)
63 {
64 //将链表中的第i个元素删去,i从1开始,引用型参数x返回被删元素的值
65 LinkNode *q, *p;
66 int k;
67 if(i<=1)//删除首元结点时表头退到下一个结点
68 {
69 q = first;
70 first = first->link;
71 }
72 else
73 {
74 p = first;
75 k = 1;
76 while(p != NULL && k<i-1)//循链找第i-1号结点
77 {
78 p=p->link;
79 k++;
80 }
81 if(p == NULL || p->link == NULL)//空表或者链太短只有头结点
82 {
83 cerr<<"无效的删除位置!\n";
84 return 0;
85 }
86 q = p->link;//保存第i号结点的地址
87 p->link = q->link;//第i-1号结点与第i+1号结点链接
88 }
89 x = q->data;//取出被删除结点中的数据值
90 delete q;//并删除
91 return 1;
92 }
97带头结点,头结点data域不存储任何信息, 空表为头结点
//带头结点的单链表
98 //头结点的data域不存储任何信息。把头结点当第0个结点,带头结点的单链表
99 //简化了链表的插入与删除操作代码的实现
100
101 //初始化单链表
102 void initList(LinkList &first)
103 {
104 first =new LinkNode;//创建头结点
105 if(!first)
106 {
107 cerr<<"存储分配失败!\n";
108 exit(1);
109 }
110 first->link = NULL;//置空
111 }
112
113 //清空单链表
114 void clearList(LinkList &first)
115 {
116 LinkNode *q;
117 while(first->link != NULL)//当链不空时,删去链中的所有结点
118 {
119 q = first->link;
120 first->link = q->link;//保存被删结点,从链上摘下该结点
121 delete q;//删除(仅留一个头结点)
122 }
123 }
124
125 //计算表的长度
126 int Length(LinkList &first)
127 {
128 LinkNode *p = first->link;
129 int count = 0;
130 while(p != NULL)//循链扫描,计算结点数
131 {
132 p = p->link;
133 count++;
134 }
135 return count;
136 }
137
138 //判断单链表是否为空。如果表空,则函数返回1,否则函数返回0
139 int isEmpty(LinkList &first)
140 {
141 return (first->link == NULL);
142 }
143
144 //在单链表中查找与x匹配的元素,查找成功时函数返回该结点地址,否则返回NULL值
145 LinkNode* Search(LinkList& first, DataType x)
146 {
147 LinkNode *p = first->link;
148 while(p != NULL && p->data != x)//循链逐个找含x的结点
149 p = p->link;
150 return p; //返回指针p的内容(地址)
151 }
152
153 //在单链表中对第i(0<=i)个结点定位。函数返回表中第i个结点的地址
154 //若i<0或i超出表中结点个数,则返回NULL
155 LinkNode* Locate(LinkList& first, int i)
156 {
157 if(i<0)//找头结点时,i<0不合理
158 return NULL;
159 LinkNode *p = first;
160 int k = 0;
161 while(p != NULL && k<i)//循链找第i个结点,k做结点计数
162 {
163 p = p->link;
164 k++;
165 }
166 return p;//返回NULL,表示i值太大,返回结点地址
167 }
168
169 //将新元素x插入在表中第i(1<=i)个结点位置。如i不合理则函数返回0,否则函数返回1
170 int Insert(LinkList& first, int i, DataType x)
171 {
172 LinkNode *p = Locate(first, i-1);//定位于第i-1个结点
173 if(p == NULL)//i不合理,插入不成功
174 return 0;
175 LinkNode *s = new LinkNode;//创建一个新结点
176 if(!s)
177 {
178 cerr<<"存储分配错误\n";
179 exit(1);
180 }
181 s->data = x;
182 s->link = p->link;//将*s链接在*p之后
183 p->link = s;//插入成功
184 return 1;
185 }
186
187 //将链表中的第i个元素删去,通过引用型参数x返回该元素的值
188 //如果i不合理则函数返回0,否则返回1
189 int Remove(LinkList& first, int i, DataType& x)
190 {
191 LinkNode *p = Locate(first, i-1);//定位于i-1第个结点
192 if(p == NULL || p->link == NULL)
193 return 0;
194 LinkNode *q = p->link;//用q保存被删结点地址
195 p->link = q->link;//重新链接,将被删结点从链中摘下
196 x = q->data;//取出被删结点中的数据
197 delete q;//释放结点
198 return 1;//删除成功
199 }
200
201 //函数假定链表first1已存在且为空,即first1的头结点已创建且
202 //first1->link == NULL
203 //复制链表first2的全部结点到空链表first1
204 void Copy(LinkList& first1, LinkList& first2)
205 {
206 LinkNode *srcptr = first2->link;//srcptr是源链指针
207 LinkNode *destptr = first1;//destptr是目标链尾指针
208 while(srcptr->link != NULL)//逐个结点复制
209 {
210 destptr->link = new LinkNode;//新结点链入目标链尾
211 if(!destptr)
212 {
213 cerr<<"存储分配失败!\n";
214 exit(1);
215 }
216 destptr = destptr->link;
217 destptr->data = srcptr->data;//结点数据传送
218 srcptr = srcptr->link;//传送源链下一结点数据
219 }
220 destptr->link = NULL;//目标链收尾
221 }
222
223
224 //实例,一个非空链表first,在first中正向输出所有结点的值,其递归算法为:
225 //正向输出链表各结点值的递归算法
226 void write(LinkNode *first)
227 {
228 if(first == NULL)//递归到底,空表返回
229 return;
230 cout<<first->data<<endl;//输出当前结点的值
231 write(first->link);//以下一个结点为表头继续递归输出
232 }
233 //正向输出非递归算法
234 void write(LinkNode *first)//非递归(迭代)算法
235 {
236 while(first->link != NULL)//循环输出到链空
237 {
238 cout<< first->link->data <<endl;//链表非空,输出结点数据
239 first = first->link;//继续输出下一结点
240 }
241 }
245 //尾插法创建单链表
246 void insertRear(LinkList& first, LinkNode* & last, DataType endTag)
247 {
248 //endTag是约定的输入序列结束标志,如果输入序列是正整数,endTag可以是0或负数
249 //如果输入序列是字符,engTag可以是字符集中不会出现的字符,入"\0".
250 DataType val;
251 cin>>val;
252 if(val == endTag)//链表收尾,停止创建
253 last->link = NULL;
254 else
255 {
256 last = new LinkNode;//创建新结点
257 if(!last)
258 {
259 cerr<<"存储分配错误!\n";
260 exit(1);
261 }
262 last->data = val;//last结点赋值
263 insertRear(first, last->link, endTag);//递归创建后续链表
264 }
265 }
266 void main(void)
267 {
268 LinkList *L = new LinkNode;
269 if(!L)
270 {cerr<<"内存分配错误!\n"; exit(1);}
271 cin>>L->data;
272 LinkNode *rear = L;
273 insertRear(L, rear->link, L->data);
274 }
275
276
277
278 //前插法创建一个单链表
279 void insertFront(LinkList& first, DataType endTag)
280 {
281 DataType val;
282 cin>>val;
283 if(val == endTag)//链表数据输入结束,停止创建
284 return;
285 LinkNode *s = new LinkNode;//创建新结点
286 if(!s)
287 {cerr<<"存储分配错误\n"; exit(1);}
288 s->data = val;//s结点赋值
289 s->link = first->link;//作为首元结点
290 first->link = s;//链入头结点之后
291 insertFront(first, endTag);//递归创建链表
292 }
293 void main(void)
294 {
295 LinkList *L = new LinkNode;
296 if(!L)
297 {cerr<<"存储分配错误\n"; exit(1);}
298 cin>>L->data;//输入约定的输入序列结束标志
299 L->link = NULL;//链表置空
300 insertFront(L, L->data);//递归建立单链表
301 }