经常会在面试时出现链表的题,本篇博客是对经典面试题一个总结。
首先:整个程序的头文件Slist.h:
新增结点:
尾插:
打印链表:
FindSlist函数:
从尾到头打印单链表:
递归从头到尾打印单链表:
递归是将问题化为子问题,若链表为:1 2 3 4 5 ,打印1 2 3 4,就先打印5,打印1 2 3 ,就先打印出4.......
代码如下:
删除一个无头结点的非尾结点(不能遍历链表):
对于这个问题可以采用替换删除法:若链表为: 2 4 6 7 ,若要删除4,可以先将6的值给4这个位置,然后将6这个位置释放。
在无头单链表的一个结点前插入一个结点(不能遍历该链表):
依然采用替换插入法:若链表为 2 5 7 9 ,若要在7前插入11,可以先将7后插入7,再将原来7位置数据换成11。代码如下:
单链表实现约瑟夫环:
约瑟夫环是指:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为m的人开始报数,数到k的那个人出列;他的下一个人又从1开始报数,数到k的那个人又出列;依此规律重复下去,直到圆桌上剩下一人。用链表实现:假设从头开始报数,代码如下:
逆置/反转单链表:
List* ReverseList(List* pHead)//反转链表
{
if (pHead == NULL || pHead->_next == NULL)
return pHead;
//pre-> pHead-> pNext
//pre<-pHead
List* pre = NULL;
List* newHead = NULL;
while (pHead != NULL) {
List* pNext = pHead->_next;
if (pNext == NULL)
newHead=pHead;
//如果不定义一个新的变量,而是直接返回pHead,将只会返回原链表最后一个结点,
//因为pHead=pNext,这时最后一个结点和前面结点已经断开
//定义一个新的变量newHead后,newHead指向phead,而接下来pHead->next指向pre,那么就将整个链表链接在一起
pHead->_next = pre;
pre = pHead;
pHead = pNext;
}
return newHead;
}
单链表冒泡排序:
合并两个有序单链表,合并后依然有序:
查找链表的中间结点,要求只能遍历一次链表:
对于这个问题利用快慢指针来解决。定义两个指针,fast和slow指针。首先,思路是:利用快慢指针,快指针先走两步(奇偶性不同),然后慢指针走一步,快指针走两步,直到快指针为空,慢指针所指即为中间结点。
查找单链表的倒数第K个结点,要求只能遍历一次链表:
思路是:同样利用快慢指针,快指针先走k-1步,然后,快慢指针各走一步,
这样快指针就比慢指针快k-1步,直到快指针为空,slow即为倒数第K个结点
删除倒数第K个结点:
利用替换删除法和快慢指针。
判断单链表是否带环,若带环,求环的长度,求环的入口点。
判断是否有环 :利用两个快慢指针,快指针一次走两步,慢指针一次走一步,如果存在环,两者相遇;如果没有环,快指针会遇到NULL;fast走两步,slow走一步,如果有环,这样会把差距缩小,肯定会相遇。下面函数返回快慢指针相遇点。
环的长度:
fast和slow从环里的任意位置开始,依然fast两步,slow一步,再次相遇时slow所经过的结点数就是环的长度。
求环的入口点:
由图可写出如下代码:
判断两个链表是否相交,若相交,求交点。(假设链表不带环)
求相交点:
链表相交,求相交点:可以先让长度长的链表走两个链表长度之差步,之后两个链表一起走,相等时即为相交点。
求两个已排序单链表中相同的数据:
对于这个问题和前面的将两个有序链表合并为一个有序链表思想一样,都是小的先走,再比较大小,直至其中一个(或者两个)链表为空。
以上就是对链表面试题一个总结。