您的位置:首页 > 其它

树形排序TreeSelection Sort 竞标赛排序 Tournament Sort

2013-10-23 08:15 211 查看
https://github.com/rugyoga/Tournament-sort/blob/master/java/array/Tournament.java

import java.util.Comparator;
import java.util.Random;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Stack;

class Tournament<T>
{
  Comparator<T> comparator;
  T[] array;
  int[] matches;
  int tourney;

  Tournament( Comparator<T> comparator, T[] v )
  {
    this.array = v;
    this.matches = new int[6*v.length];
    this.comparator = comparator;
    this.tourney = knockout( 0, v.length-1, 3 );
  }

  public T pop()
  {
    T result = array[getPlayer( tourney )];
    tourney = isPlayer( tourney ) ? 0 : rebuild( tourney );
    return result;
  }

  public static <T> void sort( T[] v, Comparator<T> comparator )
  {
    Tournament<T> tourney = new Tournament<T>( comparator, v );
    ArrayList<T> copy = new ArrayList<T>( v.length );
    for (int i = 0; i < v.length; i++)
      copy.add( tourney.pop() );
    copy.toArray( v );
  }
  
  private int getPlayer( int i )
  {
    return i <= 0 ? Math.abs(i) : getWinner( i );
  }
  
  private void setWinner( int root, int winner ) { matches[root] = winner; }
  private void setWinners( int root, int winners ) { matches[root+1] = winners; }
  private void setLosers( int root, int losers ) { matches[root+2] = losers; }
  private int getWinner( int root ) { return matches[root]; }
  private int getWinners( int root ) { return matches[root+1]; }
  private int getLosers( int root ) { return matches[root+2]; }
  private void setMatch( int root, int winner, int winners, int losers )
  {
    matches[root] = winner;
    matches[root+1] = winners;
    matches[root+2] = losers;
  }
  
  private int mkMatch( int top, int bot, int root )
  {
    int top_w = getPlayer( top );
    int bot_w = getPlayer( bot );
    if (comparator.compare( array[top_w], array[bot_w] ) <= 0)
      setMatch( root, top_w, top, bot );
    else
      setMatch( root, bot_w, bot, top );
    return root;
  }
  
  private int mkPlayer( int i ){ return -i; }

  private int knockout( int i, int k, int root )
  {
    if (i == k) return mkPlayer( i );
    int j = (i+k)/2;
    return mkMatch( knockout( i, j, 2*root ), knockout( j+1, k, 2*root+3 ), root );
  }
  
  private boolean isPlayer( int i ) { return i <= 0; }

  public String toString( int root )
  {
    return isPlayer( root ) ?
            "[" + array[-root] + "]" :
            "(" + toString( getLosers( root ) ) +
                " " + array[getWinner( root )] + " " +
                toString( getWinners( root ) ) + ")";
  }

  public int rebuild( int root )
  {
    if (isPlayer( getWinners( root ) ))
      return getLosers( root );
    else
    {
      setWinners( root, rebuild( getWinners( root ) ) );
      if (comparator.compare( array[getPlayer(getLosers( root ))], array[getPlayer(getWinners( root ))] ) < 0)
      {
        setWinner( root, getPlayer( getLosers( root ) ) );
        int temp = getLosers( root );
        setLosers( root, getWinners( root ) );
        setWinners( root, temp );
      }
      else
        setWinner( root, getPlayer( getWinners( root ) ) );
      return root;
    }
  }
    
  static Integer[] randomInts( int n )
  {
    Random r = new Random( 12345678 );
    Integer[] v = new Integer
;
    for (int i = 0; i < n; i++)
      v[i] = r.nextInt( 10*n );
    return v;
  }

  static void time( String description, Runnable action, InstrumentedCompare compare )
  {
    long start = System.currentTimeMillis();
    action.run();
    long finish = System.currentTimeMillis();
    System.out.println( description + " took " + ((double)(finish-start)/1000.0) +" secs " + compare.count + " comparisons" );        
  }

  static class InstrumentedCompare implements Comparator<Integer>
  {
    public int count = 0;
    public int compare( Integer a, Integer b )
    {
      count++;
      return a.compareTo( b );
    }         
  }

  public static void main( String[] args )
  {
    int n = args.length >= 1 ? Integer.parseInt( args[0] ) : 100000;
    final InstrumentedCompare tournamentCompare = new InstrumentedCompare();
    final Integer[] nums = randomInts( n );
    time( "Tournament.sort", new Runnable(){ public void run(){ Tournament.sort( nums, tournamentCompare ); } }, tournamentCompare );
    final Integer[] nums2 = randomInts( n );
    final InstrumentedCompare systemCompare = new InstrumentedCompare();
    time( "Array.sort", new Runnable(){ public void run(){ Arrays.sort( nums2, systemCompare ); } }, systemCompare );
    for (int i = 0; i < n; i++)
      if (nums[i].compareTo( nums2[i] ) != 0)
      {
        System.err.println( "Arrays do not match at index: " + i );
        return;
      }
  }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: