1.
从尾到头打印单链表
2.约瑟夫环问题
3.
单链表的逆置
4.
单链表的排序(冒泡法)
5.
合并两个有序单链表之后使新的单链表依旧有序
6.
查找单链表的中间节点,且只能遍历一次链表
7.查找单链表的倒数第K个节点
8.
删除倒数第k个节点
从尾到头打印单链表
这道题的思路是要运用递归来实现
407 //逆置打印链表 408 #include <stdio.h> 409 void LinkListPrintReverse(LinkNode* head) 410 { 411 if(head == NULL) 412 { 413 //空链表 414 return ; 415 } 416 //运用递归 417 LinkListPrintReverse(head->next); 418 printf("%c",head->data); 419 }
约瑟夫环问题
约瑟夫环问题是指:已知n个人(以编号1,2,3,...,n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的人出列;他的下一个人又开始从1开始报数,数到m的人出列;依次规律重复下去,直至圆桌周围的人全部出列,只剩下一个人。
421 //约瑟夫环 422 LinkNode* JosphCricle(LinkNode* head,int M) 423 { 424 if(head == NULL) 425 { 426 //空链表 427 return NULL; 428 } 429 LinkNode* cur=head; 430 while(cur->next!=cur) 431 { 432 int i=1; 433 for(;i<M;++i) 434 { 435 cur=cur->next; 436 } 437 //cur指向的元素就是要被吃掉的元素 438 printf("%c\n",cur->data); 439 cur->data=cur->next->data; 440 LinkNode* to_delete=cur->next; 441 cur->next=to_delete->next; 442 DestroyNode(to_delete); 443 } 444 return cur; 445 }
方法一:(推荐使用)
447 //链表逆置 448 void LinkListReverse(LinkNode** phead) 449 { 450 if(phead == NULL) 451 { 452 //非法输入 453 return; 454 } 455 if(*phead == NULL) 456 { 457 //空链表 458 return ; 459 } 460 if((*phead)->next == NULL) 461 { 462 //只有一个元素 463 return ; 464 } 465 LinkNode* cur=*phead; 466 while(cur->next!=NULL) 467 { 468 LinkNode* to_delete=cur->next; 469 //把这个节点删除掉 470 cur->next=to_delete->next; 471 //把删除掉的元素插入到链表头部 472 to_delete->next=*phead; 473 *phead=to_delete; 474 } 475 return ; 476 }
方法二:
479 void LinkListReverse2(LinkNode** phead) 480 { 481 if(phead == NULL) 482 { 483 //非法输入 484 return ; 485 } 486 if(*phead == NULL) 487 { 488 //空链表 489 return ; 490 } 491 if((*phead)->next==NULL) 492 { 493 //只有一个元素 494 return ; 495 } 496 LinkNode* cur=(*phead)->next; 497 LinkNode* pre=(*phead); 498 while(cur!=NULL) 499 { 500 LinkNode* next=cur->next; 501 //修改cur->next指针的指向 502 cur->next=pre; 503 //交换pre cur指针 504 pre=cur; 505 cur=cur->next; 506 } 507 //修改头指针指向 508 *phead=pre; 509 }
单链表的排序(冒泡法)
511 //交换两个值 512 void Swap(LinkNodeType* a,LinkNodeType* b) 513 { 514 LinkNodeType tmp=*a; 515 *a=*b; 516 *b=tmp; 517 }
518 //对单链表进行排序(冒泡法) 519 void LinkListBubbleSort(LinkNode* head) 520 { 521 if(head == NULL) 522 { 523 //空链表 524 return ; 525 } 526 if(head->next = NULL) 527 { 528 //只有一个节点 529 return; 530 } 531 LinkNode* count=head; 532 LinkNode* tail=NULL;//结束标记 533 //第一重循环表示排序的趟数 534 for(;count!=NULL;count=count->next) 535 { 536 LinkNode* cur=head; 537 //第二重循环表示保证将当前最大值冒到最后 538 for(;cur->next!=tail;cur=cur->next) 539 { 540 if(cur->data>cur->next->data) 541 { 542 Swap(&cur->data,&cur->next->data); 543 } 544 } 545 tail=cur; 546 } 547 return ; 548 }
合并两个有序单链表之后使新的单链表依旧有序
比较cur1和cur2的大小,将较小的放入新链表的new_head中
550 //合并两个有序链表并且之后依旧有序 551 LinkNode* LinkListMerge(LinkNode* head1,LinkNode* head2) 552 { 553 if(head1 == NULL) 554 { 555 return head2; 556 } 557 if(head2 == NULL) 558 { 559 return head1; 560 } 561 LinkNode* cur1=head1; 562 LinkNode* cur2=head2; 563 //用来指向新链表的头结点和尾节点 564 LinkNode* new_head=NULL; 565 LinkNode* new_tail=NULL; 566 while(cur1=NULL&&cur2!=NULL) 567 { 568 if(cur1->data<cur2->data) 569 { 570 if(new_tail == NULL) 571 { 572 new_tail=new_tail=cur1; 573 } 574 else 575 { 576 new_tail->next=cur1; 577 new_tail=new_tail->next; 578 } 579 cur1=cur1->next; 580 } 581 else if(cur1->data>cur1->data) 582 { 583 if(new_tail == NULL) 584 { 585 new_tail=new_tail=cur2; 586 } 587 else 588 { 589 new_tail->next=cur2; 590 new_tail-new_tail->next; 591 } 592 } 593 } 594 //有一方已经先到达结尾,要将剩余部分接到新的链表之后 595 if(cur1=NULL) 596 { 597 new_tail->next=cur1; 598 } 599 else 600 { 601 new_tail->next=cur2; 602 } 603 return new_head; 604 }
查找单链表的中间节点,且只能遍历一次链表
定义两个指针分别是fast和slow,开始都指向链表头部,让fast指针一次走两步,slow指针一次走一步,这样当fast指针走到链表结尾时,slow指针刚好走到链表中间节点的位置。
606 //查找单链表的中间节点,只能遍历一次链表 607 LinkNode* LinkListFindMidNode(LinkNode* head) 608 { 609 if(head == NULL) 610 { 611 //空链表 612 return ; 613 } 614 LinkNode* slow=head; 615 LinkNode* fast=head; 616 while(fast!=NULL&&fast->next!=NULL) 617 { 618 slow=slow->next; 619 fast=fast->next->next; 620 } 621 return slow; 622 }
查找链表的倒数第k个节点
方法同上一个问题,定义两个指针,fast和slow,让fast指针先走k步,然后再一起出发,都一次走一步,当fast指针走到结尾,则slow指针指向的就是倒数第k个节点。
624 //查找链表的倒数第k个节点 625 LinkNode* LinkListFindLastKNode(LinkNode* head,int k) 626 { 627 if(head == NULL) 628 { 629 //空链表 630 return ; 631 } 632 LinkNode* fast=head; 633 LinkNode* slow=head; 634 //让fast先走k步 635 int i=0; 636 for(;i<k;++i) 637 { 638 if(fast==NULL) 639 { 640 break; 641 } 642 fast=fast->next; 643 } 644 if(i!=NULL) 645 { 646 //没走完,k的数值超过链表长度 647 return NULL; 648 } 649 while(fast!=NULL) 650 { 651 fast=fast->next; 652 slow=slow->next; 653 } 654 return slow; 655 }
删除倒数第k个节点
657 //删除倒数第k个节点 658 void LinkListEraseLastKNode(LinkNode** phead,int k) 659 { 660 if(phead == NULL) 661 { 662 //非法输入 663 return ; 664 } 665 if(*phead == NULL) 666 { 667 //空链表 668 return ; 669 } 670 int len=LinkListSize(*phead); 671 if(k>len) 672 { 673 return ; 674 } 675 if(k == len) 676 { 677 //要删除的元素为第一个 678 LinkNode* to_delete=*phead; 679 *phead=(*phead)->next; 680 DestroyNode(to_delete); 681 return ; 682 } 683 LinkNode* pre=*phead; 684 int i=0; 685 for(;i<len-(k+1);++i) 686 { 687 pre=pre->next; 688 } 689 //循环结束后意味着pre已指向要删除元素的前一个节点 690 LinkNode* to_delete=pre->next; 691 pre->next=to_delete->next; 692 DestroyNode(to_delete); 693 return ; 694 }