多个有序链表的合并

1, 先将问题简化,合并两个有序链表

首先分析合并两个链表的过程。我们的分析从合并两个链表的头结点开始。链表1的头结点的值小于链表2的头结点的值,因此链表1的头结点将是合并后链表的头结点。如下图所示。

参考:http://www.cnblogs.com/jason2013/articles/4341153.html

使用递归方法,一步步生成头结点,代码如下

递归的要诀是子问题要和父问题完全一样,只是规模变小(每次调用,更小的参数值),

 1 List merge(List head1, List head2){
 2     List mergeHead = NULL;
 3     if (head1 == NULL) {
 4         return head2;
 5     }
 6     if (head2 == NULL){
 7         return head1;
 8     }
 9
10     if (head1->item < head2->item){
11         mergeHead = head1;
12         mergeHead->next = merge(head1->next, head2);
13     }else{
14         mergeHead = head2;
15         mergeHead->next = merge(head1, head2->next);
16     }
17     return mergeHead;
18 }

2, 当有多个链表时,考虑分治法每两个链表进行合并.

确定父子函数原型,要想使用递归,子问题和父问题必须完全一样(即返回值,参数类型完全一致)

父问题:多个链表

子问题:n/2,...,2个链表,1个链表

递归函数原型List mergeList(int l, int r)

父子问题都是返回一个合并后链表,

使用l,r 两个变量控制问题规模,指定链表个数(快速排序,归并排序都喜欢用这样的两个参数)

将多个链表存放在全局变量vector<List> lists中,简化递归函数.

第9行代码复用前面提到的两个有序链表合并

 1 List mergeList(int l, int r){
 2     List u, v;
 3     int m = (l + r) / 2;
 4     if (l == r) {
 5         return lists[l];
 6     }
 7     u = mergeList(l, m);
 8     v = mergeList(m + 1, r);
 9     return merge(u, v);
10 }

3, main 函数

 1 int main(void)
 2 {
 3     int size = 8;
 4     int num = 5;
 5     ListFactory(size, num);
 6     for (int i = 0; i < size; i++){
 7         print(lists[i]);
 8     }
 9     cout << endl;
10     link t = mergeList(0, size-1);
11     print(t);
12     return 0;
13 }

效果

1->9->17->25->33->
2->10->18->26->34->
3->11->19->27->35->
4->12->20->28->36->
5->13->21->29->37->
6->14->22->30->38->
7->15->23->31->39->
8->16->24->32->40->

1->2->3->4->5->6->7->8->9->10->11->12->13->14->15->16->17->18->19->20->21->22->23->24->25->26->27->28->29->30->31->32->33->34->35->36->37->38->39->40->

完整程序

 1 #include<iostream>
 2 #include<string>
 3 #include<vector>
 4 using std::cin;
 5 using std::cout;
 6 using std::endl;
 7 using std::string;
 8 using std::vector;
 9 typedef struct node* link;
10 struct node{
11     int item;
12     link next;
13 };
14 typedef link List;
15 vector<List> lists;
16 void print(List list){
17     while (list != NULL){
18         cout << list->item<< "->";
19         list = list->next;
20     }
21     cout << endl;
22 }
23
24 vector<List> ListFactory(int num, int size){
25     for (int k = 1; k <= num; k++){
26         link t = (link)malloc(sizeof *t);
27         t->item = k;
28         t->next = t;
29         link x = t;
30         for (int m = k + num; m <= num*size; m = m+num){
31             x = (x->next = (link)malloc(sizeof *x));
32             x->item = m;
33             x->next = t;
34         }
35         x->next = NULL;
36         lists.push_back(t);
37     }
38     return lists;
39 }
40
41 List merge(List head1, List head2){
42     List mergeHead = NULL;
43     if (head1 == NULL) {
44         return head2;
45     }
46     if (head2 == NULL){
47         return head1;
48     }
49
50     if (head1->item < head2->item){
51         mergeHead = head1;
52         mergeHead->next = merge(head1->next, head2);
53     }else{
54         mergeHead = head2;
55         mergeHead->next = merge(head1, head2->next);
56     }
57     return mergeHead;
58 }
59
60 List mergeList(int l, int r){
61     List u, v;
62     int m = (l + r) / 2;
63     if (l == r) {
64         return lists[l];
65     }
66     u = mergeList(l, m);
67     v = mergeList(m + 1, r);
68     return merge(u, v);
69 }
70
71 int main(void)
72 {
73     int size = 8;
74     int num = 5;
75     ListFactory(size, num);
76     for (int i = 0; i < size; i++){
77         print(lists[i]);
78     }
79     cout << endl;
80     link t = mergeList(0, size-1);
81     print(t);
82     return 0;
83 }

