外排序   败者树   多路归并
admin
2023-08-01 08:23:12
0

一、外排序

排序按数据存在的位置不同分为内排序和外排序

内排序:数据都在内存中,选择合适的排序方法对数据进行排序,比如选择排序、快速排序等

              衡量内排序的效率是数据的比较次数

外排序:数据无法全部加载到内存中,只能不断在外部存储器和内存中进行交换完成排序

              衡量外排序的效率是内存与外村的交换次数


外排序是针对大文件的数据排序,内存中无法加载这个大文件,把这个文件分为k个小文件,分别排序后合并


http://blog.csdn.net/msdnwolaile/article/details/52084983


二、败者树

胜者树和败者树都是完全二叉树,每个叶子节点相当于一个选手,每个中间节点相当于一场比赛,每一层相当于一轮比赛


胜者树的中间节点记录的是胜者的序号,败者树的中间节点记录的是败者的序号

1、胜者树

优点是:如果一个选手的数值改变,那么只需沿着一条路径(这个节点到根节点的路径)即可修正这颗胜者树


2、败者树

用中间节点记录败者,用另一个辅助节点记录胜者来进行下一场比赛

下面举一个栗子说明:


外排序    败者树    多路归并



三、K路归并排序

我们把败者树分为两部分:

第一部分是b[],用来保存K路数组的首元素,叶节点存放在此处

第二部分式ls[],用来保存败者数组的下标,b[0]是最终的胜者(即所求的数),败者节点存放在此处

1、创建败者树

败者树

外排序    败者树    多路归并


调整败者树

将新补充的节点与其父节点进行比较,败者留在该父节点上,胜者继续向上直至根节点

外排序    败者树    多路归并


http://blog.sina.com.cn/s/blog_13a5c10be0102v1fb.html



#include 
using namespace std;

const int MINKEY = 0;

