多路归并排序之败者树

#include<iostream>
#include<iomanip>
#define M  4
using namespace std;

class LoserTree
{
private:
    // 调整K为2的整数次幂
    int round(int k)
    {
        if(k&(k-1)!=0)
        {
            int i=0;
            for(i=31;i>=0;i--)
            {
                if(((1<<i)&k)!=0)
                {
                    cout<<i<<endl;
                    break;
                }
            }
            return 0x1<<(i+1);
        }
        return k;
    }
    void ajust(int s)
    {
        cout<<"调整:"<<s<<endl;
        int sData=_ls[s];
        int t=s/2;
        while(t>=1)
        {
            if(_data[_ls[t]]<_data[sData])
            {
                int tmp=sData;
                sData=_ls[t];
                _ls[t]=tmp;
            }
            t=t/2;
        }
        _ls[0]=sData;
    }
    const int _k;
    int       _n;   // 败者树应留下多少空间存放根节点
    int   *_data;   // 存放数据
    int    *_ls;     // 存放败者树的结构
public:
    const int MINKEY;
    const int MAXKEY;
    void print(int *ls,int n)
    {
        cout<<"|||||||||||||||"<<endl;
        for(int i=0;i<n;i++)
            cout<<setw(5)<<i;
        cout<<endl;
        for(int i=0;i<n;i++)
        {
            cout<<setw(5)<<ls[i];
        }
        cout<<endl;
    }

    int  init(int input[],int m) // 初始化败者树,并返回胜者的下标
    {
        if(m!=_k)
        {
            return -1;
        }
        int i;
        for(i=0;i<_n+1;i++)
        {
            _ls[i]=_k;       // 映射到最小值
        }
        for(i=0;i<_k;i++)
        {
            _data[i]=input[i];
        }
        for(i=_n+1;i<_n+_k+1;i++)
        {

            _ls[i]=i-(_n+1);
        }
        for(i=_n+_k;i>=_n+1;i--)
        {
            ajust(i);
            print(_ls,_n+_k+1);
        }
        return _ls[0];
    }
    int next(int index,int value)
    {
        _data[index]=value;
         ajust(index);
         return _ls[0];
    }
    LoserTree(int k):_k(k),MINKEY(1<<31),MAXKEY(~(1<<31))
    {
         _n=round(_k)-1;  // 计算前面应当预留多少空间
        _data=new int[_k+1];
        _ls=new int [_n+_k+1];
        _ls[_k]=MINKEY;
    }
    ~LoserTree()
    {
        delete []_data;
        delete []_ls;
    }
};

int main()
{
    int input[M],i;
    for(i=0;i<M;i++)
    {
        input[i]=rand()%20;
        cout<<input[i]<<"  ";
    }
    cout<<endl;
    LoserTree lt(M);
    int index=lt.init(input,M); // 初始化败者树,并放入到数据缓冲器,此时会返回一个胜者的下标,根据下标可以调用next函数输入下一个数据
    cout<<"min index:"<<index<<"min:"<<input[index]<<endl;
    system("pause");
}
时间: 2024-10-03 22:52:17

多路归并排序之败者树的相关文章

外排序 &amp; 败者树 &amp; 多路归并-学习

来来来,根据这篇文章,学一下败者树吧: http://blog.csdn.net/whz_zb/article/details/7425152 一.胜者树 胜者树的一个优点是,如果一个选手的值改变了,可以很容易地修改这棵胜者树.只需要沿着从该结点到根结点的路径修改这棵二叉树,而不必改变其他比赛的结果. 二.败者树 败者树是胜者树的一种变体.在败者树中,用父结点记录其左右子结点进行比赛的败者,而让胜者参加下一轮的比赛.败者树的根结点记录的是败者,需要加一个结点来记录整个比赛的胜利者.采用败者树可以

外排序 &nbsp; 败者树 &nbsp; 多路归并

一.外排序 排序按数据存在的位置不同分为内排序和外排序 内排序:数据都在内存中,选择合适的排序方法对数据进行排序,比如选择排序.快速排序等 衡量内排序的效率是数据的比较次数 外排序:数据无法全部加载到内存中,只能不断在外部存储器和内存中进行交换完成排序 衡量外排序的效率是内存与外村的交换次数 外排序是针对大文件的数据排序,内存中无法加载这个大文件,把这个文件分为k个小文件,分别排序后合并 http://blog.csdn.net/msdnwolaile/article/details/52084

C++ 模板实现败者树,进行多路归并

