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 – – x);

(L – – 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)步,之后两个链表同时前进,每次一步,相遇的第一点即为两个链表相交的第一个点。

目录
相关文章
|
11月前
|
机器学习/深度学习 算法
24. 两两交换链表中的节点, 19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交
1. **两两交换链表中的节点**:通过引入虚拟头结点,使所有节点都能采用统一的交换逻辑,避免对头结点单独处理。 2. **删除链表的倒数第N个节点**:利用双指针技巧,让快慢指针保持N个节点的距离,当快指针到达末尾时,慢指针正好指向待删除节点的前一个节点。 3. **链表相交**:先计算两链表长度并调整起点,确保从相同距离末尾的位置开始遍历,从而高效找到相交节点或确定无交点。 以上方法均在时间复杂度和空间复杂度上进行了优化,适合用于理解和掌握链表的基本操作及常见算法设计思路。
|
人工智能 自然语言处理 算法
通义灵码助力技术求职:如何成为笔试面试冲刺的“超级助手”
在技术岗位竞争日益激烈的当下,求职季的备战已不仅是知识储备的较量,更是效率与实战能力的比拼。面对海量面试题、复杂算法挑战及快速迭代的技术框架,开发者亟需高效工具辅助突破瓶颈。阿里云推出的智能编码工具通义灵码,凭借其代码生成、优化及智能问答等核心能力,正成为开发者备战求职季的“超级助手”。
C语言里的循环链表
C语言里的循环链表
|
存储 算法 C语言
【C语言】深入浅出:C语言链表的全面解析
链表是一种重要的基础数据结构,适用于频繁的插入和删除操作。通过本篇详细讲解了单链表、双向链表和循环链表的概念和实现,以及各类常用操作的示例代码。掌握链表的使用对于理解更复杂的数据结构和算法具有重要意义。
4059 6
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
534 5
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
1652 4
|
存储 缓存 C语言
C语言:链表和数组有什么区别
C语言中,链表和数组是两种常用的数据结构。数组是一种线性结构,元素在内存中连续存储,通过下标访问,适合随机访问且大小固定的情况。链表由一系列不连续的节点组成,每个节点存储数据和指向下一个节点的指针,适用于频繁插入和删除操作的场景,链表的大小可以动态变化。
|
C语言
无头链表再封装方式实现 (C语言描述)
如何在C语言中实现无头链表的再封装,包括创建节点和链表、插入和删除操作、查找和打印链表以及销毁链表的函数。
178 0
|
C语言
C语言链式结构之有头单链表再封装写法
本文介绍了如何使用C语言对有头单链表进行封装,包括节点的创建、链表的初始化、数据的插入和删除,以及链表的打印等功能。
196 1
|
C语言
C语言结构体链式结构之有头单链表
文章提供了一个C语言实现的有头单链表的完整代码,包括创建链表、插入、删除和打印等基本操作。
276 1