

1 //假设A,B为非空循环链表的尾指针
2 LinkList Connect(LinkList A,LinkList B)
3 {
4 LinkList p = A->next; //保存A表的头结点位置
5
6 A->next = B->next->next; //B表的开始结点链接到A表尾
7
8 free(B->next); //释放B表的头结点,初学者容易忘记
9
10 B->next = p;
11
12 return B; //返回新循环链表的尾指针
13 }

1 #include "stdio.h"
2
3 #define OK 1
4 #define ERROR 0
5 #define TRUE 1
6 #define FALSE 0
7
8 typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
9 typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int */
10
11 typedef struct Node
12 {
13 ElemType data;
14 struct Node *next;
15 }Node, *LinkList;
16
17 /* 初始化带头结点的空链表 */
18 Status InitList(LinkList *L)
19 {
20 *L = (LinkList)malloc(sizeof(Node)); /* 产生头结点,并使L指向此头结点 */
21
22 if(!(*L)) /* 存储分配失败 */
23 return ERROR;
24
25 (*L)->next=NULL; /* 指针域为空 */
26
27 return OK;
28 }
29
30 /* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
31 int ListLength(LinkList L)
32 {
33 int i=0;
34 LinkList p=L->next; /* p指向第一个结点 */
35 while(p)
36 {
37 i++;
38 p=p->next;
39 }
40 return i;
41 }
42
43 /* 随机产生n个元素的值,建立带表头结点的单链线性表L(头插法) */
44 void CreateListHead(LinkList *L, int n)
45 {
46 LinkList p;
47 int i;
48
49 srand(time(0)); /* 初始化随机数种子 */
50
51 *L = (LinkList)malloc(sizeof(Node));
52 (*L)->next = NULL; /* 建立一个带头结点的单链表 */
53
54 for (i=0; i < n; i++)
55 {
56 p = (LinkList)malloc(sizeof(Node)); /* 生成新结点 */
57 p->data = rand()%100+1; /* 随机生成100以内的数字 */
58 p->next = (*L)->next;
59 (*L)->next = p; /* 插入到表头 */
60 }
61 }
62
63 /* 随机产生n个元素的值,建立带表头结点的单链线性表L(尾插法) */
64 void CreateListTail(LinkList *L, int n)
65 {
66 LinkList p,r;
67 int i;
68
69 srand(time(0)); /* 初始化随机数种子 */
70 *L = (LinkList)malloc(sizeof(Node)); /* L为整个线性表 */
71 r = *L; /* r为指向尾部的结点 */
72
73 for (i=0; i < n; i++)
74 {
75 p = (Node *)malloc(sizeof(Node)); /* 生成新结点 */
76 p->data = rand()%100+1; /* 随机生成100以内的数字 */
77 r->next=p; /* 将表尾终端结点的指针指向新结点 */
78 r = p; /* 将当前的新结点定义为表尾终端结点 */
79 }
80
81 r->next = (*L)->next->next;
82 }
83
84 // 比较步数的方法
85 int HasLoop1(LinkList L)
86 {
87 LinkList cur1 = L; // 定义结点 cur1
88 int pos1 = 0; // cur1 的步数
89
90 while(cur1)
91 { // cur1 结点存在
92 LinkList cur2 = L; // 定义结点 cur2
93 int pos2 = 0; // cur2 的步数
94 while(cur2)
95 { // cur2 结点不为空
96 if(cur2 == cur1)
97 { // 当cur1与cur2到达相同结点时
98 if(pos1 == pos2) // 走过的步数一样
99 break; // 说明没有环
100 else // 否则
101 {
102 printf("环的位置在第%d个结点处。\n\n", pos2);
103 return 1; // 有环并返回1
104 }
105 }
106 cur2 = cur2->next; // 如果没发现环,继续下一个结点
107 pos2++; // cur2 步数自增
108 }
109 cur1 = cur1->next; // cur1继续向后一个结点
110 pos1++; // cur1 步数自增
111 }
112 return 0;
113 }
114
115 // 利用快慢指针的方法
116 int HasLoop2(LinkList L)
117 {
118 int step1 = 1;
119 int step2 = 2;
120 LinkList p = L;
121 LinkList q = L;
122
123 while (p != NULL && q != NULL && q->next != NULL)
124 {
125 p = p->next;
126 if (q->next != NULL)
127 q = q->next->next;
128
129 printf("p:%d, q:%d \n", p->data, q->data);
130
131 if (p == q)
132 return 1;
133 }
134 return 0;
135 }
136
137 int main()
138 {
139 LinkList L;
140 Status i;
141 char opp;
142 ElemType e;
143 int find;
144 int tmp;
145
146 i = InitList(&L);
147 printf("初始化L后:ListLength(L)=%d\n",ListLength(L));
148
149 printf("\n1.创建有环链表(尾插法) \n2.创建无环链表(头插法) \n3.判断链表是否有环 \n0.退出 \n\n请选择你的操作:\n");
150 while(opp != '0')
151 {
152 scanf("%c",&opp);
153 switch(opp)
154 {
155 case '1':
156 CreateListTail(&L, 10);
157 printf("成功创建有环L(尾插法)\n");
158 printf("\n");
159 break;
160
161 case '2':
162 CreateListHead(&L, 10);
163 printf("成功创建无环L(头插法)\n");
164 printf("\n");
165 break;
166
167 case '3':
168 printf("方法一: \n\n");
169 if( HasLoop1(L) )
170 {
171 printf("结论:链表有环\n\n\n");
172 }
173 else
174 {
175 printf("结论:链表无环\n\n\n");
176 }
177
178 printf("方法二:\n\n");
179 if( HasLoop2(L) )
180 {
181 printf("结论:链表有环\n\n\n");
182 }
183 else
184 {
185 printf("结论:链表无环\n\n\n");
186 }
187 printf("\n");
188 break;
189
190 case '0':
191 exit(0);
192 }
193 }
194
195 }