败者树是计算机科学学科里的一种数据结构,可用于外部排序中提高效率。实际上是一棵完全二叉树。
败者树的中间结点记录的败者的标号 它可以在 log(n) 时间内找到最值。
败者树的建立:在参赛者数组b[]的最后添加一位,存放一个参赛选手的绝对最小值(选手都是正数的话,如-1)。所有中间节点都记录这个最小值的下标。然后依次调整(adjust())各个选手即可。
败者树的调整:当改变一个选手的值,需要调整以维持败者树的形态。败者树只需调整选手的父节点即可。当子节点的值大于父节点,则子节点记录于父节点(小为胜利,记录败者),父节点继续与其父节点比赛;若子节点小于父节点,则直接使用子节点进行下一轮比赛。
如图所示是一颗败者树,规定数大者败。
- b0与b1对比,b0败
- b2与b3对比,b3败
- b1与b2对比,b2败
ls[0]记录的是胜者的下标
相关实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| #include <stdio.h> #include <string.h> #define LEN 4 #define MIN -1
int buf[LEN+1]; int ls[LEN+1];
inline void adjust(int index, int *arr) { int tmp = (index+LEN)>>1;
while (tmp > 0) { if (buf[index] > buf[ls[tmp]]) { ls[tmp] ^= index; index ^= ls[tmp]; ls[tmp] ^= index; } tmp /= 2; } ls[0] = index; }
inline void build(int *arr) { buf[LEN] = MIN;
for (int i = 0; i < LEN+1; i++) ls[i] = LEN; for (int i = 0; i < LEN; i++) adjust(i, arr); } int main(int argc, char const *argv[]) { int arr[] = {12, 1, 6, 8}; memcpy(buf,arr,LEN*sizeof(int)); build(buf);
printf("%d\n", buf[ls[0]]);
arr[1] = 22; memcpy(buf,arr,LEN*sizeof(int)); adjust(1, buf); printf("%d\n", buf[ls[0]]); return 0; }
|
结果输出:
败者树一般用于外部排序中,相关代码可访问ExternalSort