大厂面试经典单链表例题(创建有序单链表,逆置单链表,判断链表是否有环,取链表中间节点)(含核心代码与解析)

目录

引言

创建有序单链表

题目

算法思路

代码实现

逆置单链表

题目

算法思路

代码实现

判断单链表是否有环

题目

算法思路

代码实现

取单链表中间节点的数值

题目

算法思路

代码实现

总结


引言

有关单链表的基础操作,如动态分布空间,单链表创建的思路,单链表的增、删、改、毁,笔者已经在上一篇博客中详细解析了,有兴趣的小伙伴也可以取看看,数据结构之单链表一生的历程(创建一个线性表,动态分布空间,单链表创建的思路,单链表的增、删、改、毁)_勾栏听曲_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;
		}
	}
}

总结

这些题目其实总体难度不高,更重要的是体会其中的算法思路,分类思想,利用好单链表本身的空间余节点取解决问题。

如果有帮助的话,欢迎点赞收藏哦~🤩,也可以点点关注,获取更多资源。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

勾栏听曲_0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值