C++勝者樹
#include <iostream>define MAX_VALUE 0x7fffffff
using namespace std; //在這里我先反思一下,不知道怎么搞的,這個算法耗費我3個小時,慘不忍睹。 void DealWhat(int b[],int n,int flags)//每一次在n位置調整該位置的與子樹的大小關系。 { int left = 2 n + 1; int right = 2 n + 2; if (left > flags)//左右子樹都不是內部節點。 { if (b[left] > b[right]) b[n] = right; else b[n] = left; } else if (left == flags && right > flags)//左子樹是內部節點,右子樹不是。 { if (b[b[left]] > b[right]) b[n] = right; else b[n] = b[left]; } else//是完全內部結點。 { if (b[b[left]] > b[b[right]]) b[n] = b[right]; else b[n] = b[left]; } } void Grial(int a[],int n) { int size = 2 n - 1; int b = new int[size]; int k = size-1; int i = n - 1; while (i>=0) { b[k--] = a[i]; i--; } i = size / 2-1; int flags = i;//標記值,用來判斷節點是不是完全內部節點,就是該節點的子節點不是葉子節點。 while (i>=0) { DealWhat(b, i, flags);//初始化構造勝者樹。 i--; } int *save = new int[n];//vs2013下面不能修改a[i]的值,我試著將a數組直接保存求得 k = 0; //的數字,可是總是報錯,惆悵了半天。
i = 1; while (k < n) { save[k++] = b[b[0]]; b[b[0]] = MAX_VALUE;//每次取走該位置的這個值后,將該位置的值設為無窮大。 i = (b[0] -1) /2 ; while (i >= 0) {DealWhat(b, i, flags); if (i == 0)break; i = (i - 1)/2;//此處每次操作完畢之后朝父親節點移動。 } } for (i = 0; i < n; i++) { cout << save[i] << " "; } cout << endl; delete[]b; b = nullptr;//vs2013里面的NULL=nullptr。
} int main() { int a[] = {2,3,4,1,7,6,0,22,-1,33,5}; Grial(a, 11); return 0; }</pre> 勝者樹類似于冒泡排序的優化,記錄已經比較的,去掉不必比較的,
將最小的不停冒泡選出,最終得到結果,跟堆十分類似。