目录
引言
有关单链表的基础操作,如动态分布空间,单链表创建的思路,单链表的增、删、改、毁,笔者已经在上一篇博客中详细解析了,有兴趣的小伙伴也可以取看看,数据结构之单链表一生的历程(创建一个线性表,动态分布空间,单链表创建的思路,单链表的增、删、改、毁)_勾栏听曲_0的博客-CSDN博客
本次介绍的是有关单链表的四道大厂面试典中典,其中的逆置单链表更是重量级,大家放心食用😁
创建有序单链表
题目
创建一个升序或降序的单链表,并打印输出,例如:
输入: 1 5 6 2 3
输出: 1 2 3 5 6
算法思路
算法思路:
s1:每获得一个数据 就创建一个数据结点
s2:把数据写入到数据结点中去
s3:把写好的数据结点加入到链表中去
分情况讨论:
从无到有
从少到多
头插法
尾插法
中间插入
我们将算法思路待人代码中观察
代码实现
Node *create_sort_list()
{
u4 d;
Node *pnew = NULL; //指向 新创建的节点
Node *head = NULL;
while(1)
{
scanf("%d",&d);
if(d == 0) //约定输入0,结束输入
break;
pnew = malloc(sizeof(*pnew)); //分配空间
pnew->data = d; //将数据写入数据节点
pnew->next = NULL;
//将写好的数据节点加入到链表
if(head == NULL) //从无到有
{
head = pnew;
}
else //从少到多
{
Node *p = head;
Node *pre = NULL;
while(p) //找出链表中比新节点大的数据打的节点
{
if(p->data > pnew->data) //找到就返回这个节点
{
break;
}
else //没找到就往下遍历,直到p==NULL,即新节点的值是最大的,插到末尾
{
pre = p;
p = p->next;
}
}
if(p != NULL)
{
if(p == head) //头插法
{
pnew->next = head; //新节点指向链表的第一个,即指向head
head = pnew; //然后将head指向新节点
}
else //插入中间
{
pnew->next = p;
pre->next = pnew;
}
}
else //插到末尾
{
pre->next = pnew;
}
}
}
return head;
}
逆置单链表
题目
就地逆置一个链表(不允许申请新的结点空间)
例子:
h: 1 5 3 4
=>
h: 4 3 5 1
要求:
不允许申请新的结点空间
算法思路
把原链表的每一个结点 ,摘下来 ,然后按头插法 加入到新链表。
Node *reverse(Node *h)
{
//创建一个指向逆置后链表的第一个结点
//创建一个指针p为遍历指针
while(p)
{
//step 1:把h指向的链表的第一个结点摘下来
//step2: 按照头插法 把p结点 加入到逆置后的链表first
//step2.1 从无到有
//step2.2 从少到多
}
//返回逆置链表的第一个节点
}
代码实现
Node *reverrse(Node *h)
{
Node *first = NULL; //创建一个指向逆置后链表的第一个结点
Node *p = h; //创建一个指针p为遍历指针
while(p)
{
//step 1:把h指向的链表的第一个结点摘下来
h = h->next;
p->next = NULL;
//step2: 按照头插法 把p结点 加入到逆置后的链表first
//step2.1 从无到有
if(first == NULL)
{
first = p;
}
else //step2.2 从少到多
{
p->next = first;
first = p;
}
p = h;
}
return first; //返回逆置链表的第一个节点
}
判断单链表是否有环
题目
判断一个单链表是否有环
算法思路
快慢指针
定义两个指针p和q;
让p每次走两步,q每次走一步
当p和q相遇时则说明有环,否则就没有环。
代码实现
/*
is_a_ring:判断单链表是否有环
@h:指定的单链表的第一个节点指针
返回值:
1 有环
0 无环
*/
int is_a_ring(Node *h)
{
Node *p = NULL;//fast指针
Node *q = NULL;//slow指针
p = h;
q = h;
while(p)
{
p = p->next;
if(p == NULL)
{
break;
}
p = p->next;
q = q->next;
if(p == q)
{
return 1;
}
}
return 0;
}
取单链表中间节点的数值
题目
写一个程序,获取链表中间结点的值
例子:
对于奇数结点 返回中间结点值
输入 :1 2 3 4 5
输出:3
对于偶数结点 返回较小下标的值
输入: 25 69 78 45 96 -21 -47 62
输出:45
算法思路
定义两个指针p和q;
让p每次走两步 q走一步
当p走到链表末尾时 此时q刚好走到链表的中间结点。
代码实现
void get_middle_v(Node *h)
{
Node *pk = h; //快指针
Node *pm = h; //慢指针
while(1)
{
if(pk->next == NULL) //快指针已经到了最后一个(奇数个)
{
printf("%d\n",pm->data);
break;
}
else
{
pk = pk->next->next; //快指针的下一个是最后一个(偶数个)
if(pk == NULL)
{
printf("%d\n",pm->data);
break;
}
pm = pm->next;
}
}
}
总结
这些题目其实总体难度不高,更重要的是体会其中的算法思路,分类思想,利用好单链表本身的空间余节点取解决问题。
如果有帮助的话,欢迎点赞收藏哦~🤩,也可以点点关注,获取更多资源。