C++算法之 合并两个有序链表

题目:合并两个已经排序好的链表

方法1:

两个链表

比如链表1: 1->3->5->7->9

链表2:  2->4->6->8->10

跟我们合并两个数组一样,链表1的头结点  和链表2的头节点比较,如果链表1头节点的值大于链表2头接点的值,

那么链表2的头结点为合并链表的头结点,那么链表1的头节点继续和链表2的第二个节点(剩余链表2的头结点)

作比较,但一个链表遍历完之后,如果另外一个链表还没有遍历完,因为链表本来就是排序的,所以让合并链表的

尾巴节点指向未遍历完链表的头结点就可以

举个例子:

链表1: 1,3,5,23,34;

链表2: 2,4,6,8,10;

当遍历之后 链表3:1,2,3,4,8,10  此时链表2已经遍历完,while循环退出,但是剩余链表1还有 23,34

此时 让链表3的尾巴节点10 链接 剩余链表的头节点 23  就可以了

<span style="color:#000000;">// 合并链表.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

struct ListNode
{
	int         m_Data;
	ListNode*   m_pNext;
	ListNode(int value,ListNode* next = NULL):m_Data(value),m_pNext(next){}
};

/*
两个链表  比如链表1: 1->3->5->7->9
			链表2:  2->4->6->8->10

			跟我们合并两个数组一样,链表1的头结点  和链表2的头节点比较,如果链表1头节点的值大于链表2头接点的值,
			那么链表2的头结点为合并链表的头结点,那么链表1的头节点继续和链表2的第二个节点(剩余链表2的头结点)
			作比较,但一个链表遍历完之后,如果另外一个链表还没有遍历完,因为链表本来就是排序的,所以让合并链表的
			尾巴节点指向未遍历完链表的头结点就可以

			举个例子:

			链表1: 1,3,5,23,34;
			链表2: 2,4,6,8,10;
			当遍历之后 链表3:1,2,3,4,8,10  此时链表2已经遍历完,while循环退出,但是剩余链表1还有 23,34
			此时 让链表3的尾巴节点10 链接 剩余链表的头节点 23  就可以了
*/

ListNode* MergeList2(ListNode* head1,ListNode* head2)
{
	if (head1 == NULL)
	{
		return head2;
	}
	else if(head2 == NULL)
	{
		return head1;
	}

	ListNode* MergeHead = NULL;
	if (head1->m_Data < head2->m_Data)
	{
		MergeHead = head1;
		head1 = head1->m_pNext;
	}
	else
	{
		MergeHead = head2;
		head2 = head2->m_pNext;
	}
	ListNode* tmpNode = MergeHead;
	while (head1&&head2)
	{
		if (head1->m_Data < head2->m_Data)
		{
			MergeHead->m_pNext = head1;
			head1 = head1->m_pNext;
		}
		else
		{
			MergeHead->m_pNext = head2;
			head2 = head2->m_pNext;
		}
		MergeHead = MergeHead->m_pNext;
	}
	if (head1)
	{
		MergeHead->m_pNext = head1;
	}
	if (head2)
	{
		MergeHead->m_pNext = head2;
	}

	return tmpNode;

}
int _tmain(int argc, _TCHAR* argv[])
{
	ListNode* pHead1 = new ListNode(1);
	ListNode* pCur = pHead1;
	for (int i = 3; i < 10; i+=2)
	{
		ListNode* tmpNode = new ListNode(i);
		pCur->m_pNext = tmpNode;
		pCur = tmpNode;
	}

	ListNode* pHead2 = new ListNode(2);
	pCur = pHead2;
	for (int j = 4; j < 10; j+=2)
	{
		ListNode* tmpNode = new ListNode(j);
		pCur->m_pNext = tmpNode;
		pCur = tmpNode;
	}

	ListNode* head = MergeList2(pHead1,pHead2);
	while (head)
	{
		cout<<head->m_Data<<" ";
		head=head->m_pNext;
	}

	getchar();
	return 0;
}</span>

方法2:

