线性表:循环链表
1 来自https://www.bilibili.com/video/av2975983/?p=17&t=13 2 个人感悟:循环链表的插入与删除与普通链表的区别就是在一个结点 而且初始化功能循环链表的头指向尾则代表空 普通链表头指针指针域指向NULL为空 3 4 //算法描述 5 //链表存储结构定义 6 typedef struct CLinkList 7 { 8 int data; 9 struct ClinkList *next; 10 }node; 11 #define LEN sizeof(node) 12 //初始化循环链表 13 void ds_init(node **pNode) 14 { 15 int item; 16 node *temp; 17 node *target; 18 19 printf("输入结点的值,输入0完成初始化"); 20 21 while(1) 22 { 23 scanf("%d",&item); 24 25 if(item == 0) 26 return; 27 28 if((*pNode) == NULL) 29 {//循环链表只有一个结点 30 *pNode = (node *)malloc(LEN); 31 if(!(*pNode)) 32 exit(1); 33 (*pNode)->data = item; 34 (*pNode)->next = *pNode; 35 } 36 else 37 { //target最终指向最后一个结点 38 for(target = (*pNode);target->next != (*pNode);target = target->next) 39 40 temp = (node *)malloc(LEN); 41 if(!temp) 42 exit(1); 43 44 temp->data = item; 45 temp->next = *pNode; 46 target->next = temp; 47 } 48 } 49 } 50 51 //插入结点 52 void ds_insert(node **pNode,int i)//参数:链表的第一个结点,插入的位置 53 { 54 node *temp; 55 node *target; 56 node *p; 57 int item; 58 int j = 1; 59 60 printf("输入要插入结点的值:"); 61 scanf("%d",&item); 62 63 if(i == 1) 64 { //新插入的结点作为第一个结点 65 temp = (node *)malloc(LEN); 66 67 if(!temp) 68 exit(1); 69 70 temp->data = item; 71 //寻找最后一个结点 72 for(target = (*pNode); target->next != (*pNode); target = target->next); 73 74 temp->next = (*pNode); 75 target->next = temp; 76 *pNode = temp; 77 } 78 else 79 { 80 target = *pNode; //target指向第一个元素 81 82 for(j; j < (i-1); j++)//找到要插入的位置 83 { 84 target = target->next; 85 } 86 target = (node *)malloc(LEN); 87 88 if(!temp) 89 exit(0); 90 91 temp->data = item; 92 p = target->next; //p作为中间变量 93 target->next = temp; //target指向新插入的结点 94 temp->next = p; //新插入的结点指向 p中存的是旧版本的第i个位置的结点 95 } 96 } 97 //删除结点 98 void ds_delete(node **pNode,int i) 99 { 100 node *target; 101 node temp; 102 int j = 1; 103 104 if(i == 1) 105 { 106 //删除的是第一个结点 107 //找到最后一个结点 108 for(target = *pNode; target->next != *pNode; target = target->next); 109 110 temp = *pNode; //保存第一个结点以删除 111 *pNode = (*pNode)->next;//第一个结点指向下一个结点 112 target->next = *pNode;//尾结点指向第一个结点 113 free(temp);//释放 114 } 115 else 116 { 117 target = *pNode; 118 119 for(; j < i-1; j++) 120 { 121 target = target->next;//target只是指向要删除的结点 122 } 123 124 temp = target->next; 125 target->next = temp->next; 126 free(temp); 127 } 128 } 129 //返回结点所在位置 130 int ds_search(node *pNode,int i) 131 { 132 node *target; 133 int i = 1; 134 135 for(target = pNode; target->data != elem && target->next != pNode; i++) 136 { 137 target = target->nexxt; 138 } 139 140 if(target->next == pNode) //说明表中不存在该元素 141 return 0; 142 else 143 return i; 144 } 145 146 147 相关代码实现: 148 #include <stdio.h> 149 #include <stdlib.h> 150 151 /*链表存储结构的定义*/ 152 typedef struct CLinkList 153 { 154 int data; 155 struct CLinkList *next; 156 }node; 157 158 /************************************************************************/ 159 /* 操作 */ 160 /************************************************************************/ 161 162 /*初始化循环链表*/ 163 void ds_init(node **pNode) 164 { 165 int item; 166 node *temp; 167 node *target; 168 169 printf("输入结点的值,输入0完成初始化\n"); 170 171 while(1) 172 { 173 scanf("%d", &item); 174 fflush(stdin); 175 176 if(item == 0) 177 return; 178 179 if((*pNode) == NULL) 180 { /*循环链表中只有一个结点*/ 181 *pNode = (node*)malloc(sizeof(struct CLinkList)); 182 if(!(*pNode)) 183 exit(0); 184 (*pNode)->data = item; 185 (*pNode)->next = *pNode; 186 } 187 else 188 { 189 /*找到next指向第一个结点的结点*/ 190 for(target = (*pNode); target->next != (*pNode); target = target->next) 191 ; 192 193 /*生成一个新的结点*/ 194 temp = (node *)malloc(sizeof(struct CLinkList)); 195 196 if(!temp) 197 exit(0); 198 199 temp->data = item; 200 temp->next = *pNode; 201 target->next = temp; 202 } 203 } 204 } 205 206 /*插入结点*/ 207 /*参数:链表的第一个结点,插入的位置*/ 208 void ds_insert(node **pNode , int i) 209 { 210 node *temp; 211 node *target; 212 node *p; 213 int item; 214 int j = 1; 215 216 printf("输入要插入结点的值:"); 217 scanf("%d", &item); 218 219 if(i == 1) 220 { //新插入的结点作为第一个结点 221 temp = (node *)malloc(sizeof(struct CLinkList)); 222 223 if(!temp) 224 exit(0); 225 226 temp ->data = item; 227 228 /*寻找到最后一个结点*/ 229 for(target = (*pNode); target->next != (*pNode); target = target->next) 230 ; 231 232 temp->next = (*pNode); 233 target->next = temp; 234 *pNode = temp; 235 } 236 else 237 { 238 target = *pNode; 239 240 for( ; j < (i-1); ++j ) 241 { 242 target=target->next; 243 } 244 245 temp = (node *)malloc(sizeof(struct CLinkList)); 246 247 if(!temp) 248 exit(0); 249 250 temp ->data = item; 251 p = target->next; 252 target->next = temp; 253 temp->next = p; 254 } 255 } 256 257 /*删除结点*/ 258 void ds_delete(node **pNode, int i) 259 { 260 node *target; 261 node *temp; 262 int j = 1; 263 264 if(i == 1) 265 { //删除的是第一个结点 266 /*找到最后一个结点*/ 267 for(target = *pNode; target->next != *pNode;target = target->next) 268 ; 269 270 temp = *pNode; 271 *pNode = (*pNode)->next; 272 target->next = *pNode; 273 free(temp); 274 } 275 else 276 { 277 target = *pNode; 278 279 for( ; j < i-1; ++j ) 280 { 281 target = target->next; 282 } 283 284 temp = target->next; 285 target->next = temp->next; 286 free(temp); 287 } 288 } 289 290 /*返回结点所在位置*/ 291 int ds_search(node *pNode, int elem) 292 { 293 node *target; 294 int i = 1; 295 296 for(target = pNode; target->data != elem && target->next != pNode; ++i) 297 { 298 target = target->next; 299 } 300 301 if(target->next == pNode) /*表中不存在该元素*/ 302 return 0; 303 else 304 return i; 305 } 306 307 /*遍历*/ 308 void ds_traverse(node *pNode) 309 { 310 node *temp; 311 temp = pNode; 312 printf("***********链表中的元素******************\n"); 313 314 do 315 { 316 printf("%4d ", temp->data); 317 }while((temp = temp->next) != pNode); 318 319 printf("\n"); 320 } 321 322 int main() 323 { 324 node *pHead = NULL; 325 char opp; 326 int find; 327 328 printf("1.初始化链表 \n\n2.插入结点 \n\n3.删除结点 \n\n4.返回结点位置 \n\n5.遍历链表 \n\n0.退出 \n\n请选择你的操作:"); 329 while(opp != '0') 330 { 331 scanf("%c", &opp); 332 switch(opp) 333 { 334 case '1': 335 ds_init(&pHead); 336 printf("\n"); 337 ds_traverse(pHead); 338 break; 339 340 case '2': 341 printf("输入需要插入结点的位置?"); 342 scanf("%d", &find); 343 ds_insert(&pHead, find); 344 printf("在位置%d插入值后:\n", find); 345 ds_traverse(pHead); 346 printf("\n"); 347 break; 348 349 case '3': 350 printf("输入需要删除的结点位置?"); 351 scanf("%d", &find); 352 ds_delete(&pHead, find); 353 printf("删除第%d个结点后:\n", find); 354 ds_traverse(pHead); 355 printf("\n"); 356 break; 357 358 case '4': 359 printf("你要查找倒数第几个结点的值?"); 360 scanf("%d", &find); 361 printf("元素%d所在位置:%d\n", find, ds_search(pHead, find)); 362 //ListTraverse(L); 363 printf("\n"); 364 break; 365 366 case '5': 367 ds_traverse(pHead); 368 printf("\n"); 369 break; 370 371 case '0': 372 exit(0); 373 } 374 } 375 376 return 0; 377 } 378 379 //自己实践的代码 380 一个简单的创建以及输出 381 #include<stdio.h> 382 #include<stdlib.h> 383 384 typedef struct Node 385 { 386 int data; 387 struct Node *next; 388 }LinkList; 389 390 #define LEN sizeof(LinkList) 391 392 LinkList *initList() //设置头结点 393 { 394 int dat; 395 LinkList *temp; 396 LinkList *target; 397 LinkList *pNode = NULL; 398 399 printf("输入以0结束\n"); 400 401 while(1) 402 { 403 scanf("%d",&dat); 404 if(dat == 0) 405 break; 406 407 if(pNode == NULL) 408 { 409 pNode = (LinkList *)malloc(LEN); 410 if(pNode == NULL) 411 exit(1); 412 pNode->data = dat; 413 pNode->next = pNode; 414 } 415 else 416 { 417 for(target=pNode; target->next!=pNode; target=target->next); 418 419 temp = (LinkList *)malloc(LEN); 420 if(temp == NULL) 421 exit(1); 422 423 temp->data = dat; 424 temp->next = pNode; //新插入数据的指针域指向头 425 target->next = temp; //指向末尾结点的target指向新插入的结点 426 } 427 428 } 429 430 return pNode; 431 432 } 433 434 void printList(LinkList *pNode) 435 { 436 LinkList *temp; 437 temp = pNode; 438 printf("链表中的元素是:\n"); 439 440 do 441 { 442 printf("%4d",temp->data); 443 temp = temp->next; 444 }while(temp != pNode); 445 printf("\n"); 446 } 447 448 int main(void) 449 { 450 LinkList *pNode; 451 LinkList *L; 452 pNode = initList(); 453 printList(pNode); 454 455 return 0; 456 }