【数据结构】--oj_合并两个有序链表(详解)

这篇具有很好参考价值的文章主要介绍了【数据结构】--oj_合并两个有序链表(详解)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

合并两个有序链表,【数据结构】知识篇+代码讲解,链表,数据结构,算法

目录

方法一:无头结点的方法 

方法二:有头结点的方法


题述:

已给函数头:

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)

已给出链表的结构体定义:

struct ListNode
{
    struct ListNode* next;
    int val;
};

已知l1、l2分别指向两个链表

要求:

将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。(完善mergeTwoLists函数

示例:合并两个有序链表,【数据结构】知识篇+代码讲解,链表,数据结构,算法

方法一:无头结点的方法 

思路:1、依次比较链表中的节点,每次取小的节点,尾插到新的链表后面。

问题一:找到较小的节点后,那是不是就要找到尾节点进行尾插,难道每次尾插完都找尾节点吗?这样效率肯定很低,所以我们可以再用一个指针tail来存尾节点。再创建一个指针head用来表示另一个没有头结点的新链表。 后续的尾插我们就可以尾插到head链表中

问题二:这个单链表是否有头结点,有头结点是一种情况,没有头结点就是另一种情况,相比而言有头节点的方式更简单,oj题一般都是默认链表无头结点的,但是我们可以创建头结点,所以这就可以推出两种方法

合并两个有序链表,【数据结构】知识篇+代码讲解,链表,数据结构,算法

合并两个有序链表,【数据结构】知识篇+代码讲解,链表,数据结构,算法

 代码如下:

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
	//如果其中一个为空,就返回另一个
	if (l1 == NULL)
	{
	//如果刚开始就有一个为空
	//那就直接返回另一个
	//如果两个都是NULL,那正好返回NULL就好了
		return l2;
	}
	if (l2 == NULL)
	{
		return l1;
	}
	struct ListNode* head = NULL, * tail = NULL;
	while (l1 && l2)
	{//循环走下去的条件就是l1和l2均不为NULL
	//如果其中一个为空了,就说明走完了
		if (l1 ->val < l2->val)
		{
			if (head == NULL)
			{
			//第一次尾插的话,我们是在新链表无头结点的情况下
			// 后续的插入才会在有节点的情况,
			// 而这两种情况代码不同,所以要分类讨论
			//所以直接使头和尾被赋值为l1
			//tail主要是用来找尾节点的
				head = tail = l1;
			}
			else
			{
			//进入else,说明新创的链表中已经有节点,所以
			//直接插入在后面的节点
				tail->next = l1;//尾插节点
				tail = l1;//tail用来保存尾节点
			}
			l1 = l1->next;//每次尾插完一个数据,l1会往后走
		}
		else
		{
			if (head == NULL)
			{
				//第一次尾插
				head = tail = l2;
			}
			else
			{
				tail->next = l2;
				tail = l2;
			}
			l2 = l2->next;
		}
	}
	if (l1)
	{//如果l1不为空,那么就是l2走完了
	//此时直接把l1剩余部分尾插到新链表中即可
		tail->next = l1;
	}
	if (12)
	{
		tail->next = l2;
	}
	return head;
}

 上段代码的缺点就是while循环中对于l1和l2有几处重复部分,所以可以在上段代码的基础上再修改一下,思路一样,head原来为NULL,那我就先找一个最小的让head指向这个节点就行,就不用在while循环中l1和l2先判断if才行,下面是更简洁的代码:

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
	//如果其中一个为空,就返回另一个
	if (l1 == NULL)
	{
		//如果刚开始就有一个为空
		//那就直接返回另一个
		//如果两个都是NULL,那正好返回NULL就好了
		return l2;
	}
	if (l2 == NULL)
	{
		return l1;
	}
	struct ListNode* head = NULL, * tail = NULL;
	//先取两个链表中一个小的去做第一个
	//能做第一个,因为两个链表都是升序的
	if (l1->val < l2->val)
	{
		head = tail = l1;
		l1 = l1->next;
	}
	if (l1->val > l2->val)
	{
		head = tail = l2;
		l2 = l2->next;
	}
	while (l1 && l2)
	{//循环走下去的条件就是l1和l2均不为NULL
	//如果其中一个为空了,就说明走完了
		if (l1->val < l2->val)
		{
			tail->next = l1;//尾插节点
			tail = l1;//tail用来保存尾节点
			l1 = l1->next;//每次尾插完一个数据,l1会往后走
		}
		else
		{
			tail->next = l2;
			tail = l2;
			l2 = l2->next;
		}
	}
	if (l1)
	{//如果l1不为空,那么就是l2走完了
	//此时直接把l1剩余部分尾插到新链表中即可
		tail->next = l1;
	}
	if (l2)
	{
		tail->next = l2;
	}
	return head;
}

方法二:有头结点的方法

原来我们题目给的是没有头结点的,但是我们可以自己创建一个头结点,他不存储数据,他是为了使后面找元素方便,值得注意的是这个head和tail都要动态内存开辟一个,最后在用完之后还需要释放,并且最后不能直接return head,要return head->next,因为题目本来就没给你头结点,你就不能返回你自己创建的头,本质上应该从head->next开始文章来源地址https://www.toymoban.com/news/detail-724451.html