/*

我们分析两个链表的过程,首先从合并两个链表的头结点开始,链表1的头节点的值小于链表2的头结点的值,因此链表1的头结点

就是合并链表的头节点,继续合并剩下的链表,在两个链表中剩余的节点仍然是排序的,因此合并两个链表的步骤是一样的,我们还是比较两个头结点的

值,此时链表2的头结点的值小于链表1的头结点的值,因此链表2的头结点是合并剩余链表的头结点,我们把这个节点和前面合并链表时得到的链表的尾巴节点

链接起来

按照上面的分析可知:每次合并的步骤都是一样的,由此我们想到了递归。

*/

// 合并链表.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

struct ListNode
{
	int         m_Data;
	ListNode*   m_pNext;
	ListNode(int value,ListNode* next = NULL):m_Data(value),m_pNext(next){}
};

/*
我们分析两个链表的过程,首先从合并两个链表的头结点开始,链表1的头节点的值小于链表2的头结点的值,因此链表1的头结点
就是合并链表的头节点,继续合并剩下的链表,在两个链表中剩余的节点仍然是排序的,因此合并两个链表的步骤是一样的,我们还是比较两个头结点的
值,此时链表2的头结点的值小于链表1的头结点的值,因此链表2的头结点是合并剩余链表的头结点,我们把这个节点和前面合并链表时得到的链表的尾巴节点
链接起来

按照上面的分析可知:每次合并的步骤都是一样的,由此我们想到了递归。

*/

ListNode* MergeList(ListNode* pHead1,ListNode* pHead2)
{
	if (pHead1 == NULL)
	{
		return pHead2;
	}
	else if (pHead2 == NULL)
	{
		return pHead1;
	}

	ListNode* pMergeHead = NULL;
	if (pHead1->m_Data < pHead2->m_Data)
	{
		pMergeHead = pHead1;
		pMergeHead->m_pNext = MergeList(pHead1->m_pNext,pHead2);

	}
	else
	{
		pMergeHead = pHead2;
		pMergeHead->m_pNext = MergeList(pHead1,pHead2->m_pNext);
	}

	return pMergeHead;

}

int _tmain(int argc, _TCHAR* argv[])
{
	ListNode* pHead1 = new ListNode(1);
	ListNode* pCur = pHead1;
	for (int i = 3; i < 10; i+=2)
	{
		ListNode* tmpNode = new ListNode(i);
		pCur->m_pNext = tmpNode;
		pCur = tmpNode;
	}

	ListNode* pHead2 = new ListNode(2);
	pCur = pHead2;
	for (int j = 4; j < 10; j+=2)
	{
		ListNode* tmpNode = new ListNode(j);
		pCur->m_pNext = tmpNode;
		pCur = tmpNode;
	}

	ListNode* head = MergeList2(pHead1,pHead2);
	while (head)
	{
		cout<<head->m_Data<<" ";
		head=head->m_pNext;
	}

	getchar();
	return 0;
}

看了这道题目,那么上次的合并数组也可以用递归这里附上代码:

<span style="color:#000000;">// MergeArray.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

//递归方法
void MergeArray2(int a[],int aCount,int b[],int blen)
{

	int len = aCount+blen-1;

	aCount--;
	blen--;
	if (aCount < 0)
	{
		while (blen>=0)
		{
			a[len--] = b[blen--];
		}

		return;
	}

	if (a[aCount] > b[blen])
	{
		a[len] = a[aCount];
		MergeArray2(a,aCount,b,++blen);
	}
	else
	{
		a[len] = b[blen];
		MergeArray2(a,++aCount,b,blen);
	}

}

void MergeArray(int a[], int aCount, int b[], int blen)//aCount为a数组实际(狭义)长度,blen为b数组实际长度
{
	int len = aCount + blen - 1;//合并数组的长度也就是a数组的广义长度
	aCount--;
	blen--;
	while (aCount>=0 && blen>=0)
	{
		if (a[aCount] >= b[blen])
		{
			a[len--] = a[aCount--];
		}
		else
		{
			a[len--] = b[blen--];
		}
	}
	while(blen >= 0)
	{
		a[len--] = b[blen--];
	}

}

int _tmain(int argc, _TCHAR* argv[])
{
	int a[] = {2,4,6,8,10,0,0,0,0,0};
	int b[] = {1,3,5,7,9};

	MergeArray2(a,5,b,5);
	for (int i = 0; i < sizeof(a)/sizeof(a[0]); i++)
	{
		cout<<a[i]<<" ";
	}

	getchar();
	return 0;
}</span>

