01.#include <stdio.h>
02.#include <stdbool.h>
03.#include <stdlib.h>
04.typedef struct ElementData
05.{
06. int index;
07.} Item ;
08.
09.typedef struct node
10.{
11. Item item;
12. struct node * nextNode;
13.} Node;
14.
15.typedef Node * linkList ;
16.
17.Node * CreateInsertNode(Item *item) ;
18.
19.
20./*链表初始化 */
21.bool initList(linkList *plist)
22.{
23. *plist = (linkList)malloc(sizeof(Node));
24. if(*plist == NULL)
25. {
26. return false;
27. }
28. (*plist)->nextNode = NULL;
29. return true;
30.}
31.
32./*返回链表长度 */
33.int getListLength(linkList *plist)
34.{
35. int length = 0;
36. Node * node = (*plist)->nextNode;
37. while(node != NULL)
38. {
39. length ++;
40. node = node->nextNode;
41. }
42. return length;
43.}
44.
45./*返回在链表L中第一个与Item相同的元素的位序, 没有返回为0 */
46.//两个结构体不能用 == 直接进行比较
47.int locateElem(linkList L, int item)
48.{
49. int index = 0;
50. while(L)
51. {
52. index ++;
53. if(L->nextNode->item.index == item)
54. {
55. return index;
56. }
57. L = L->nextNode;
58. }
59. return index;
60.}
61.
62./*返回在链表L的index-1个位置的元素 */
63.//ndex-1个位置避免在index个位置插入的时候出错
64.Node * getNode(linkList *L, int index)
65.{
66. linkList p = (*L);
67.
68. int j = 1;
69. while(p != NULL && j < index)
70. {
71. p = p->nextNode;
72. j++;
73. }
74.
75. if(p == NULL || j > index)
76. {
77. fprintf(stderr, "要找的元素位置超出链表的长度.\n");
78. exit(EXIT_FAILURE);
79. }
80.
81. return p;
82.}
83.
84./*在链表L的index个位置插入item */
85.void listInsert(linkList *L, int index, Item *item)
86.{
87. //得到index-1的元素
88. linkList currentNode;
89. currentNode = getNode(L, index);
90.
91. //创建要插入的元素
92. linkList insertNode = CreateInsertNode(item) ;
93.
94. //插入到链表中
95. insertNode->nextNode = currentNode->nextNode;
96. currentNode->nextNode = insertNode;
97.}
98.
99./*把位于链表L的index个位置的元素删掉, 并用item返回其值 */
100.void listDelect(linkList *L, int index, Item *item)
101.{
102. //得到index-1的元素
103. linkList currentNode = getNode(L, index);
104.
105. //删掉元素
106. linkList delectNode = currentNode->nextNode;
107. currentNode->nextNode = delectNode->nextNode;
108. *item = delectNode->item;
109. free(delectNode);
110.}
111.
112./*头插入 */
113.void CreateListHead(linkList *L, Item *item)
114.{
115. //创建要插入的元素并初始化
116. Node *insertNode = CreateInsertNode(item) ;
117.
118. //插入
119. linkList head = *L;
120. insertNode->nextNode = head->nextNode;
121. head->nextNode = insertNode;
122.}
123.
124.
125./*尾插入 */
126.void CreateListTail(linkList *L, Item *item)
127.{
128. //创建初始化要插入的元素
129. linkList insertNode = CreateInsertNode(item) ;
130.
131. //找到最后一个元素
132. linkList list = (*L)->nextNode;
133. while(list->nextNode != NULL)
134. {
135. list = list->nextNode;
136. }
137.
138. //插入
139. list->nextNode = insertNode;
140.}
141.
142.
143./*删除 */
144.void ClearList(linkList *L)
145.{
146. linkList list = (*L)->nextNode ;
147. linkList p ;
148. while( list != NULL )
149. {
150. p = list->nextNode;
151. free(list);
152. list = p;
153. }
154. (*L)->nextNode = NULL;
155.}
156.
157./*输出链表 */
158.void listTraverse(linkList *L)
159.{
160. linkList p = (*L)->nextNode;
161. while(p)
162. {
163. printf("%d ,",p->item.index);
164. p = p->nextNode;
165. }
166.}
167.
168./*创建要插入的元素 返回创建的node指针 */
169.Node * CreateInsertNode(Item *item)
170.{
171. Node * insertNode = (linkList)malloc(sizeof(Node));
172. if(insertNode == NULL)
173. {
174. fprintf(stderr,"尾插入错误");
175. exit(EXIT_FAILURE);
176. }
177. insertNode->item = *item ;
178. insertNode->nextNode = NULL;
179. return insertNode;
180.}
181.
182./*单链表翻转/逆序 */
183.//current始终保持在第一位,pnext与prev遍历并完成交换。
184.void ListReverse(linkList *L)
185.{
186. linkList current; //当前节点
187. linkList next; //下一节点
188. linkList prev; //上一节点
189.
190. current = (*L)->nextNode;
191. next = current->nextNode;
192. current->nextNode = NULL;
193.
194. while(next){
195. prev = next->nextNode;
196. next->nextNode = current;
197. current = next;
198. next = prev;
199. }
200. (*L)->nextNode = current;
201.}
202.
203./*单链表翻转/逆序 */
204.//current始终是原链表的第一个数,然后把pnext不断移动到首位。
205.void ListReverse1(linkList *L)
206.{
207. linkList current; //当前节点
208. linkList next; //下一节点
209.
210. current = (*L)->nextNode;
211.
212. while(current->nextNode != NULL){
213. next = current->nextNode;
214. current->nextNode = next->nextNode;
215. next->nextNode = (*L)->nextNode;
216. (*L)->nextNode = next;
217. }
218.}
219.
220./*单链表翻转/逆序 */
221.//重新建立一个单链表newList,每次将L中的第一个结点放到newList后面
222.linkList ListReverse2(linkList *L)
223.{
224. linkList newlist = CreateInsertNode( &((*L)->item) );
225. if( (*L)->nextNode == NULL)
226. {
227. return NULL;
228. }
229. linkList firstNode;
230. while( (*L)->nextNode )
231. {
232. firstNode = newlist->nextNode;
233. newlist->nextNode = (*L)->nextNode;
234. (*L)->nextNode = (*L)->nextNode->nextNode;
235. newlist->nextNode->nextNode = firstNode;
236. }
237. free(*L);
238. return newlist;
239.}
240.
241.// 获取单链表倒数第N个结点值
242.//建立两个指针,第一个先走n步,然后第2个指针也开始走,
243.//两个指针步伐(前进速度)一致。当第一个结点走到链表末尾时,
244.//第二个节点的位置就是我们需要的倒数第n个节点的值。
245.void GetNthNodeFromBack(linkList *L, int n, Item *item)
246.{
247. linkList list = (*L)->nextNode;
248. linkList last = (*L)->nextNode;
249. int index = 1;
250.
251. while(list->nextNode != NULL && index < n)
252. {
253. index++;
254. list = list->nextNode;
255. }
256.
257. if(list->nextNode == NULL || index > n)
258. {
259. fprintf(stderr, "要找的元素位置超出链表的长度.\n");
260. exit(EXIT_FAILURE);
261. }
262.
263. while(list->nextNode != NULL)
264. {
265. list = list->nextNode;
266. last = last->nextNode;
267. }
268. *item = last->item;
269.}
270.
271.//找到链表的中间节点
272.void GetMidNode(linkList *L, Item *e)
273.{
274. linkList first = *L;
275. linkList second = *L;
276. //first移动的速度是second的2倍
277. while(first->nextNode){
278. if(first->nextNode->nextNode){
279. first = first->nextNode->nextNode;
280. second = second->nextNode;
281. }else{
282. first = first->nextNode;
283. }
284. }
285.
286. *e = second->item;
287.}
288.
289.//删除重复的节点
290.void RemoveDupNode(linkList *L)
291.{
292. linkList first = *L; //用于遍历链表
293. linkList second ;
294. linkList delNode ;
295.
296. while(first->nextNode){
297. second = first->nextNode; //从first后面开始遍历
298. while(second->nextNode){
299. //判断节点是否相等
300. if(second->nextNode->item.index == first->nextNode->item.index){
301. //删除节点
302. delNode = second->nextNode;
303. second->nextNode = delNode->nextNode;
304. free(delNode);
305. }else{
306. second = second->nextNode;
307. }
308. }
309. first = first->nextNode;
310. }
311.}
312.
313.//在单链表第n个位置建环
314.//找到环入口点first,把最后的指针curr指向first
315.void BulidListLoop(linkList *L, int num)
316.{
317. linkList first = *L;
318. linkList curr ;
319.
320. if(!first || num < 0){
321. fprintf(stderr,"建环失败.");
322. exit(EXIT_FAILURE);
323. }
324.
325. for(int i = 0; i < num; i++){
326. if(!first){
327. fprintf(stderr,"建环失败,超出链表长度.");
328. exit(EXIT_FAILURE);
329. }
330. first = first->nextNode;
331. }
332.
333. curr = first;
334.
335. while(curr->nextNode){
336. curr = curr->nextNode;
337. }
338.
339. curr->nextNode = first;
340.}
341.
342.//判断链表是否有环
343.//设两个工作指针,一个快一个慢,如果有环的话,它们会必然在某点相遇。
344.int hasLoop(linkList *L)
345.{
346. linkList first = *L;
347. linkList second = *L;
348.
349. while(first && second && second->nextNode){
350. first = first->nextNode;
351. if(second->nextNode){
352. second = second->nextNode->nextNode;
353. }
354. if(first == second){
355. return 1;
356. }
357. }
358.
359. return 0;
360.}
361.
362.//判断链表是否有环
363.//设两个工作指针p、q,p总是向前走,但q每次都从头开始走,
364.//对于每个节点,看p走的步数是否和q一样
365.int hasLoop1(linkList *L)
366.{
367. linkList first = *L;
368. int setp = 0;
369.
370. while(first){
371. setp ++;
372. linkList second = *L;
373. int index = 0;
374. while(second){
375. index ++;
376. if(first == second){
377. if(setp == index){ //步数相等说明没环
378. break;
379. }else{
380. return 1;
381. }
382. }
383. second = second->nextNode;
384. }
385. first = first->nextNode;
386. }
387.
388. return 0;
389.}
390.
391./*测试 */
392.int main(void)
393.{
394. linkList L;
395.
396. if(!initList(&L))
397. {
398. fprintf(stderr,"初始化错误");
399. exit(EXIT_FAILURE);
400. }
401. Item item1 = {
402. item1.index = 5
403. };
404.
405. Item item2 = {
406. item2.index = 6
407. };
408.
409. Item item3 = {
410. item3.index = 7
411. };
412.
413. Item item4 = {
414. item4.index = 6
415. };
416.
417. Item item5 = {
418. item5.index = 9
419. };
420.
421. Item item6 = {
422. item6.index = 4
423. };
424.
425. listInsert(&L,1,&item1);
426. listInsert(&L,2,&item2);
427. listInsert(&L,3,&item3);
428. listInsert(&L,4,&item4);
429. CreateListHead(&L, &item5);
430. CreateListTail(&L, &item6);
431.
432. int length = getListLength(&L);
433.// printf("length=%d\n",length);
434. listTraverse(&L); //显示
435./*
436. printf("\n");
437. linkList n = ListReverse2(&L); //翻转
438. listTraverse(&n); //显示
439.
440.
441. Item item5;
442. listDelect(&L,1,&item5);
443. int length1 = getListLength(&L);
444. printf("length1=%d\n",length1);
445. listTraverse(&L);
446.*/
447. Node * getnode ;
448. getnode = getNode(&L, 2);
449. printf("\n%d\n", getnode->nextNode->item.index);
450.
451. /*
452. Item i;
453. GetNthNodeFromBack(&L, 2,&i) ; 测试单链表倒数第N个结点值
454. printf("\n");
455. printf("%i",i.index);
456. */
457.
458. /*
459. Item i;
460. GetMidNode(&L, &i); 测试中间节点
461. printf("\n");
462. printf("%i",i.index);
463. */
464.
465. /*
466. RemoveDupNode(&L); 测试删除重复节点
467. printf("\n");
468. listTraverse(&L);
469. */
470.
471. /*
472. BulidListLoop(&L,2);
473. int i = hasLoop1(&L); 测试建环 检测是否有环
474. printf("\n%d",i) ;
475. */
476.// int index = locateElem(L,5);
477.// printf("%d",index);
478.
479. ClearList(&L);
480. return 0;
481.}