//完全二叉树的叶子节点个数比度为2的节点个数多1
void Adjust(int* &b,int* &ls,int i,int k)
{
	//控制ls[]的下标
	int t = (i + k) / 2;//第一个非叶子结点的下标、第二个。。。
	//控制b[]的下标
	int s = i;
	for (; t > 0; t /= 2){
		if (b[ls[t]]= 0; --i){
		Adjust(b, ls, i, k);
		for (int i = 0; i < k; ++i)
			cout << ls[i] << " ";
		cout << endl;
	}
}


int main()
{
	/*int arr1[] = { 10, 14, 26, 50 };
	int arr2[] = { 9, 22, 38 };
	int arr3[] = { 20, 24, 30 };
	int arr4[] = { 6, 15, 25 };
	int arr5[] = { 12, 11, 18 };
	int arr6[] = { 90, 92, 97 };
	int* arr[6] = { arr1, arr2, arr3, arr4, arr5, arr6 };
	createLoserTree(arr, 6);*/
	int arr1[] = { 6, 15, 25 };
	int arr2[] = { 12, 37, 48 };
	int arr3[] = { 10, 15, 16 };
	int arr4[] = { 9, 18, 20 };
	int arr5[] = { 10, 11, 40 };
	int* arr[] = { arr3, arr4, arr5, arr1, arr2 };
	createLoserTree(arr, 5);

	system("pause");
}

/*//自己分析的过程。。。(较混乱,可不看)
//createLoserTree()
for (int i = k - 1; k >= 0; --k){
	Adjust(i);
}
//Adjust(i)
int t = (i + k) / 2;//第一个非叶子结点的下标

int s = i;
for (; t >= 0; t /= 2){
	if (b[ls[t]]

 

2、K路归并排序

void kMerge(int* arr[], int* arrayElementsCount, int& k, int* &ls, int* &b, int& mostMinCount)
{
    int* index = new int[k];
    for (int i = 0; i < k; ++i)
        index[i] = 0;
    for (int i = 0; i < mostMinCount; ++i){
        int s = ls[0];
        cout << b[s] << " ";
        ++index[s];
        if (index[s] < arrayElementsCount[s])
            arr[s][0] = arr[s][index[s]];
        else
            arr[s][0] = MAXKEY;
        b[s] = arr[s][0];
        Adjust(k, ls, b, s);
    }
    delete[] index;
}


3、完整代码

#include 
using namespace std;

const int MINKEY = 0;//假设给定数组中所有数都大于0
const int MAXKEY = 200;//假设给定数组中所有数都小于200

//完全二叉树的叶子节点个数比度为2的节点个数多1
void Adjust(int &k, int* &ls, int* &b, int i)
{
    //控制ls[]的下标
    int t = (i + k) / 2;//第一个非叶子结点的下标、第二个。。。
    //控制b[]的下标
    int s = i;
    for (; t > 0; t /= 2){
        if (b[ls[t]]= 0; --i){
        Adjust(k, ls, b, i);
        for (int i = 0; i < k; ++i)
            cout << ls[i] << " ";
        cout << endl;
    }
}

void kMerge(int* arr[], int* arrayElementsCount, int& k, int* &ls, int* &b, int& mostMinCount)
{
    int* index = new int[k];
    for (int i = 0; i < k; ++i)
        index[i] = 0;
    for (int i = 0; i < mostMinCount; ++i){
        int s = ls[0];
        cout << b[s] << " ";
        ++index[s];
        if (index[s] < arrayElementsCount[s])
            arr[s][0] = arr[s][index[s]];
        else
            arr[s][0] = MAXKEY;
        b[s] = arr[s][0];
        Adjust(k, ls, b, s);
    }
    delete[] index;
}

int main()
{
    int arr0[] = { 6, 15, 25 };
    int arr1[] = { 12, 37, 48, 50 };
    int arr2[] = { 10, 15, 16 };
    int arr3[] = { 9, 18, 20 };
    int arr4[] = { 10, 11, 40 };
    //6,9,10,10,11,12,15,15,16,18,20,25,37,40,48,50
    int* arr[] = { arr2, arr3, arr4, arr0, arr1 };
    int* arrayElementsCount = new int[5];
    arrayElementsCount[0] = sizeof(arr2) / sizeof(arr2[0]);
    arrayElementsCount[1] = sizeof(arr3) / sizeof(arr3[0]);
    arrayElementsCount[2] = sizeof(arr4) / sizeof(arr4[0]);
    arrayElementsCount[3] = sizeof(arr0) / sizeof(arr0[0]);
    arrayElementsCount[4] = sizeof(arr1) / sizeof(arr1[0]);
    int k = sizeof(arr) / sizeof(arr[0]);
    //记录每个数组的首元素
    int* b = new int[k + 1];
    //记录败者的下标
    int* ls = new int[k];
    createLoserTree(arr, k,ls,b);
    int mostMinCount = 13;
    kMerge(arr, arrayElementsCount, k, ls, b, mostMinCount);
    delete[] b;
    delete[] ls;
    delete[] arrayElementsCount;

    system("pause");
}



后记:

堆结构:待处理的数据在树节点中(非叶子和叶子)

败者树结构:待处理的数据都只在叶子节点

堆结构适用于插入式无规则的,选出最值

败者树结构适用于多路序列插入,选出最值

相关内容

热门资讯

凤凰直击广西水灾救援现场:无人... 此前因强降雨而出现溃口的广西横州六蓝水库,7月8日总体情况保持稳定。凤凰卫视记者在受灾区域采访了一些...
中方发布“批判指南”,逐一驳斥... 【环球时报报道 记者 樊巍 胡雨薇】自然资源部海洋发展战略研究所8日发布《菲律宾南海领土主张的历史法...
孔灯怎么拆卸安装 拆卸和安装孔灯需要注意安全,以下是一般的步骤:1. 关闭电源:在进行任何电气工作之前,请确保关闭电源...
扬子空调故障码03 扬子空调故障码03 是室内外通讯故障。当连续一段时间室内机没有接收到室外机发送的正确信号,或室外机没...
格力空调故障码e6怎么维修 问题:格力空调故障码e6怎么维修回答:1、可以看一下关掉电源以后重新通电,如果E6的代码消失,就说明...
上海警方通报男童被2只狗咬住拖... 2026年7月7日8时50分,育才路一居民小区内发生一起犬只伤人案件。经查,马某(男,49岁)饲养的...
奥克斯空调故障代码,奥克斯空调...   奥克斯空调故障代码—故障代码;  不工作 E2故障:Q106、Q107、Q108、Q109、D1...
美的空调显示p10是什么故障 表示系统低压保护。出现此类情况主要有以下原因:1、连接管存在变形,造成节流的现象。2、由于P10表示...
四川宜宾发生4.8级地震,震源... 中国地震台网正式测定:07月09日07时44分在四川宜宾市高县(北纬28.51度,东经104.68度...
特朗普突然换飞机引猜测,伊朗官... 北约峰会7月8日结束后,美国总统特朗普回国时换回了旧的“空军一号”专机。在美伊再度大打出手之际,特朗...