算法导论6.5-8习题解答(最小堆K路合并)
来源:互联网 发布:淘宝2017双11销售额 编辑:程序博客网 时间:2024/05/21 14:53
《算法导论》第六章第五节的第8题,原题为:请给出一个时间为O(nlgk)、用来将k个已排序链表合并为一个排序链表的算法。此处n为所有输入链表中元素的总数。(提示:用一个最小堆来做k路合并)。
算法思想:
1. 从k个链表中取出每个链表的第一个元素,组成一个大小为k的数组arr,然后将数组arr转换为最小堆,那么arr[0]就为最小元素了
2. 取出arr[0],将其放到新的链表中,然后将arr[0]元素在原链表中的下一个元素补到arr[0]处,即arr[0].next,如果 arr[0].next为空,即它所在的链表的元素已经取完了,那么将堆的最后一个元素补到arr[0]处,堆的大小自动减一,循环n-k次即可。
为了方便粘贴,把.h和.cpp都弄在一起,首先是两个类List和Node,然后就是两个关于最小堆操作的函数,代码有点长,但是一点都不难,因为你肯定看过最大堆的操作,那么最小堆就大同小异了:
#include <iostream>
usingnamespace std;
class Node
{
public:
Node* next;
int data;
Node();
Node(int d);
operator Node()const;
//只需用到"<"号
booloperator < (const Node& temp);
};
class List
{
public:
Node* first;
List();
void insert(int d);
};
//修正i的位置,在此处已经假设i的子节点都是堆
void min_heapify(Node* &a,int i,int length);
//建立数组的堆
void build_min_heap(Node* &a,int length);
int main()
{
int K =5;
List* list_one = new List();
List* list_two = new List();
List* list_three = new List();
List* list_four = new List();
List* list_five = new List();
for(int i =0; i <5; i++)
{
list_one->insert(i);
list_two->insert(i - 3);
list_three->insert(i + 5);
list_four->insert(2*i);
list_five->insert(i - 10);
}
Node* arr = new Node[K];
arr[0] = *(list_one->first);
arr[1] = *(list_two->first);
arr[2] = *(list_three->first);
arr[3] = *(list_four->first);
arr[4] = *(list_five->first);
//先对这K个排序
build_min_heap(arr, K);
List* list = new List();
//每次取arr[0]的下一个Node,如果Node为空的话,
//则把堆末尾的元素补到arr[0],由于有--K,所以堆的大小减一
while(K >0)
{
list->insert(arr[0].data);
if(arr[0].next != NULL)
arr[0] = *(arr[0].next);
else
arr[0] = arr[--K];
min_heapify(arr, 0, K);
}
Node* begin = list->first;
while(begin != NULL)
{
cout<<begin->data<<endl;
begin = begin->next;
}
return0;
}
void min_heapify(Node* &a,int i,int length)
{
int smallest = i;
while(smallest <= length -1)
{
int left =2*smallest +1;
int right =2*smallest +2;
int temp = smallest;
if(left <= length -1 && a[left] < a[smallest])
{
smallest = left;
}
if(right <= length -1 && a[right] < a[smallest])
{
smallest = right;
}
if(smallest != temp)
{
Node exchange = a[smallest];
a[smallest] = a[temp];
a[temp] = exchange;
}
else
break;
}
}
void build_min_heap(Node* &a,int length)
{
int root = length/2 -1;
for(int i = root; i >=0; i--)
min_heapify(a, i, length);
}
Node::Node()
{
next = NULL;
}
Node::Node(int d)
{
data = d;
next = NULL;
}
Node::operator Node() const
{
return data;
}
bool Node::operator<(const Node& temp)
{
if(data < temp.data)
returntrue;
returnfalse;
}
List::List()
{
first = NULL;
}
void List::insert(int d)
{
Node* node = new Node(d);
if(first == NULL)
first = node;
else
{
Node* temp = first->next;
Node* prev = first;
while(temp != NULL)
{
prev = temp;
temp = temp->next;
}
prev->next = node;
}
}
原文链接:http://www.cnblogs.com/shuaiwhu/archive/2011/03/20/2065077.html
- 算法导论6.5-8习题解答(最小堆K路合并)
- 算法导论 第六章 堆排序 习题6.5-8 k路合并排序
- 算法导论6.5-8堆排序-K路合并
- 算法导论6.5-8堆排序-K路合并
- 算法导论最小堆实现k路归并
- 算法导论-6.5-9 使用最小堆完成k路归并算法
- 《算法导论》 - 第6章 - 堆排序 - 习题解答
- 【通告】算法导论习题解答
- “用最小堆将k个已排序链表合并为一个排序链表”(算法导论 练习6.5-9)
- 算法导论 最小堆
- 算法导论 6.5-8解答
- 算法导论 堆排序习题
- 算法导论 习题6.5-8
- 算法导论 习题 6.5-8
- 算法导论动态规划课后习题解答
- 算法导论习题15.5-1解答
- 算法导论习题32.1-4解答
- 算法导论第三版4.1习题解答
- Comodo防火墙导致vmware虚机无法获得ip地址
- Liunx下修改MySQL字符集
- properties文件操作类
- 【iOS-Cocos2d游戏开发之十八】解决滚屏背景/拼接地图有黑边(缝隙)以及禁止游戏中自动锁屏问题
- 动态申请内存方式和数组的比较
- 算法导论6.5-8习题解答(最小堆K路合并)
- How to deal with "Incorrect NSStringEncoding value 0×0000 Error with ASIHTTPRequest" problem?
- [ASP.NET] UpdatePanel局部刷新 -- 与用户控件使用
- 不同平台的换行符
- 数字签名原理剖析
- spring quartz.SchedulerFactoryBean 定时启动检测排期是否过期
- HTC XV6850 Android系统移植资源索引
- 如何隐藏盘符
- uiview的frame,bounds,center的几个关系