[转载 整理]C语言链表实例
C语言链表有单链表、双向链表、循环链表。单链表由数据域和指针域组成,数据域存放数据,指针域存放该数据类型的指针便于找到下一个节点。双链表则含有头指针域、数据域和尾指针域,域单链表不同,双链表可以从后一个节点找到前一个节点,二单链表则不行。循环链表就是在单链表的基础上,将头结点的地址指针存放在最后一个节点的指针域里以,此形成循环。此外还有双向循环链表,它同时具有双向链表和循环链表的功能。
单链表如:
链表节点的数据结构定义
struct node { int num; struct node *p; } ;
在此链表节点的定义中,除一个整型的成员外,成员p是指向与节点类型完全相同的指针。
※在链表节点的数据结构中,非常特殊的一点就是结构体内的指针域的数据类型使用了未定义成功的数据类型。这是在C中唯一规定可以先使用后定义的数据结构。
链表实例代码:
1 // 原文地址 http://www.cnblogs.com/wireless-dragon/p/5170565.html 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 6 typedef int elemType;//定义存入的数据的类型可以是int char 7 8 typedef struct NODE{ //定义链表的结构类型 9 elemType element; 10 struct NODE *next; 11 }Node; 12 13 /************************************************************************/ 14 /* 以下是关于线性表链接存储(单链表)操作的19种算法 */ 15 16 /* 1.初始化线性表,即置单链表的表头指针为空 */ 17 /* 2.创建线性表,此函数输入负数终止读取数据*/ 18 /* 3.打印链表,链表的遍历*/ 19 /* 4.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为一个空表 */ 20 /* 5.返回单链表的长度 */ 21 /* 6.检查单链表是否为空,若为空则返回1,否则返回0 */ 22 /* 7.返回单链表中第pos个结点中的元素,若pos超出范围,则停止程序运行 */ 23 /* 8.从单链表中查找具有给定值x的第一个元素,若查找成功则返回该结点data域的存储地址,否则返回NULL */ 24 /* 9.把单链表中第pos个结点的值修改为x的值,若修改成功返回1,否则返回0 */ 25 /* 10.向单链表的表头插入一个元素 */ 26 /* 11.向单链表的末尾添加一个元素 */ 27 /* 12.向单链表中第pos个结点位置插入元素为x的结点,若插入成功返回1,否则返回0 */ 28 /* 13.向有序单链表中插入元素x结点,使得插入后仍然有序 */ 29 /* 14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停止程序运行 */ 30 /* 15.从单链表中删除表尾结点并返回它的值,若删除失败则停止程序运行 */ 31 /* 16.从单链表中删除第pos个结点并返回它的值,若删除失败则停止程序运行 */ 32 /* 17.从单链表中删除值为x的第一个结点,若删除成功则返回1,否则返回0 */ 33 /* 18.交换2个元素的位置 */ 34 /* 19.将线性表进行冒排序 */ 35 36 37 38 /*注意检查分配到的动态内存是否为空*/ 39 40 41 42 43 /* 1.初始化线性表,即置单链表的表头指针为空 */ 44 void initList(Node **pNode) 45 { 46 *pNode=NULL; 47 printf("initList函数执行,初始化成功\n"); 48 } 49 50 /* 2.创建线性表,此函数输入负数终止读取数据*/ 51 Node *creatList(Node *pHead) 52 { 53 Node *p1,*p2; 54 p1=p2=(Node *)malloc(sizeof(Node)); 55 if(p1 == NULL || p2 ==NULL) 56 { 57 printf("内存分配失败\n"); 58 exit(0); 59 } 60 memset(p1,0,sizeof(Node)); 61 62 scanf("%d",&p1->element); 63 p1->next=NULL; 64 65 while(p1->element >0) //输入的值大于0则继续,否则停止 66 { 67 if(pHead == NULL)//空表,接入表头 68 { 69 pHead=p1; 70 } 71 else 72 { 73 p2->next=p1; 74 } 75 76 p2=p1; 77 p1=(Node *)malloc(sizeof(Node)); 78 79 if(p1==NULL||p2==NULL) 80 { 81 printf("内存分配失败\n"); 82 exit(0); 83 } 84 memset(p1,0,sizeof(Node)); 85 scanf("%d",&p1->element); 86 p1->next=NULL; 87 } 88 printf("CreatList函数执行,链表创建成功\n"); 89 return pHead; 90 } 91 92 /* 3.打印链表,链表的遍历*/ 93 void printList(Node *pHead) 94 { 95 if(NULL==pHead) 96 { 97 printf("PrintList函数执行,链表为空\n"); 98 } 99 else 100 { 101 while(NULL!=pHead) 102 { 103 printf("%d\n",pHead->element); 104 pHead=pHead->next; 105 } 106 } 107 108 } 109 110 111 /* 4.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为一个空表 */ 112 void clearList(Node *pHead) 113 { 114 Node *pNext; 115 116 if(pHead==NULL) 117 { 118 printf("clearList函数执行,链表为空\n"); 119 return; 120 } 121 while(pHead->next!=NULL) 122 { 123 pNext=pHead->next; 124 free(pHead); 125 pHead=pNext; 126 } 127 printf("clearList函数执行,链表已经清除!\n"); 128 129 } 130 131 /* 5.返回链表的长度*/ 132 int sizeList(Node *pHead) 133 { 134 int size=0; 135 136 while(pHead!=NULL) 137 { 138 size++; 139 pHead=pHead->next; 140 } 141 printf("sizelist函数执行,链表长度为%d\n",size); 142 return size; 143 } 144 145 /* 6.检查单链表是否为空,若为空则返回1,否则返回0 */ 146 int isEmptyList(Node *pHead) 147 { 148 if(pHead==NULL) 149 { 150 printf("isEmptylist函数执行,链表为空!\n"); 151 return 1; 152 } 153 154 else 155 printf("isEmptylist函数执行,链表非空!\n"); 156 return 0; 157 158 } 159 160 /* 7.返回链表中第post节点的数据,若post超出范围,则停止程序运行*/ 161 int getElement(Node *pHead,int pos) 162 { 163 int i=0; 164 if(pos<1) 165 { 166 printf("getElement函数执行,pos值非法!"); 167 return 0; 168 } 169 if(pHead==NULL) 170 { 171 printf("getElement函数执行,链表为空!"); 172 } 173 174 while (pHead!=NULL) 175 { 176 ++i; 177 if(i==pos) 178 { 179 break; 180 } 181 pHead=pHead->next; 182 } 183 if(i<pos) 184 { 185 printf("getElement函数执行,pos值超出链表长度\n"); 186 return 0; 187 } 188 printf("getElement函数执行,位置%d中的元素为%d\n",pos,pHead->element); 189 190 return 1; 191 } 192 193 //8.从单一链表中查找具有给定值x的第一个元素,若查找成功后,返回该节点data域的存储位置,否则返回NULL 194 elemType *getElemAddr(Node *pHead,elemType x) 195 { 196 if(NULL==pHead) 197 { 198 printf("getEleAddr函数执行,链表为空"); 199 return NULL; 200 } 201 if(x<0) 202 { 203 printf("getEleAddr函数执行,给定值x不合法\n"); 204 return NULL; 205 } 206 while((pHead->element!=x)&&(NULL!=pHead->next))//判断链表是否为空,并且是否存在所查找的元素 207 { 208 pHead=pHead->next; 209 } 210 if(pHead->element!=x) 211 { 212 printf("getElemAddr函数执行,在链表中没有找到x值\n"); 213 return NULL; 214 } 215 else 216 { 217 printf("getElemAddr函数执行,元素%d的地址为0x%x\n",x,&(pHead->element)); 218 } 219 return &(pHead->element); 220 221 } 222 223 224 /*9.修改链表中第pos个点X的值,如果修改成功,则返回1,否则返回0*/ 225 int modifyElem(Node *pNode,int pos,elemType x) 226 { 227 Node *pHead; 228 pHead=pNode; 229 int i=0; 230 if(NULL==pHead) 231 { 232 printf("modifyElem函数执行,链表为空\n"); 233 return 0; 234 } 235 236 if(pos<1) 237 { 238 printf("modifyElem函数执行,pos值非法\n"); 239 return 0; 240 } 241 242 while(pHead!= NULL) 243 { 244 ++i; 245 if(i==pos) 246 { 247 break; 248 } 249 pHead=pHead->next; 250 } 251 252 if(i<pos) 253 { 254 printf("modifyElem函数执行,pos值超出链表长度\n"); 255 return 0; 256 } 257 pNode=pHead; 258 pNode->element=x; 259 printf("modifyElem函数执行,修改第%d点的元素为%d\n",pos,x); 260 261 return 1; 262 263 } 264 265 /* 10.向单链表的表头插入一个元素 */ 266 int insertHeadList(Node **pNode,elemType insertElem) 267 { 268 Node *pInsert; 269 pInsert=(Node *)malloc(sizeof(Node)); 270 if(pInsert==NULL) exit(1); 271 memset(pInsert,0,sizeof(Node)); 272 pInsert->element=insertElem; 273 pInsert->next=*pNode; 274 *pNode=pInsert; 275 printf("insertHeadList函数执行,向表头插入元素%d成功\n",insertElem); 276 return 1; 277 } 278 279 /* 11.向单链表的末尾添加一个元素 */ 280 int insertLastList(Node *pNode,elemType insertElem) 281 { 282 Node *pInsert; 283 Node *pHead; 284 Node *pTmp; 285 286 pHead=pNode; 287 pTmp=pHead; 288 pInsert=(Node *)malloc(sizeof(Node)); 289 if(pInsert==NULL) exit(1); 290 memset(pInsert,0,sizeof(Node)); 291 pInsert->element=insertElem; 292 pInsert->next=NULL; 293 while(pHead->next!=NULL) 294 { 295 pHead=pHead->next; 296 } 297 pHead->next=pInsert; 298 printf("insertLastList函数执行,向表尾插入元素%d成功!\n",insertElem); 299 return 1; 300 } 301 302 /* 12.向单链表中第pos个结点位置插入元素为x的结点,若插入成功返回1,否则返回0*/ 303 int isAddPos(Node *pNode,int pos,elemType x) 304 { 305 Node *pHead; 306 pHead=pNode; 307 Node *pTmp; 308 int i=0; 309 310 if(NULL==pHead) 311 { 312 printf("AddPos函数执行,链表为空\n"); 313 return 0; 314 } 315 316 if(pos<1) 317 { 318 printf("AddPos函数执行,pos值非法\n"); 319 return 0; 320 } 321 322 while(pHead!=NULL) 323 { 324 ++i; 325 if(i==pos) 326 break; 327 pHead=pHead->next; 328 } 329 330 if(i<pos) 331 { 332 printf("AddPos函数执行,pos值超出链表长度\n"); 333 return 0; 334 } 335 336 pTmp=(Node *)malloc(sizeof(Node)); 337 if(pTmp==NULL) exit(1); 338 memset(pTmp,0,sizeof(Node)); 339 pTmp->next=pHead->next; 340 pHead->next=pTmp; 341 pTmp->element=x; 342 343 printf("AddPos函数执行成功,向节点%d后插入数值%d\n",pos,x); 344 return 1; 345 } 346 347 /* 13.向有序单链表中插入元素x结点,使得插入后仍然有序 */ 348 int OrrderList(Node *pNode,elemType x) 349 { 350 //注意如果此数值要排到行尾要修改本代码 351 Node *pHead; 352 pHead=pNode; 353 Node *pTmp; 354 355 if(NULL==pHead) 356 { 357 printf("OrrderList函数执行,链表为空\n"); 358 return 0; 359 } 360 361 if(x<1) 362 { 363 printf("OrrderList函数执行,x值非法\n"); 364 return 0; 365 } 366 367 while(pHead!=NULL) 368 { 369 if((pHead->element)>=x) 370 break; 371 pHead=pHead->next; 372 } 373 374 375 if(pHead==NULL) 376 { 377 printf("OrrderList函数查找完毕,该函数中没有该值\n"); 378 return 0; 379 } 380 381 382 pTmp=(Node *)malloc(sizeof(Node)); 383 if(pTmp==NULL) exit(1); 384 memset(pTmp,0,sizeof(Node)); 385 pTmp->next=pHead->next; 386 pHead->next=pTmp; 387 pTmp->element=x; 388 389 printf("OrrderList函数成功插入数值%d\n",x); 390 return 1; 391 } 392 393 /*14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停止程序运行*/ 394 int DelHeadList(Node **pList) 395 { 396 Node *pHead; 397 pHead=*pList; 398 if(pHead!=NULL) 399 printf("DelHeadList函数执行,函数首元素为%d删除成功\n",pHead->element); 400 else 401 { 402 printf("DelHeadList函数执行,链表为空!"); 403 return 0; 404 } 405 *pList=pHead->next; 406 return 1; 407 } 408 409 /* 15.从单链表中删除表尾结点并返回它的值,若删除失败则停止程序运行 */ 410 int DelLastList(Node *pNode) 411 { 412 Node *pHead; 413 Node *pTmp; 414 415 pHead=pNode; 416 while(pHead->next!=NULL) 417 { 418 pTmp=pHead; 419 pHead=pHead->next; 420 } 421 printf("链表尾删除元素%d成功!\n",pHead->element); 422 free(pHead); 423 pTmp->next=NULL; 424 return 1; 425 } 426 427 /* 16.从单链表中删除第pos个结点并返回它的值,若删除失败则停止程序运行 */ 428 int DelPos(Node *pNode,int pos) 429 { 430 Node *pHead; 431 pHead=pNode; 432 Node *pTmp; 433 434 int i=0; 435 436 if(NULL==pHead) 437 { 438 printf("DelPos函数执行,链表为空\n"); 439 return 0; 440 } 441 442 if(pos<1) 443 { 444 printf("DelPos函数执行,pos值非法\n"); 445 return 0; 446 } 447 448 while(pHead!=NULL) 449 { 450 ++i; 451 if(i==pos) 452 break; 453 pTmp=pHead; 454 pHead=pHead->next; 455 } 456 457 if(i<pos) 458 { 459 printf("DelPos函数执行,pos值超出链表长度\n"); 460 return 0; 461 } 462 printf("DelPos函数执行成功,节点%d删除数值%d\n",pos,pHead->element); 463 pTmp->next=pHead->next; 464 free(pHead); 465 return 1; 466 } 467 468 /* 17.从单链表中删除值为x的第一个结点,若删除成功则返回1,否则返回0 */ 469 int Delx(Node **pNode,int x) 470 { 471 Node *pHead; 472 Node *pTmp; 473 pHead=*pNode; 474 int i=0; 475 476 if(NULL==pHead) 477 { 478 printf("Delx函数执行,链表为空"); 479 return 0; 480 } 481 if(x<0) 482 { 483 printf("Delx函数执行,给定值x不合法\n"); 484 return 0; 485 } 486 while((pHead->element!=x)&&(NULL!=pHead->next))//判断链表是否为空,并且是否存在所查找的元素 487 { 488 ++i; 489 pTmp=pHead; 490 pHead=pHead->next; 491 } 492 if(pHead->element!=x) 493 { 494 printf("Delx函数执行,在链表中没有找到x值\n"); 495 return 0; 496 } 497 if((i==0)&&(NULL!=pHead->next)) 498 { 499 printf("Delx函数执行,在链表首部找到此元素,此元素已经被删除\n"); 500 *pNode=pHead->next; 501 free(pHead); 502 return 1; 503 } 504 printf("Delx函数执行,首个为%d元素被删除\n",x); 505 pTmp->next=pHead->next; 506 free(pHead); 507 return 1; 508 } 509 510 /* 18.交换2个元素的位置 */ 511 int exchange2pos(Node *pNode,int pos1,int pos2) 512 { 513 Node *pHead; 514 int *pTmp; 515 int *pInsert; 516 int a; 517 int i=0; 518 519 if(pos1<1||pos2<1) 520 { 521 printf("DelPos函数执行,pos值非法\n"); 522 return 0; 523 } 524 525 pHead=pNode; 526 while(pHead!=NULL) 527 { 528 ++i; 529 if(i==pos1) 530 break; 531 pHead=pHead->next; 532 } 533 534 if(i<pos1) 535 { 536 printf("DelPos函数执行,pos1值超出链表长度\n"); 537 return 0; 538 } 539 540 pTmp=&(pHead->element); 541 i=0; 542 pHead=pNode; 543 while(pHead!=NULL) 544 { 545 ++i; 546 if(i==pos2) 547 break; 548 pHead=pHead->next; 549 } 550 551 if(i<pos2) 552 { 553 printf("DelPos函数执行,pos2值超出链表长度\n"); 554 return 0; 555 } 556 557 pInsert=&(pHead->element); 558 a=*pTmp; 559 *pTmp=*pInsert; 560 *pInsert=a; 561 562 printf("DelPos函数执行,交换第%d个和第%d个pos点的值\n",pos1,pos2); 563 return 1; 564 } 565 566 int swap(int *p1,int *p2) 567 { 568 int a; 569 if(*p1>*p2) 570 { 571 a=*p1; 572 *p1=*p2; 573 *p2=a; 574 } 575 return 0; 576 } 577 578 /* 19.将线性表进行冒泡排序 */ 579 int Arrange(Node *pNode) 580 { 581 Node *pHead; 582 pHead=pNode; 583 584 int a=0,i,j; 585 586 if(NULL==pHead) 587 { 588 printf("Arrange函数执行,链表为空\n"); 589 return 0; 590 } 591 592 while(pHead!=NULL) 593 { 594 ++a; 595 pHead=pHead->next; 596 } 597 598 pHead=pNode; 599 for(i=0;i<a-1;i++) 600 { 601 for(j=1;j<a-i;j++) 602 { 603 swap(&(pHead->element),&(pHead->next->element)); 604 pHead=pHead->next; 605 } 606 pHead=pNode; 607 } 608 printf("Arrange函数执行,链表排序完毕!\n"); 609 return 0; 610 } 611 612 int main() 613 { 614 Node *pList=NULL; 615 int length=0; 616 617 elemType posElem; 618 619 initList(&pList); 620 printList(pList); 621 622 pList=creatList(pList); 623 printList(pList); 624 625 sizeList(pList); 626 printList(pList); 627 628 isEmptyList(pList); 629 630 631 posElem=getElement(pList,3); 632 printList(pList); 633 634 getElemAddr(pList,5); 635 636 modifyElem(pList,4,1); 637 printList(pList); 638 639 insertHeadList(&pList,5); 640 printList(pList); 641 642 insertLastList(pList,10); 643 printList(pList); 644 645 isAddPos(pList,4,5); 646 printList(pList); 647 648 OrrderList(pList,6); 649 printList(pList); 650 651 DelHeadList(&pList); 652 printList(pList); 653 654 DelLastList(pList); 655 printList(pList); 656 657 DelPos(pList,5); 658 printList(pList); 659 660 Delx(&pList,5); 661 printList(pList); 662 663 exchange2pos(pList,2,5); 664 printList(pList); 665 666 Arrange(pList); 667 printList(pList); 668 669 clearList(pList); 670 return 0; 671 }