K路归并排序(k-way merge sort) 代码(C++)
本文地址: http://blog.csdn.net/caroline_wendy
K路归并排序作为经典的外部排序算法, 是程序员必须要掌握的.
知识概念参考: <数据结构>
主要思想: 在k个已排序的文件中, 选择第一个值, 采用败者树, 更新二叉树结构, 最终选择最优值.
代码仅供参考, 如最小值用(-1)代替, 最大值用(100)代替.
/*
* main.cpp
*
* Created on: 2014年9月11日
* Author: Spike
*/
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
class KWayMergeSort
{
public:
KWayMergeSort(vector<ifstream*>& vif) :
m_vifs(vif), m_ofs("out.txt") { }
void calculate() {
/* 分别从k个输入归并段读人该段当前第一个记录的关键字到外结点 */
for(int i = 0;i < k;++i) {
input(i, b[i]);
}
createLoserTree();
while(b[ls[0]] != MAXKEY){
/* q指示当前最小关键字所在归并段 */
int q = ls[0];
/* 将编号为q的归并段中当前(关键字为b[q].key)的记录写至输出归并段 */
cout << b[q] << " ";
m_ofs << b[q] << " ";
/* 从编号为q的输入归并段中读人下一个记录的关键字 */
input(q, b[q]);
/* 调整败者树,选择新的最小关键字 */
adjust(q);
}
/* 将含最大关键字MAXKEY的记录写至输出归并段 */
cout << endl;
m_ofs << endl;
}
private:
void input (int i, int& b) {
if ((*m_vifs[i]).good()) {
(*(m_vifs[i])) >> b;
}
}
/**
* 已知b[0]到b[k-1]为完全二叉树ls的叶子结点,存有k个关键字,沿从叶子
* 到根的k条路径将ls调整成为败者树。
*/
void createLoserTree() {
b[k] = MINKEY;
/* 设置ls中“败者”的初值 */
for(int i = 0; i < k; ++i){
ls[i] = k;
}
/* 依次从b[k-1],b[k-2],…,b[0]出发调整败者 */
for(int i = k - 1; i >= 0; --i){
adjust(i);
}
}
void adjust(int i) {
/* ls[t]是b[s]的双亲结点 */
int t = (i + k) / 2;
while (t > 0) {
/* s指示新的胜者 */
if (b[i] > b[ls[t]]) {
int tmp = i;
i = ls[t];
ls[t] = tmp;
}
t = t / 2;
}
ls[0] = i;
}
private:
static const int k = 4;
static const int MINKEY = -1;
static const int MAXKEY = 100;
int b[k+1]; //败者树的叶子节点
int ls[k]; //败者树的其余节点
vector<ifstream*> m_vifs;
ofstream m_ofs;
};
int main(void) {
vector<ifstream*> vif;
ifstream* ifs0 = new ifstream("f0.txt");
ifstream* ifs1 = new ifstream("f1.txt");
ifstream* ifs2 = new ifstream("f2.txt");
ifstream* ifs3 = new ifstream("f3.txt");
vif.push_back(ifs0);
vif.push_back(ifs1);
vif.push_back(ifs2);
vif.push_back(ifs3);
KWayMergeSort k(vif);
k.calculate();
delete ifs0;
delete ifs1;
delete ifs2;
delete ifs3;
return 0;
}
待排序文件, 最后一个是标记, 用于停止更新败者树:
f0: 5 16 49 52 78 100
f1: 7 12 25 84 91 100
f2: 29 38 57 66 71 100
f3: 9 22 47 48 59 100
输出:
5 7 9 12 16 22 25 29 38 47 48 49 52 57 59 66 71 78 84 91