`
runfeel
  • 浏览: 908079 次
文章分类
社区版块
存档分类
最新评论

数据结构:胜者树与败者树

 
阅读更多

已移到:http://www.wypblog.com/archives/93

假设有k个称为顺串的有序序列,我们希望将他们归并到一个单独的有序序列中。每一个顺串包含一些记录,并且这些记录按照键值的大小,以非递减的顺序排列。令n为k个顺串中的所有记录的总数。并归的任务可以通过反复输出k个顺串中键值最小的记录来完成。键值最小的记录的选择有k种可能,它可能是任意有一个顺串中的第1个记录。并归k个顺串的最直接的办法就是进行k-1次比较确定下一个输出的记录。对k>2,我们可以通过使用选择数这种数据结构来降低寻找下一个最小元素所需要进行的比较次数。有两个种选择树:胜利树和失败树。

胜者树与败者树是完全二叉树。就像是参加比赛一样,每个选手有不同的实力,两个选手PK,实力决定胜负,晋级下一轮,经过几轮之后,就能得到冠军。不同的是,胜者树的中间结点记录的是胜者的标号;而败者树的中间结点记录的败者的标号。胜者树与败者树可以在log(n)的时间内找到最值。任何一个叶子结点的值改变后,利用中间结点的信息,还是能够快速地找到最值。在k路归并排序中经常用到。

一、胜者树

胜者树的一个优点是,如果一个选手的值改变了,可以很容易地修改这棵胜者树。只需要沿着从该结点到根结点的路径修改这棵二叉树,而不必改变其他比赛的结果。下面是选择一个最小的数字为最胜利者(见图1所示),第一次把各个数组里面的第一个元素都放进去,这是根据胜利树的规则两两比较,得到最小的值,第一次弄完之后,就得出1数字是胜利的,也就是1是最小的。在下一次输出第二小的数字时候,只需要把1所在的数组里面的元素加进去,然后从叶子节点到根节点一直比较得出第二小的值,这样就减少了很多次无用的比较(见图2所示)。

图 一 图二

问题:有20个有序数组,每个数组有500个uint变量,降序排序。要求从这10000个元素中选出最大的500个。

程序:

#include <iostream>
#include <vector>
#include <cmath>
#include <ctime>
#include <algorithm>

/**
*	
*	Author: w397090770
*	Data  : 2012.10.15
*	Email : wyphao.2007@163.com
*	转载请注明出处,谢谢。 
*       
*/ 
#define N 10
#define INF (1 << 31) - 1
using namespace std;

typedef struct Node{
	int which;	//记录是哪个子数组 
	int index;	//记录是上个标记数组的第几个元素了 
	int data;	//记录数组的元素 
}Node;

int com(const void *a, const void *b){
	if(*(int *)a > *(int *)b){
		return 1;
	}else if(*(int *)a < *(int *)b){
		return -1;
	}
	
	return 0;
}

void adjustTreeForFirst(Node *tempArray, int len){
	int i = len / 2;
	int j = 0;
	while(i > 1){
		for(j = i; j < 2 * i - 1; j += 2){
			if(tempArray[j].data > tempArray[j + 1].data){
				tempArray[j / 2] = tempArray[j + 1];
			}else{
				tempArray[j / 2] = tempArray[j];
			}
		}
		i /= 2;
	}
}

//col 是列
//row 是行
//len 是选择出前多少个元素 
void winTree(int **a, int row, int col, int len){
	int *result = (int *)malloc(len * sizeof(int));
	Node tempArray[row * 2];
	int index = 0;
	int i = 0, j = 0;
	memset(tempArray, 0, sizeof(struct Node) * 2 * row);
	
	for(i = 0; i < row; i++){
		tempArray[row + i].data = a[i][0];
		tempArray[row + i].which = i;
		tempArray[row + i].index = 0;
	}
	
	for(i = 0 ; i < len; i++){
		adjustTreeForFirst(tempArray, 2 * row);//为了代码减少代码量,我把每一次调用都调整整个树,其实是不必要的,有兴趣的用户可以自己写写
		result[i] = tempArray[1].data;
		if(tempArray[1].index + 1 < col){
			tempArray[row + tempArray[1].which].data = a[tempArray[1].which][tempArray[1].index + 1];
			tempArray[row + tempArray[1].which].index = tempArray[1].index + 1;
			tempArray[row + tempArray[1].which].which = tempArray[1].which;
		}else{//如果某个数组里面的数据处理完了,就把那个节点赋值为无穷大 
			tempArray[row + tempArray[1].which].data = INF;
			//tempArray[row + tempArray[1].which].index = tempArray[1].index + 1;
			//tempArray[row + tempArray[1].which].which = tempArray[1].which;
		}		
	}
	
	for(i = 0; i < len; i++){
		cout << result[i] << endl;
	} 
    free(result);
}

int main(){
	/*int a[N - 2][N] = {
		3, 4, 5, 6, 10, 11, 12, 13, 20, 21,
	 	1, 2, 7, 8, 9, 30, 31, 32, 33, 34,
   		14, 15, 16, 17, 18, 19, 22, 23, 24, 25,
   		26, 27, 28, 29, 35, 36, 37, 38, 39, 40,
   		50, 51, 52, 54, 55, 65, 66, 67, 68, 69,
   		53, 56, 57, 58, 59, 60, 61, 62, 63, 64,
   		41, 42, 43, 44, 45, 46, 47, 48, 49, 2222,
   		1, 2, 2, 4, 5, 6, 12, 13, 20, 21
	};*/
	const int size = 500;
	const int del = 20;
	
	int *a[del];
	int i = 0, j = 0;
	//分配内存空间 
 	for(i = 0; i < del; i++){
 		a[i] = (int *)malloc(size * sizeof(int));	
 	}
 	
 	//初始化数组 
	srand( time(NULL) ); 
	for(i = 0; i < size; i++){
		for(j = 0; j < del; j++){
			a[j][i] = rand();
		}	
	}
	
	//排序 
	for(i = 0; i < del; i++){
		qsort(a[i], size, sizeof(int), com);
	}
	
	//利用胜利树进行处理 
	winTree(a, del, size, size);
	return 0;
}

二、败者树

败者树是胜者树的一种变体。在败者树中,用父结点记录其左右子结点进行比赛的败者,而让胜者参加下一轮的比赛。败者树的根结点记录的是败者,需要加一个结点来记录整个比赛的胜利者。采用败者树可以简化重构的过程。



转载请注明:http://blog.csdn.net/w397090770/article/details/8074831

分享到:
评论

相关推荐

    HP-Socket编译-Linux

    HP-Socket编译-Linux

    JavaScript_生活在Discord上的开源社区列表.zip

    JavaScript

    JavaScript_MultiOn API.zip

    JavaScript

    JavaScript_简单和完整的React DOM测试工具,鼓励良好的测试实践.zip

    JavaScript

    JavaScript_成为一个Nodejs开发者.zip

    JavaScript

    node-v14.5.0-headers.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    android手机应用源码带文字的ProgressBar Demo源码.rar

    android手机应用源码带文字的ProgressBar Demo源码.rar

    JavaScript_基于Electron和Vuejs的全新跨平台Apple Music体验,从头开始编写,并考虑到性能.zip

    JavaScript

    海信LED32EC290N(0000)BOM1通用LED32K220(0000)BOM1生产用软件数据U盘升级文件.zip

    机型:LED32K220 BOM:1 编号:LED32K220(0000)_C010 方案:MST628 版本号:LED32K220_V0000.30.20A.G0809 U盘升级说明: 就是将下载的程序解压到U盘根目录下,即根目录下有个TargetHis文件夹。 U盘采用FAT32格式,将U盘插在上面那个USB口上(若不行则更换另一个usb口)。 升级方式1: 电视开机后,插入U盘,会弹出提示是否升级,确定即可。 升级方式2: 交流开机瞬间不停的按下、松开home键,然后进入自动升级界面。 新贴片的程序第一次升级可能会在升级进度21%的界面卡住,交流断电再上电即可,继续升级。升级完成后自动启动完成即可(首次开机可能要3分钟)。 升级方式3: 插入U盘,电视上电时在串口打印界面按回车键使开机停止在boot界面,键入cu命令,然后回车即可。

    Python笔记.zip

    Python笔记.zip

    人工智能和智能制造的交汇点

    参考行业研究

    Java输出后序遍历二叉树的代码

    附件是Java输出后序遍历二叉树的代码,后序遍历的顺序是:首先递归地后序遍历左子树,然后递归地后序遍历右子树,最后访问根节点。 TreeNode 类定义了二叉树的节点,BinaryTree 类包含一个 root 属性和 postOrderTraversal 方法。postOrderTraversal 方法递归地遍历二叉树,首先遍历左子树,然后遍历右子树,最后访问当前节点。

    西门子840 x130口设置

    可以通过这个资料 完成西门子840Dsl的x130口采集

    蛋白质耐热温度分类及预测重要数据表.zip

    蛋白质耐热温度分类及预测重要数据表蛋白质是生物体中普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物中的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动中发挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。

    一个简单的HTML5和CSS代码示例,用于创建一个动态的爱心形状,并在网页上展示一个类似520表白的消息 这个示例使用了CSS的

    520表白html5爱心代码 一个简单的HTML5和CSS代码示例,用于创建一个动态的爱心形状,并在网页上展示一个类似520表白的消息。这个示例使用了CSS的动画效果和HTML的结构。

    node-v16.19.0-headers.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    node-v15.3.0-headers.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    海信电视刷机数据 LED32K370(0000)BOM1升级VIDAA2软件数据 务必确认机编一致 强制刷机 整机USB升级程序

    MT5505机芯升级方法: 1、下载数据,压缩包解压,升级软件文件夹名字为Hisense_5505,文件夹下包含“机型名.pkg”以及version.txt 2、将文件夹Hisense_5505,整个文件夹拷贝至U盘根目录下 3、电视关机,插入U盘(USB3或者靠近高频头的USB口),重新启动电视机,电视机自动检测到升级软件之后并进行升级 4、在升级过程中屏幕有相关提示,升级完成后能自动开机。(建议是升级完成之后拔下U盘设备以免下次开机进行重复性升级) 注意: 1、(U盘要求使用FAT32格式,建议4G-8G的品牌U盘,刷机成功率会高) 2、升级到结束,大约需要8-30分钟,中途绝对不能断电 3、升级重启第一次进入系统,请等完全正常进入开机桌面之后,才能拨下U盘 4、如无法升级,将Hisense 5505文件夹内“机型名.pkg”的文件重命名为“upgrade.pkg”,此时插上U盘开机,电视就会默认为强制升级模式

    node-v8.9.4-headers.tar.gz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    JavaScript_AI拟声 5秒内克隆您的声音并生成任意语音内容

    JavaScript

Global site tag (gtag.js) - Google Analytics