#include<stdio.h>
#include<stdlib.h>
struct ListNode
{
	struct ListNode* next;
	int val;
};
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
	//如果其中一个为空,就返回另一个
	if (l1 == NULL)
	{
		//如果刚开始就有一个为空
		//那就直接返回另一个
		//如果两个都是NULL,那正好返回NULL就好了
		return l2;
	}
	if (l2 == NULL)
	{
		return l1;
	}
	struct ListNode* head = NULL, * tail = NULL;
	//哨兵位的头结点,head和tail刚开始均指向头结点
	head = tail = (struct ListNode*)malloc(sizeof(struct ListNode));
	while (l1 && l2)
	{//循环走下去的条件就是l1和l2均不为NULL
	//如果其中一个为空了,就说明走完了
		if (l1->val < l2->val)
		{
			tail->next = l1;//尾插节点
			tail = l1;//tail用来保存尾节点
			l1 = l1->next;//每次尾插完一个数据,l1会往后走
		}
		else
		{
			tail->next = l2;
			tail = l2;
			l2 = l2->next;
		}
	}
	if (l1)
	{//如果l1不为空,那么就是l2走完了
	//此时直接把l1剩余部分尾插到新链表中即可
		tail->next = l1;
	}
	if (l2)
	{
		tail->next = l2;
	}
	struct ListNode* list = head->next;
	free(head);
	return list;
}

到了这里,关于【数据结构】--oj_合并两个有序链表(详解)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【每日算法 && 数据结构(C++)】—— 03 | 合并两个有序数组(解题思路、流程图、代码片段)

    【每日算法 && 数据结构(C++)】—— 03 | 合并两个有序数组(解题思路、流程图、代码片段)

    An inch of time is an inch of gold, but you can’t buy that inch of time with an inch of gold. An inch of time is an inch of gold, but you can\\\'t buy that inch of time with an inch of gold 给你两个有序数组,请将两个数组进行合并,并且合并后的数组也必须有序 这个题目要求将两个有序数组合并成一个有序数组。在数

    2024年02月11日
    浏览(11)
  • 合并两个有序链表(精美图示详解哦)

    合并两个有序链表(精美图示详解哦)

    在前面两篇文章中,我们介绍了几道链表的习题:反转链表、链表的中间结点、链表的倒数第k个结点: 戳我看反转链表详解哦 戳我看链表的中间结点与链表的倒数第k个结点详解哦 本篇文章中,将继续介绍关于链表的题目:合并两个有序链表: 合并两个有序链表OJ链接 这道

    2024年02月08日
    浏览(4)
  • 【数据结构】链表OJ面试题(《删除定值、反转、返回中间结点、倒数第k节点、合并链表》)+解析)

    【数据结构】链表OJ面试题(《删除定值、反转、返回中间结点、倒数第k节点、合并链表》)+解析)

    还不清楚链表的码喵们可以看看前篇关于链表的详解 既然已经懂得了链表该如何实现,那么现在就趁热打铁开始练习!这里给码喵们整理了相对不错的一些OJ题来练习  力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 思路:遍历整个表,访问每个表的值并且删除再将nex

    2024年02月22日
    浏览(12)
  • 【Java--数据结构】链表经典OJ题详解(上)

    【Java--数据结构】链表经典OJ题详解(上)

    欢迎关注个人主页:逸狼 创造不易,可以点点赞吗~ 如有错误,欢迎指出~ 目录 谈谈头插、头删、尾插、头插的时间复杂度 反转一个单链表  链表的中间结点 返回倒数第k个结点 合并两个链表 头插和头删的时间复杂度为O(1), 尾插和尾删的时间复杂度为O(n) (因为尾插和

    2024年04月27日
    浏览(9)
  • 【数据结构】——线性表(顺序表加链表),万字解读(加链表oj详解)

    【数据结构】——线性表(顺序表加链表),万字解读(加链表oj详解)

    前言 由于之前存在过对两者的区别考虑,所以把他们放在一起来说,更加容易区别和理解 对于有关线性表的概念这里就不展示了,这里主要是介绍线性表里面的这两个结构的知识点 一.顺序表 1.顺序表介绍 顺序表的存储结构和逻辑结构都是相邻的, 这里如果我们把a1的地址

    2024年03月22日
    浏览(27)
  • 【链表OJ】链表中倒数第k个结点 合并两个链表(含哨兵位) 分割链表 链表的回文结构

    【链表OJ】链表中倒数第k个结点 合并两个链表(含哨兵位) 分割链表 链表的回文结构

    前言: 💥🎈个人主页:​​​​​​Dream_Chaser~ 🎈💥 ✨✨刷题专栏:http://t.csdn.cn/UlvTc ⛳⛳本篇内容:力扣和牛客上链表OJ题目 目录  一、链表中倒数第k个结点 题目描述: 解题思路: 二.合并两个链表(含哨兵位)  题目描述: 解题思路:                                     

    2024年02月12日
    浏览(57)
  • 27、链表-合并两个有序链表

    27、链表-合并两个有序链表

    这道题不需要集合放入两个链表再进行重排序,只需要两个指针,按大小进行遍历,代码如下:  

    2024年04月14日
    浏览(8)
  • 21. 合并两个有序链表

    21. 合并两个有序链表

     

    2024年02月12日
    浏览(12)
  • 21.合并两个有序链表

    21.合并两个有序链表

    一、思路 二、源码 创建一个新链表 两个链表比较,小于等于取下来尾插 循环结束条件为任意一个链表为空 最后将之剩下的链表直接尾插

    2024年01月23日
    浏览(9)
  • 合并两个有序链表

    合并两个有序链表

    题目链接 :力扣21,合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 首先我们能够想到的就是 遍历一遍数组,判断两个结点的大小,将数值小的结点放在前面,数值大的不断尾插在后面 。是不是听

    2023年04月27日
    浏览(13)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包