项目需要实现一个败者树,今天研究了一下,附上实现代码. 几点说明: 1. 败者树思想及实现参考这里:http://www.cnblogs.com/benjamin-t/p/3325401.html 2. 多路归并中的“多路”的容器使用的是C语言数组 + 数组长度的实现(即 const ContainerType* ways, size_t num ),而没有用STL中的容器,这是因为项目需要如此,日后再改成STL容器: 3. _losers 存储下标,用的是 int 类型,还需要修改.程序中其他

外部排序&amp;多路归并排序

外部排序: 一.定义问题 外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序 整个文件的目的.外部排序最常用的算法是多路归并排序,即将原文件分解成多个能够一次性装入内存的部分,分别把每一部分调入内存完成排序.然后,对已经排 序的子文件进行多路归并排序. 二.处理过程 (1)按可用内存的大小,把外存上含有n个记录的文件分成若干个长度为L的子文件,把这些子文件依次读入内存,并利用有效的内部排序方法对它们进行

堆排序、胜者树、败者树,孰优孰劣?

在顺序存储结构中,堆排序是一种非常不错的高级选择排序算法,普通情况和最差情况下都可以将时间复杂度控制在O(n * logn). 堆排序可以用在顺序存储结构,是因为完全二叉树的一种独特性质.而这里还要先提一下满二叉树. 啥叫满二叉树?满二叉树是这样一种二叉树,它的每一层都是"满"的,设根部为第0层,则每一层都有2^n个节点.所有节点的度数要么是2,要么是0(叶子). 那完全二叉树呢?我们首先做出如下规定,即对二叉树中的节点,按从根部到叶子.每层从左到右递增的编号:如果某棵树,其所有节点的

排序(二)键索引、桶排序、位示图、败者树等

排序(二) 以上排序算法都有一个性质:在排序的最终结果中,各元素的次序依赖于它们之间的比较.我们把这类排序算法称为比较排序. 任何比较排序的时间复杂度的下界是nlgn. 以下排序算法是用运算而不是比较来确定排序顺序的.因此下界nlgn对它们是不适用的. 键索引计数法(计数排序) 计数排序假设n个输入元素中的每一个都是在0到k区间的一个整数,其中k为某个整数. 思想:对每一个输入元素x,确定小于x的元素个数.利用这一信息,就可以直接把x放到它在输出数组中的位置了. 例如: 学生被分为若干组,标号为

外部排序---置换选择+败者树

当需要对一个大文件进行排序时,计算机内存可能不够一次性装入所有数据,解决办法是归并.归并的大概做法是将大文件分为若干段,依次读入内存进行排序,排序后再重新写入硬盘.这些排好序的片段成为顺串.然后对这些顺串进行逐躺归并,使归并段逐渐由小变大,最终使整个文件有序.要使用归并就得考虑两个问题,一个是如何生成顺串,一个是如何对顺串进行归并. 置换选择算法 先考虑如何生成顺串.我们知道,减少顺串的数量可以降低归并的次数,而在文件大小固定的情况下,要减少顺串的数量,就要增大单个顺串的长度.如果使用内部排序生

(转)败者树 和 胜者树---数组实现

转自:http://blog.csdn.net/sqx2011/article/details/8241734 胜者树和败者树都是完全二叉树,是树形选择排序的一种变型.每个叶子结点相当于一个选手,每个中间结点相当于一场比赛,每一层相当于一轮比赛. 不同的是,胜者树的中间结点记录的是胜者的标号:而败者树的中间结点记录的败者的标号. 胜者树与败者树可以在log(n)的时间内找到最值.任何一个叶子结点的值改变后,利用中间结点的信息,还是能够快速地找到最值.在k路归并排序中经常用到. 一.胜者树 胜者树

一篇能够加深对胜者树和败者树理解的文章

概念介绍 胜者树和败者树都是完全二叉树,是树形选择排序的一种变型.每个叶子结点相当于一个选手,每个中间结点相当于一场比赛,每一层相当于一轮比赛. 不同的是,胜者树的中间结点记录的是胜者的标号:而败者树的中间结点记录的败者的标号. 胜者树与败者树可以在log(n)的时间内找到最值.任何一个叶子结点的值改变后,利用中间结点的信息,还是能够快速地找到最值.在k路归并排序中经常用到. 胜者树 胜者树的一个优点是,如果一个选手的值改变了,可以很容易地修改这棵胜者树.只需要沿着从该结点到根结点的路径修改这棵