k-路合并操作问题
假定有k个有序数组,每个数组中含有n个元素,您的任务是将它们合并为单独的一个有序数组,该数组共有kn个元素。设计和实现一个有效的分治算法解决k-路合并操作问题。
// Divide-exam2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <random>
#include <algorithm>
#include <vector>
using namespace std;
/**********k路合并操作问题***********/
//相同长度的数组合并代价最小,两两合并
vector<int> Merge(vector<int> r1, vector<int> r2, int len1,int len2)
{
int i = 0;
int j = 0;
int k = 0;
vector<int> r(len1+len2);
while (i < len1&&j < len2)
if (r1[i] <= r2[j])
r[k++] = r1[i++];
else
r[k++] = r2[j++];
if (i < len1-1)
while (i < len1)
r[k++] = r1[i++];
else
while (j < len2)
r[k++] = r2[j++];
return r;
}
//C++ 标准库使用比如vector::push_back 等这类函数时,会对参数的对象进行复制,连数据也会复制.这就会造成对象内存的额外创建,
//本来原意是想把参数push_back进去就行了.C++11 提供了std::move 函数来把左值转换为xrvalue,
//而且新版的push_back也支持&&参数的重载版本, 这时候就可以高效率的使用内存了.
vector<int> merge_k(vector<vector<int> >& vec)
{
auto size = vec.size();
if (size == 1)
return move(vec.back());
decltype(size) mid = size / 2;
vector<vector<int> > left_vec;
for (decltype(size) i = 0; i < mid; ++i)
left_vec.push_back(move(vec[i]));
//divide
vector<int> left_merged = merge_k(left_vec);
vector<vector<int> > right_vec;
for (decltype(size) i = mid; i < size; ++i)
right_vec.push_back(move(vec[i]));
//divide
vector<int> right_merged = merge_k(right_vec);
return Merge(left_merged, right_merged,left_merged.size(),right_merged.size());
}
//随机产生vector
void gen_random(vector<vector<int> >& vec)
{
static default_random_engine e;
int k = vec.size();
int n = vec[0].size();
static uniform_int_distribution<int> u(-n * k, n * k);
for (vector<vector<int> >::size_type i = 0; i < vec.size(); ++i)
{
for (vector<int>::size_type j = 0; j < vec[i].size(); ++j)
vec[i][j] = u(e);
sort(vec[i].begin(), vec[i].end());
}
}
/**
void mergeSort(vector<vector<int>> a, int min, int max) { //递归分解自身,直至该列表被分为长度为1
if (min<max) {
int mid = (min + max) / 2;
mergeSort(a, min, mid,n);
mergeSort(a, mid + 1, max,n);
Merge(a,a[min], a[mid],n);
}
}
*/
/***********(<=>)*********/
int i = 0;
int y = 0;
void partition(int r[],int n)
{
y = n - 1;
int temp = r[i]; //把第一个数作为基准pivot
int tmp = 0;
for (int j = 1; j < n; ++j)
{
if (r[j] < temp)
{
tmp = r[j];
r[j] = r[i];
r[i++] = tmp;
}
}
for (int j = n - 1; j >= i; --j)
{
if (temp < r[j])
{
tmp = r[j];
r[j] = r[y];
r[y--] = tmp;
}
}
}
int main()
{
//K路合并问题
int K = 10;
int N = 50;
vector<vector<int> > vec(K,vector<int>(N));
gen_random(vec);
vector<int> merged = merge_k(vec);
cout << boolalpha << is_sorted(merged.begin(), merged.end()); // true
/****
//(<=>)
int a[] = { 4,1,6,2,3,5,4,2,7,6 };
partition(a, 10);
for (int j = 0; j < i; ++j)
cout << a[j] << " "; //1 2 3 2
cout << endl;
for (int j = i; j <= y; ++j)
cout << a[j] << " "; //4 4
cout << endl;
for (int j = y+1; j < 10; ++j)
cout << a[j] << " "; //6 5 7 6
cout << endl;
**/
return 0;
}