zoukankan      html  css  js  c++  java
  • winner tree 胜者树

    在树形选择排序中,利用锦标赛思想建立的树称为胜者树。

    1、每个非终端节点存储的是左右孩子节点中的优胜者

    2、通过减少比较次数,提高效率

    3、胜者树就是一颗特殊的线段树

    一、构建树

    Procedure buildmint;  复杂度 O(n)
    var i,j,k:longint;
    begin
      i:=N; j:=N+n-1; { 其中 N 为大于等于 n 的最小 2 次方数 }
      while i>1 do
      begin
        k:=i;
        while k<j do
        begin
          f[k div 2]:=min(f[k],f[k+1]);
          k:=k+2;
        end;
        if j and 1=0 then f[j div 2]:=f[j];
        i:=i div 2; j:=j div 2;
      end;
    end;

    二、查询

    核心思想:自下向上,奇偶缩进。

    Function findmin(x,y:longint):longint;  复杂度 O(logn)
    var i,j,k,r:longint;
    begin
      i:=x+N-1; j:=y+N-1; r:=i;
      while i<=j do
      begin
        if (f[r]>f[i]) then r:=i;
        if (f[r]>f[j]) then r:=j;
        if (i and 1=1) then inc(i);
        if (j and 1=0) then dec(j);
        i:=i shr 1; j:=j shr 1;
      end;  exit(f[r]);
      while r<N do
      if (f[r]=f[r*2]) then r:=r*2 else r:=r*2+1; 
      exit(r-N+1);
    end; 

    三、更新

    核心思想:自下而上,更新父节点。

    胜者树不擅长更新,因为,某个结点更新的时候,它还需要跟兄弟结点比较。更新频繁的情况,用败者树

    四、败者树

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

    典型应用:多路归并排序,可以减少比较次数


    五、代码实现胜者树

    poj2328 http://poj.org/problem?id=2823

    Description

    An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves rightwards by one position. Following is an example: 
    The array is [1 3 -1 -3 5 3 6 7], and k is 3.
    Window positionMinimum valueMaximum value
    [1  3  -1] -3  5  3  6  7  -1 3
     1 [3  -1  -3] 5  3  6  7  -3 3
     1  3 [-1  -3  5] 3  6  7  -3 5
     1  3  -1 [-3  5  3] 6  7  -3 5
     1  3  -1  -3 [5  3  6] 7  3 6
     1  3  -1  -3  5 [3  6  7] 3 7

    Your task is to determine the maximum and minimum values in the sliding window at each position. 

    Input

    The input consists of two lines. The first line contains two integers n and k which are the lengths of the array and the sliding window. There are n integers in the second line. 

    Output

    There are two lines in the output. The first line gives the minimum values in the window at each position, from left to right, respectively. The second line gives the maximum values. 

    Sample Input

    8 3
    1 3 -1 -3 5 3 6 7
    

    Sample Output

    -1 -3 -3 -3 3 3
    3 3 5 5 6 7
    

    Source

    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    const int MX = 1000011;
    
    int n, k;
    int a[MX], minRes[MX], maxRes[MX];
    int treeMin[5*MX], treeMax[5*MX];
    int N;
    
    //构建一颗winner tree,tree用数组存储,根结点是数组的第二个结点,即A[1]
    //叶子结点是原始数组。树的最左结点的下标是2的指数
    void build() {
        int i = N, j = N+n-1;
        while (i > 1) {
            int t = i;
            while (t < j) {
                treeMin[t/2] = min(treeMin[t], treeMin[t+1]);
                treeMax[t/2] = max(treeMax[t], treeMax[t+1]);
                t += 2;
            }
            if ((j&1) == 0) {//下标j是偶数,说明这个结点是落单的
                treeMin[j/2] = treeMin[j];
                treeMax[j/2] = treeMax[j];
            }
            i = i>>1;
            j = j>>1;
        }
    }
    
    int query(int x, int y) {
        int i=x+N, j=y+N, t = i;
        while (i <= j) {
            if (treeMin[t] > treeMin[i]) t = i;
            if (treeMin[t] > treeMin[j]) t = j;
            if ((i&1) == 1) i++;
            if ((j&1) == 0) j--;
            i = i>>1;
            j = j>>1;
        }
        //return treeMin[t];
        while (t < N) {
            if (treeMin[t] == treeMin[t*2]) t = t*2;
            else t = t*2+1;
        }
        return treeMin[t];
        //return t - N;
    }
    
    void work() {
        for (int i=0; i<n-k+1; i++) {
            int x=N+i, y=x+k-1, t=x, r=x;
            while (x<=y) {
                if (treeMin[t] > treeMin[x]) t = x;
                if (treeMin[t] > treeMin[y]) t = y;
                if (treeMax[r] < treeMax[x]) r = x;
                if (treeMax[r] < treeMax[y]) r = y;
                if ((x&1) == 1) x++;
                if ((y&1) == 0) y--;
                x = x>>1;
                y = y>>1;
            }
            minRes[i] = treeMin[t];
            maxRes[i] = treeMax[r];
        }
    }
    
    void printRes() {
        for (int i=0; i<n-k+1; i++) {
            if (i!=0) cout<<" ";
            cout<<minRes[i];
        }
        cout<<endl;
        for (int i=0; i<n-k+1; i++) {
            if (i!=0) cout<<" ";
            cout<< maxRes[i];
        }
        cout<<endl;
    }
    
    int calN(int x) {
        int i = 1;
        while (i < x) {
            i = i<<1;
        }
        return i;
    }
    
    void printTree() {
        cout << "min winner tree:" << endl;
        for (int i=1; i< n+N; i++) {
            cout << treeMin[i] << " ";
        }
        cout << endl << "max winner tree:" << endl;
        for (int i=1; i<n + N; i++) {
            cout << treeMax[i] << " ";
        }
        cout << endl;
    }
    
    int main()
    {
        cin >> n >> k;
        N = calN(n);
        for (int i=0; i<n; i++) {
            cin >> a[i];
            treeMax[N+i] = treeMin[N+i] = a[i];
        }
    
        build();
    
        //printTree();
    
        work();
        printRes();
    
        //cout<<"query:"<< query(0, 2)<<endl;
    
        //cout << "Hello world!" << endl;
        return 0;
    }
  • 相关阅读:
    log4j配置只打印指定jar或包的DEBUG信息
    实现cookie跨域访问
    使用轻量级Spring @Scheduled注解执行定时任务
    Docker容器里时间与宿主机不同步
    Wildfly8 更改response header中的Server参数
    JBoss部署项目log4j配置会造成死锁问题,浏览器访问一直pending状态
    json-lib-2.4.jar Bug,json字符串中value为"[value]"结构时,解析为数组,不会解析成字符串
    【转载】分享下多年积累的对JAVA程序员成长之路的总结
    web项目嵌入Jetty运行的两种方式(Jetty插件和自制Jetty服务器)
    rabbitmq+haproxy+keepalived实现高可用集群搭建
  • 原文地址:https://www.cnblogs.com/549294286/p/3780568.html
Copyright © 2011-2022 走看看