个人感觉合并数组用递归不太好,因为考虑如果一个数组遍历完另一个数组还没有遍历完这个情况有点麻烦,而如果是链表的话,一个数链表历完,

那么这个链表为空,则返回另外一个链表就可以了,也就是前面合并好的链表自动链接上另外没有遍历完的链表的那部分!

时间: 2024-10-07 17:24:14

C++算法之 合并两个有序链表的相关文章

经典算法学习——合并两个有序链表

类似的,合并两个有序的数组或者链表也是剑指Offer中的经典题型.题目描述如下:输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是按照递增排序的.我这里以合并链表来实现. 在这里,并不需要去创建一个新的链表,只要有三个节点指针就行,第一个节点指针Node1指向第一个链表,第二个节点指针Node2指向第二个链表,第三个节点指针Node3指向新的链表.简单的示意图如下: 当下一个节点在第一个链表中时,Node3指向该节点,Node1++,以此类推.直到某一个链表为空时,把另一个链表全部接

每天一个小算法(2)----合并两个有序链表

每天一个小算法还是有点没时间,尽量抽出时间写一写. 今天是合并有序的链表,对单链表有点忘了,尤其是指针指来指去的,有点晕,幸好基础还算好,想了想还是能想回来. 代码使用随机数函数生成一个链表,然后对链表排序,最后合并链表并打印,删除链表的函数于算法无关紧要,所以未实现^_^. 在Linux/g++下编译运行成功. 合并思路:和合并数组有些类同,比较两个节点的元素大小然后将小的摘下来尾插到链表bList中,然后指针指向下一个节点,最后直接把非空的链表合并到bList的末尾. 1 #include

算法题——合并两条有序的链表

题目:给定两个已排序的链表,返回合并后的链表. 思路:将链表L2的每个结点插入到链表L1中,时间复杂度为O(m+n),m.n分别为两条链表的长度. 代码: 1 struct ListNode 2 { 3 int value; 4 ListNode *next; 5 ListNode(int v): value(v), next(NULL) 6 { 7 } 8 }; 9 10 ListNode *mergeSortedList(ListNode *L1, ListNode *L2) 11 { 12

链表(14)----合并两个有序链表

1.链表定义 typedef struct ListElement_t_ { void *data; struct ListElement_t_ *next; } ListElement_t; typedef struct List_t_{ int size; int capacity; ListElement_t *head; ListElement_t *tail; } List_t; 2.合并两个有序链表 ListElement_t * MergeList( ListElement_t *

合并两个有序链表

题目描述: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. (hint: 请务必使用链表.) 输入: 输入可能包含多个测试样例,输入以EOF结束. 对于每个测试案例,输入的第一行为两个整数n和m(0<=n<=1000, 0<=m<=1000):n代表将要输入的第一个链表的元素的个数,m代表将要输入的第二个链表的元素的个数. 下面一行包括n个数t(1<=t<=1000000):代表链表一中的元素.接下来一行包含m个元素,s(1

小算法:合并两个有序数组,合并之后仍然有序

1 /** 2 * 合并两个有序数组,合并后仍然有序 3 * @param a 要合并的数组A 4 * @param b 要合并的数组B 5 * @param c 合并后的数组C 6 */ 7 public static void merge(int a[] ,int b[],int c[]){ 8 int lengthA = a.length; 9 int lengthB = b.length; 10 11 int indexA = 0; 12 int indexB = 0; 13 int i

[leetcode] 21. 合并两个有序链表

21. 合并两个有序链表 两个有序链表合并为一个新的有序链表 class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode ans = new ListNode(Integer.MAX_VALUE); ListNode p = ans; while (l1 != null && l2 != null) { if (l1.val < l2.val) { p.next = l1; l

[LeetCode]21 Merge Two Sorted Lists 合并两个有序链表

---恢复内容开始--- [LeetCode]21 Merge Two Sorted Lists 合并两个有序链表 Description Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. Example Example: Input: 1->2->4, 1-&g

leecode刷题(23)-- 合并两个有序链表

leecode刷题(23)-- 合并两个有序链表 合并两个有序链表 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4 思路: 这道题我们可以用递归的方法来处理.首先我们可以设置一个临时头节点 head,当链表 l1 和链表 l2 不为空时,对它们进行比较.如果 l1 对应的节点小于或等于 l2 对应的节点,则将 head