zoukankan      html  css  js  c++  java
  • C语言链表在笔试面试中常考问题总结

    1、实现单链表逆置

       无头结点:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 
     4 typedef struct node{
     5     int data;
     6     struct node *next;
     7 }Node;
     8 
     9 //创建链表
    10 Node *CreateList(void){
    11     int val,i,n;
    12     Node *head,*p,*q;
    13 
    14     head=NULL;
    15     printf("请输入您要建立的链表长度:\n");  
    16     scanf("%d",&n);
    17     printf("请输入您要输入的数据:\n");  
    18     for(i=0;i<n;i++){
    19         scanf("%d",&val);
    20         p=(Node*)malloc(sizeof(Node));
    21         p->data=val;
    22         if(head==NULL)
    23             head=q=p;
    24         else
    25             q->next=p;
    26         q=p;
    27     }
    28     p->next=NULL;
    29     return head;
    30 }
    31 
    32 //链表的逆置
    33 Node *ReverseList(Node *head){
    34     Node *p,*q,*r;
    35     p=head;
    36     q=r=NULL;
    37     while(p){
    38         q=p->next;
    39         p->next=r;
    40         r=p;
    41         p=q;
    42     }
    43     return r;
    44 }
    45 
    46 //输出链表
    47 void ShowList(Node *head){
    48     Node *p;
    49     p=head;
    50     while(p){
    51         printf("%d ",p->data);
    52         p=p->next;
    53     }
    54     printf("\n");
    55 }
    56 
    57 void main(){
    58     Node *head;
    59 
    60     head=CreateList();
    61     printf("链表逆置前的数据:\n");
    62     ShowList(head);
    63 
    64     head=ReverseList(head);
    65     printf("链表逆置后的数据:\n");  
    66     ShowList(head);  
    67 }

      运行演示:

        

    2、判断单链表是否有环

      判断链表是否存在环的办法为:

      设置两个指针(fast,slow),初始值都指向头指针,slow每次前进一步,fast每次前进两步,如果链表存在环,则fast必定先进入环,而slow后进入环,两个指针必定相遇。(当然,fast先行从头到尾部为NULL,则为无环链表)程序如下:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 
     4 typedef struct node{
     5     int elem;
     6     struct node * next;
     7 }Node, *NodeList;
     8 
     9 bool IsExitsLoop(NodeList head){
    10     NodeList slow=head,fast=head;
    11     while(fast && fast->next){
    12         slow=slow->next;
    13         fast=fast->next->next;
    14         if(slow==fast)
    15             break;
    16     }
    17     return !(fast==NULL || fast->next==NULL);
    18 }
    19 
    20 void main(){
    21     //创建一个有环的单链表
    22     NodeList head=NULL,p,q;
    23     for(int i=1;i<=5;i++){
    24         p=(NodeList)malloc(sizeof(Node));
    25         p->elem=i;
    26         if(head==NULL)
    27             head=q=p;
    28         else
    29             q->next=p;
    30         q=p;
    31     }
    32     p=(NodeList)malloc(sizeof(Node));
    33     p->elem=6;
    34     q->next=p;
    35     q=p;
    36     q->next=head->next->next->next;
    37     //判断单链表是否存在环
    38     printf("单链表是否存在环: ");
    39     bool b=IsExitsLoop(head);
    40     printf("%s\n",b==false?"false":"true");
    41 }

      运行结果显示:

        

    3、如果单链表有环,则找到环的入口点

      当fast若与slow相遇时,slow肯定没有遍历完链表,而fast已经在环内循环了n圈(1<=n),假设slow走了s步,而fast走了2s步(fast步数还等于s加上在环上多转的n圈),设环长为r,则:

        2s = s + n*r;  

        s = n*r;

    设整个链表长为L,入口环与相遇点距离为x,起点到环入口点的距离为a。

        a + x = n*r;    

        a + x = (n-1)*r + r = (n-1)*r + L -a;    

        a = (n-1)r + (L – a – x);

    (L – a – x)为相遇点到环入口点的距离,由此可知,从链表头到环入口点等于(n-1)循环内环+相遇点到环入口点,于是我们从链表头、与相遇点分别设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。程序描述如下:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 
     4 typedef struct node{
     5     int elem;
     6     struct node * next;
     7 }Node, *NodeList;
     8 
     9 //寻找环的入口点
    10 NodeList FindLoopPort(NodeList head){
    11     NodeList slow=head,fast=head;
    12     while(fast && fast->next){
    13         slow=slow->next;
    14         fast=fast->next->next;
    15         if(slow==fast)
    16             break;
    17     }
    18     if(fast==NULL||fast->next==NULL)
    19         return NULL;
    20     slow=head;
    21     while(slow!=fast){
    22         slow=slow->next;
    23         fast=fast->next;
    24     }
    25     return slow;
    26 }
    27 
    28 void main(){
    29     //创建一个有环的单链表
    30     NodeList head=NULL,p,q;
    31     for(int i=1;i<=5;i++){
    32         p=(NodeList)malloc(sizeof(Node));
    33         p->elem=i;
    34         if(head==NULL)
    35             head=q=p;
    36         else
    37             q->next=p;
    38         q=p;
    39     }
    40     p=(NodeList)malloc(sizeof(Node));
    41     p->elem=6;
    42     q->next=p;
    43     q=p;
    44     q->next=head->next->next->next;
    45     //寻找环的入口点
    46     NodeList list=FindLoopPort(head);
    47     printf("环的入口节点元素值为:%d\n",list->elem);
    48 }

      运行结果显示:

        

    4、判断两个单链表是否相交,如果相交,给出相交的第一个点(两个链表都不存在环)

      比较好的方法有两个:

      一、将其中一个链表首尾相连,检测另外一个链表是否存在环,如果存在,则两个链表相交,而检测出来的依赖环入口即为相交的第一个点。

      二、如果两个链表相交,那么两个链表从相交点到链表结束都是相同的节点,我们可以先遍历一个链表,直到尾部,再遍历另外一个链表,如果也可以走到同样的结尾点,则两个链表相交。这时我们记下两个链表length,再遍历一次,长链表节点先出发前进(lengthMax-lengthMin)步,之后两个链表同时前进,每次一步,相遇的第一点即为两个链表相交的第一个点。

     

  • 相关阅读:
    哈希冲突详解(拉链法,开放地址法)
    哈希冲突详解(拉链法,开放地址法)
    排序算法
    排序算法
    加分二叉树
    加分二叉树
    动态规划
    动态规划
    动态规划
    动态规划
  • 原文地址:https://www.cnblogs.com/gw811/p/2743182.html
Copyright © 2011-2022 走看看