一:特殊要求的结点删除
问题描述:假设有一个没有头指针的单链表。一个指针指向此单链表中间的一个结点(不是第一个,也不是最后一个)。请将该节点从单链表中删除。
思路:根据题意,似乎很难完成。其实我们可以将当前结点的后续结点的值域赋值给当前结点的值域。然后再删除当前结点的后续结点,即可完成”狸猫换太子“。代码如下:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <time.h>
5
6 typedef struct tag
7 {
8 int Nnum_;
9 struct tag *Nnext_;
10 }Node, *pNode;
11
12
13 void link_print(pNode phead)
14 {
15 while(phead != NULL)
16 {
17 printf("%4d", phead->Nnum_);
18 phead = phead->Nnext_;
19 }
20 printf("\n");
21 }
22 //头插法
23 void link_init_tail(pNode *phead, int size) //传的是地址
24 {
25 pNode pNew = NULL;
26 pNode pTail = NULL;
27
28 while( size > 0)
29 {
30 //申请内存
31 pNew = (pNode)malloc(sizeof(Node)); //注意这里为何不用pNode而用Node,因为sizeof(pNode) = 4
32 //赋值
33 pNew->Nnum_ = rand()%1000;
34 //插入链表
35 if(*phead == NULL) //链表为空时
36 {
37 *phead = pNew;//连接新的结点
38 pTail = pNew;
39 }
40 else//不为空
41 {
42 pTail->Nnext_ = pNew ; //连接新的结点
43 pTail = pNew; //改名字
44 }
45 size --;
46 }
47 }
48
49 int delete_special_pos(pNode *phead) //为了验证结果而将其打印出来,我们采用带有头指针的链表
50 {
51 if(*phead == NULL && (*phead)->Nnext_ == NULL)
52 return 0;
53 int i = 1;//为了叙述方便,我们假设其位置是3
54
55 pNode pCur = *phead;
56 while( i < 3) //使pCur指向第三个结点
57 {
58 pCur = pCur->Nnext_;
59 i ++;
60 }
61 //删除第三个结点的int值
62 pNode pNext = pCur->Nnext_; //建立初始值
63 //我们要把pNext所指向结点int值放到pCur中,然后再删除pNext。此刻就完成了“狸猫换太子”
64 pCur->Nnext_ = pNext->Nnext_;
65 pCur->Nnum_ = pNext->Nnum_;
66 free(pNext);
67 pNext = NULL; //防止野指针的出现
68 return 1;
69 }
70
71 int main(int argc, char const *argv[])
72 {
73 srand(time(NULL));
74 pNode phead = NULL;
75 link_init_tail(&phead, 10);
76 link_print(phead);
77
78 printf("ret:%d\n",delete_special_pos(&phead) );
79 link_print(phead);
80
81 return 0;
82 }
View Code
二:编码实现环状单向链表(尾指针直接指向头指针,中间没有空结点),去除连续的重复元素的操作。(2012,人人)
比如:1(头)->2 ->2 ->3 ->3 ->1 ->1(头),去除以后的结果是 1 ->2 ->3(注意头部的 1 也要去掉一个);
思路:
1、如果该链表为空或者长度为1,则直接返回。
2、遍历一次循环单向链表,删除连续的重复的结点;
3、判断最后一个结点是否和第一个结点值相同:
一)若相同,删除最后一个结点,并且返回头结点;
二)若不相同,直接返回头结点。
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <time.h>
5 #include <assert.h>
6
7 typedef struct tag
8 {
9 int Nnum_;
10 struct tag *Nnext_;
11 }Node, *pNode;
12
13
14 void link_print(pNode phead, int size)
15 {
16 int i= 1;
17 while(phead != NULL)
18 {
19 printf("%2d", phead->Nnum_);
20 phead = phead->Nnext_;
21 if( ++i > size)
22 break;
23 }
24 printf("\n");
25 }
26 //尾插法
27 void link_init_tail(pNode *phead, int size) //传的是地址
28 {
29 pNode pNew = NULL;
30 pNode pTail = NULL;
31
32 while( size > 0)
33 {
34 //申请内存
35 pNew = (pNode)malloc(sizeof(Node)); //注意这里为何不用pNode而用Node,因为sizeof(pNode) = 4
36 //赋值
37 //pNew->Nnum_ = rand()%5;
38 pNew->Nnum_ = 1;
39
40 //插入链表
41 if(*phead == NULL) //链表为空时
42 {
43 *phead = pNew;//连接新的结点
44 pTail = pNew;
45 }
46 else//不为空
47 {
48 pTail->Nnext_ = pNew ; //连接新的结点
49 pTail = pNew; //改名字
50 }
51 size --;
52 }
53 //生成一个首尾相连的环
54 pTail->Nnext_ = *phead;
55 }
56
57 pNode unique( pNode phead)
58 {
59 //如果该链表为空或者长度为1,则直接返回。
60 if( phead == NULL || phead->Nnext_ ==NULL)
61 return phead;
62
63 //遍历一次循环单向链表,
64 pNode pCur = phead;
65 pNode pNext = pCur->Nnext_;
66
67 while(pNext != phead)
68 {
69 //删除连续的重复的结点
70 while(pCur->Nnum_ == pNext->Nnum_ && pNext != phead)
71 {
72 pCur->Nnext_ = pNext->Nnext_;
73 free(pNext);
74 pNext= pCur->Nnext_;
75 }
76
77 if( pNext == phead) //判断最后一个结点是否和第一个结点值相同
78 break;
79 //int值不相等-->向后移动
80 pCur = pNext;
81 pNext = pNext->Nnext_;
82 }
83
84 if( pCur->Nnum_ == pNext->Nnum_)
85 {
86 //所有值域全部相同
87 if(pNext == pCur)
88 {
89 printf("All the link's elements are equal\n");
90 printf("the value is:%d\n",pNext->Nnum_);
91 //free(pNext);// 为什么加上这两句就错了?
92 //pNext = NULL;
93 return pCur;
94 }
95 //存在值域不相同的结点->此时剩余的结点组成一个循环链表
96 pCur->Nnext_ = pNext->Nnext_;
97 free(pNext);
98 return pCur;
99 }
100 //不相等,这时pNext == *phead
101 return pNext;
102 }
103
104 int main(int argc, char const *argv[])
105 {
106 srand(time(NULL));
107 pNode phead = NULL;
108 link_init_tail(&phead, 10); //10为初始链表的长度
109 link_print(phead,15);
110
111 pNode pRet = unique(phead);
112
113 link_print(pRet, 10);
114 return 0;
115 }
View Code
链表的快慢指针的使用,详见下篇:链表三——快慢指针的使用