首页 > 其他分享 >锦标赛排序(树形选择排序)

锦标赛排序(树形选择排序)

时间:2022-09-04 11:23:20浏览次数:51  
标签:结点 idx 锦标赛 树形 数组 排序 节点

1.介绍

  树形选择排序(Tree Selection Sort),又称锦标赛排序(Tournament Sort),是一种按照锦标赛思想进行选择排序的不稳定排序。

2.实现原理

  如图所示,给定有8个元素的数组,对该数组进行从小到大的排序。

  第一步,如图所示,根据数组建立一颗满二叉树(胜者树),用于进行‘锦标赛事’的多层次比较。所有的数组元素如同打锦标赛一样全部位于二叉树的叶子节点上,因为是满二叉树,所以所有的数组元素都位于最底层,请读者自行思考。元素数量不足时,用空节点补齐。

  第二步,如图所示,像锦标赛一样,让相邻节点相互‘pk’,把数值较小的节点“晋升”到其父节点上,注意,这一排序目标是从小到大,因此是较小的移到父节点,反之,则是较大的移到父节点。

  如此一来,聪明的读者一定可以自己推出第一次打完锦标赛时树的样子了,如图所示,显而易见,树的根节点的值最小,就像锦标赛中冠军一定是本赛季最强的一个道理。

  选出最小值后,将该叶子节点删除(设为无穷大),接着继续打锦标赛(选手们不累吗),当然选手们并不用那么辛苦,我们不必对整棵树进行操作,因为第二小的值一定是在和第一小的值对峙时败下阵来的,因此第二小的数一定在第一小的晋升的路上,所以只需在这条路上再选出一个第一小的数就行了(图就不画了,太难受了)。

  重复上述步骤n轮你就成功的排好序了,Oh Yeah!

3.算法复杂度分析

  创建和填充二叉树仅需O(n),后继每一轮进行局部刷新二叉树需要O(logn),共进行n-1轮,因此总的时间复杂度为:O(nlogn);

  由于二叉树的结点数量和数组元素个数成正比,所以空间复杂度为O(n)。相对于选择排序,锦标赛排序有效地降低了时间复杂度,但使用的辅助存储空间较多,和∞的比较多余。

  实际编程时,除叶子结点外,并不需要在其它结点保存刷新的元素值,可以使用辅助数组idx[]保存刷新的元素值的原始下标位置即可。如图所示,数组idx[]初始化时,idx[8]=0表示结点8的值为a[0],idx[9]=1表示结点9的值为a[1]......

假设现在更新结点7的值,因为左子结点的编号为14(即7<<1),右子结点的编号为15(即(7<<1)+1),它们指向的元素值分别为27和49,所以idx[7]的值应为6,即a[6]的值。

 

\完结撒花!!!/

 

等等……是不是漏了些什么……

  

 4.参考程序

 1 #include <bits/stdc++.h>
 2 #define INF 0x3f3f3f
 3 using namespace std;
 4 int a[1000100],idx[1000100];
 5 int siz = 1;
 6 void Adjust(int p,int Ls,int Rs){
 7     idx[p] = a[idx[Ls]]<a[idx[Rs]]?idx[Ls]:idx[Rs];
 8 }
 9 int main(){
10     int n;
11     cin>>n;
12     while (siz<n){
13         siz<<=1; //siz*=2;
14     }
15     for (int i=0;i<n;i++){
16         cin>>a[i];
17         idx[i+siz] = i; //辅助数组记录数组下标 
18     }
19     for (int i=n;i<siz;i++){
20         a[i] = INF; //空节点设为无穷大( 
21         idx[i+siz] = i;
22     }
23     for (int i = siz-1;i;i--)
24         Adjust(i,i<<1,(i<<1)+1); //节点,左儿子,右儿子下标 
25     for (int i=0;i<n;i++){
26         cout<<a[idx[1]]<<' '; //输出 
27         a[idx[1]] = INF;
28         for (int j=(idx[1]+siz)>>1;j;j>>=1){
29             Adjust(j,j<<1,(j<<1)+1);
30         }
31     }
32     return 0;
33 }

 

标签:结点,idx,锦标赛,树形,数组,排序,节点
From: https://www.cnblogs.com/reasa/p/16654283.html

相关文章

  • 排序算法整理C++(初赛)
    排序算法整理常见考点将一个乱掉的字符串排回有序(以交换为基本操作)的最少操作,就是冒泡排序。排序算法的稳定性排序算法的时间复杂度排序算法的稳定性稳定性是指排......
  • java 实现冒泡排序
    先循环一次将数组内部的最大元素排序到最后一位importjava.util.Arrays;publicclassMain{ publicstaticvoidmain(String[]args){ int[]arr1={2,5,8,......
  • 列表排序
    列表排序给定一个$n$行$m$列的整数列表。列表中每一行的$m$个整数都是一个$1\simm$的排列。现在,你可以对该列表执行以下两种操作:选择一行中的两个整数并交......
  • leetcode 面试题08.08 有重复字符串的排列组合 C/C++ 排序 + 深度优先搜索(分支限界)
    #include<iostream>#include<algorithm>#include<vector>usingnamespacestd;classSolution{public:vector<string>permutation(stringS){sort(S.begin(......
  • 归并排序
    需要额外空间的外部排序?菜鸟教程版本这个版本的写法很不一样,首先,它每次都copy构造了两个子数组,然后再从这两个子数组中挑元素往原数组放构造的两个子数组容量都+1,并且......
  • 排序
    其实排序能用的上的就三个:快排,归并,基排(\(O(wys)\))。(其实priority_queue可能也算)快排很好说,sort就行。还有一个stable_sort是相同大小元素顺序不变的稳定排序算法。(事实上......
  • element Tree 树形控件 指定点击,一级或二级或某级菜单, 触发事件
    改变数据结构(添加属性)data:[{label:'一级1',whether:false,children:[{label:'二级2',whet......
  • js 实现快速排序
    //快速排序//稳定性//快速排序是以两个游标(指针)双向遍历,当两个指针相遇则遍历结束,并将相遇位置与基准值进行交换,递归出口为左游标>=右游标//快速排序的每一轮处理......
  • 饮冰三年-人工智能-Pandas-78-Pandas 新增、统计、排序
    上一篇:饮冰三年-人工智能-Pandas-77-Pandas数据查询 数据准备可参考:饮冰三年-人工智能-Django淘宝拾遗-75-数据准备一、新增数据列1.1直接赋值#1:直接赋值(将性别......
  • 信息学奥赛一本通 1185:单词排序
    时间限制:1000ms      内存限制:65536KB提交数:20423   通过数:10401【题目描述】输入一行单词序列,相邻单词之间由1个或多个空格间隔,请按照字典......