时间: 2024-10-03 04:45:29

多个有序链表的合并的相关文章

有序链表的合并

/* Name: 有序链表的合并 Copyright: Author: 巧若拙 Date: 22-11-14 16:13 Description: 分别用递归和非递归两种方式实现两个有序链表(不含头结点)的合并 */ #include<stdio.h> #include<stdlib.h> #include<malloc.h> typedef char ElemType; typedef int Status; //函数类型,其值是函数结果状态代码,如OK等 typed

数据结构学习---有序链表的合并

递归调用 简单 有点像归并排序的合并部分吧. 因为是用vs创建的工程,所以主函数是_tmain. 1 // 链表.cpp : 定义控制台应用程序的入口点. 2 // 3 4 #include "stdafx.h" 5 6 7 typedef struct Node { 8 int data; 9 struct Node *next; 10 11 } LinkList; 12 13 14 //链表组合的函数 输入:两个有序无头结点链表 输出:将链表组合成一个无头结点有序链表 15 Lin

递归实现两个有序链表的合并

package com.wyl.linklist; /** * 合并两个链表 * @author wyl */ public class MergeLinkList { /** * 内部类,链表节点的结构 * @author wyl * */ public static class Node{ private int val; //节点值 private Node next; //节点的后继节点 public Node(){ } public Node(int val){ this(val,nu

两个有序链表的合并

笔记和代码的思路来源: 好大学慕课浙江大学陈越.何钦铭的<数据结构> 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 typedef int ElementType; 5 typedef struct Node *PtrToNode; 6 struct Node { 7 ElementType Data; 8 PtrToNode Next; 9 }; 10 typedef PtrToNode List; 11 12 List

合并N个有序链表与FQ公平调度

下大雨了,于是就想表达一些只有下雨才能表达的东西.夜半酒酣惊觉起,使我流泪忆江南-前天晚上下班带着小小在暴雨中狂奔,非常舒服,其实也算是流言终结者吧.反驳一下几千年来在我国北方通过长辈代代相传的淋雨和感冒之间的因果关系. ??昨天早上很早起来,听雨作文,今天早上继续,文章不算太长. 合并两个有序链表 这是一道超级常见的课后作业题或者面试题,网上答案一搜一箩筐,我自己也写了一个不会编程版: 有序链表合并C语言递归版–我稍微会一点编程:https://blog.csdn.net/dog250/art

详谈单链表之合并and冒泡排序

<span style="font-family:KaiTi_GB2312;font-size:18px;"><strong> 线性表一章基本看完了,但是感觉还学得太少,应该和一些经典的算法相结合,看看自己应用的如何.不得不承认自己只是做简单的实现,并没有对代码进行太多的优化...希望各位大神莫怪~~废话少说,代码搞起..</strong></span> <strong><span style="font-fa

K个排序链表的合并(Hard)

问题来源:选自leetCode 23:合并K个排序链表 问题描述: 题目给定信息: 不确定需要合并的链表的数目,但依然要求我们把给定的这些有序链表合并成一个链表,并且保证合并的链表依然是有序的. 问题分析: 我们可以使用暴力合并的方法,就是不管有多少个链表,先让第一个链表和第二个链表进行合并,合并之后的结果在和第三个链表进行合并,依次进行下去直到把全部的链表全部合并成一个链表,这种方法是最简单最易想到的方法,但是时间复杂度太高了:还有一种方法是把所有链表中的节点值保存到一个数组中,然后对这个数组

链表(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 *

23. Merge k Sorted Lists 合并K个有序链表

这道题是21题合并2个有序链表的升级版本,看了许多解题思路: A:直接暴力解锁,全部放进一个堆,然后依次吐出来: B:利用21题的算法,循环一次做两两合并,这样就得到结果:但是时间复杂度有点差: C:利用归并排序思想,进行分治:其实就是利用递归,牺牲空间,提升时间效率: 存在的问题是:看过了许多解答后发现,大家基于的给定数据类型是 List<ListNode>/ArrayList<ListNode>,然后,现在系统更新了,给的数据类型是 ListNode[] lists,所以,我现