算导--6.5-9使用最小堆完成k路归并问题

题目:请设计一个时间复杂度为O(nlgk)的算法,它能够将k个有序链表合并为一个有序链表,这里n是所有输入链表包含 的总的元素个数。

(提示:使用最小堆完成k路归并)

思路:建一个大小为k的堆,堆中的每个元素代表一个List,元素的key为List当前最小元素的值,调整为最小堆,取出堆顶的元素,并记录到排序结果中,然后插入相应List中下一个元素的值作为新的堆顶元素key的值,然后调整堆为最小堆,并记录到排序结果中,如果该List没有下一个元素要插入,就删除List所在的结点,然后调整堆为最小堆,依次进行下去,直到n个元素归并完毕。

C++实现如下:

#include <iostream>
#include <vector>
using namespace std;

#include <stdlib.h>

#include "Exercise6_5_8.h"
#include "Heap.h"

#define K 10
#define DATA_COUNT 100

ostream& operator<<(ostream & s, const node & n)
{
	s << n.value;
	return s;
}

//5个链表,每个链表的头结点放入Head中
int mergeResult[DATA_COUNT+1] = {0};
CMaxHeap<node> H(K, node::getMaxNode());

vector<ARRAY> buildTestData();
void showTestData(vector<ARRAY> inputParam);
void insertListHeadToHeap(vector<ARRAY> &inputParam, int listIndex);
void showResult();
void recordMergeResult(int data);
ARRAY solve_6_5_8(vector<ARRAY> inputParam);

int K_Merge_6_5_8()
{
	vector<ARRAY> inputParam = buildTestData();
	showTestData(inputParam);

	ARRAY result = solve_6_5_8(inputParam);

	showResult();
	return 0;
}

ARRAY solve_6_5_8(vector<ARRAY> inputParam)
{
	ARRAY ret;
	while(H.isEmpty() == false)
		H.extract();

	for(int i = 0; i < inputParam.size(); i++)
		insertListHeadToHeap(inputParam, i);
	while(H.isEmpty() == false)
	{
		node top = H.extract();
		ret.push_back(top);
		insertListHeadToHeap(inputParam, top.list);
	}
	return ret;
}

vector<ARRAY> buildTestData()
{
	int value, list;
		//构造需要合并的数据
	vector<ARRAY > ret(K);
	for(value = DATA_COUNT; value >0; value--)
	{
		list = rand() % K;
		node newNode;// = {list, value};
		newNode.list = list;
		newNode.value = value;
		ret[list].push_back(newNode);
	}
	return ret;
}

void showTestData(vector<ARRAY> inputParam)
{
	cout<<"显示待排序数据"<<endl;
	for(int i = 0; i < inputParam.size(); i++)
	{
		ARRAY array = inputParam[i];
		for(int j = 0; j < array.size(); j++)
			cout<<array[j].value<<' ';
		cout<<endl;
	}
}

void insertListHeadToHeap(vector<ARRAY> &inputParam, int  listIndex)
{
	ARRAY &array = inputParam[listIndex];
	if(array.size() != 0)
	{
		H.insert(array[0]);
		array.erase(array.begin());
	}
}

void showResult()
{
	//输出合并结果
	cout<<"输出合并结果"<<endl;
	for(int i = 1; i <= mergeResult[0];i++)
		cout<<mergeResult[i]<<' ';
	cout<<endl;
}

void recordMergeResult(int data)
{
	mergeResult[++mergeResult[0]] = data;
}
代码参考: http://blog.csdn.net/mishifangxiangdefeng/article/details/7668486


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值