内部排序->选择排序->树形选择排序

文字描述

  树形选择排序又称锦标赛排序; 比如,在8个运动员中决出前3名至多需要11场比赛, 而不是7+6+5=18场比赛(它的前提是甲胜乙,乙胜丙,则甲必能胜丙)

  首先对n个记录的关键字进行两两比较,然后在(n/2)个较小者之间再进行两两比较,直至选出最小关键字的记录为止,这个过程可用一颗有n个叶子结点的完全二叉树表示。关于完全二叉树的定义和与本排序算法用到的性质见附录1

示意图

算法分析

  由于含n个叶子结点的完全二叉树的深度为[log2n]+1, 则在树形选择排序中,除了最小关键字外,每选择一个次小关键字仅需进行log2n次比较,因此它的时间复杂度为nlogn.。但是它需要的辅助空间为2*n-1。而且它在选择过程中,和"最大值"进行了多余的比较。 另外,该算法是不稳定的。

代码实现

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <math.h>
  4 /*
  5  * double log2(double x);    以2为底的对数
  6  * double ceil(double x);    取上整
  7  * double floor(double x);    取下整
  8  * double fabs(double x);    取绝对值
  9  */
 10
 11 #define DEBUG
 12
 13 #define EQ(a, b) ((a) == (b))
 14 #define LT(a, b) ((a) <  (b))
 15 #define LQ(a, b) ((a) <= (b))
 16
 17 #define MAXSIZE  100
 18 #define INF         1000000
 19 typedef int KeyType;
 20 typedef char InfoType;
 21 typedef struct{
 22     KeyType key;
 23     InfoType otherinfo;
 24 }RedType;
 25
 26 typedef struct{
 27     RedType r[MAXSIZE+1];
 28     int length;
 29 }SqList;
 30
 31 void PrintList(SqList L){
 32     int i = 0;
 33     printf("下标值:");
 34     for(i=0; i<=L.length; i++){
 35         printf("[%d] ", i);
 36     }
 37     printf("\n关键字:");
 38     for(i=0; i<=L.length; i++){
 39         if(EQ(L.r[i].key, INF)){
 40             printf(" %-3c", ‘-‘);
 41         }else{
 42             printf(" %-3d", L.r[i].key);
 43         }
 44     }
 45     printf("\n其他值:");
 46     for(i=0; i<=L.length; i++){
 47         printf(" %-3c", L.r[i].otherinfo);
 48     }
 49     printf("\n\n");
 50     return ;
 51 }
 52
 53 /*树形选择排序算法*/
 54 void TreeSelectSort(SqList *L)
 55 {
 56     //为实现该排序所需的辅助树
 57     SqList tree;
 58     //辅助树的大小
 59     tree.length = L->length-1 + L->length;
 60
 61     tree.r[0].otherinfo = ‘0‘;
 62     int i = 0, low = 1;
 63     //由后向前填充此树的叶子结点
 64     for(i=0; i<L->length; i++){
 65         tree.r[tree.length-i] = L->r[L->length-i];
 66     }
 67     //由后向前填充此树的非叶子结点
 68     for(i=(tree.length-L->length); i>=1; i--){
 69         tree.r[i] = (LT(tree.r[2*i].key, tree.r[2*i+1].key)?tree.r[2*i]:tree.r[2*i+1]);
 70     }
 71     //纪录当前辅助树的最小结点
 72     RedType minred;
 73     //记录最小结点在叶子结点中的下标值
 74     int minindex = 0;
 75     while(low <= L->length){
 76         minred = tree.r[1];
 77 #ifdef DEBUG
 78         printf("第%d趟树形选择排序后,输出当前数最小值%d, %c\n", low, minred.key, minred.otherinfo);
 79         PrintList(tree);
 80 #endif
 81         //不断移走最小结点
 82         L->r[low++] = minred;
 83         minindex = tree.length;
 84         //找到最小值在辅助树叶子结点中的下标值
 85         for(minindex=tree.length; (minindex>(tree.length-L->length)); minindex--){
 86             if(EQ(tree.r[minindex].key, minred.key) && EQ(tree.r[minindex].otherinfo, minred.otherinfo)){
 87                 break;
 88             }
 89         }
 90         //设置一个最大值标志,INF表示无穷大
 91         tree.r[minindex].key = INF;
 92         //重新调整此辅助树,使根结点关键字值最小
 93         for(i=(minindex/2); i>=1; i/=2){
 94             tree.r[i] = (LT(tree.r[2*i].key, tree.r[2*i+1].key)?tree.r[2*i]:tree.r[2*i+1]);
 95         }
 96     }
 97 #ifdef DEBUG
 98     printf("按照树形选择排序后的原顺序表:\n");
 99     PrintList(*L);
100 #endif
101 }
102
103 int  main(int argc, char *argv[])
104 {
105     if(argc < 2){
106         return -1;
107     }
108     SqList L;
109     int i = 0;
110     for(i=1; i<argc; i++){
111         if(i>MAXSIZE)
112             break;
113         L.r[i].key = atoi(argv[i]);
114         L.r[i].otherinfo = ‘a‘+i-1;
115     }
116     L.length = (i-1);
117     L.r[0].key = 0;
118     L.r[0].otherinfo = ‘0‘;
119     printf("输入数据:\n");
120     PrintList(L);
121     //对顺序表L作树形选择排序
122     TreeSelectSort(&L);
123     return 0;
124 }

树形选择排序

运行



附录1 完全二叉树

定义:设二叉树深度为h,除第h层外,其他各层(1 ~ h-1)的结点数都达到最大个数,第h层所有的结点都集中在最左边,这就是完全二叉树。

性质:

1] 结点i (i>1)的双亲结点为i/2

2] 结点i的左孩子结点为2*i, 右孩子结点为2*i+1

3] 叶子结点数n0, 度为2(有左、右孩子结点)的结点数n2, 则n0 = n2+1

性质3]证明:

  设n1为二叉树中度为1的结点数。因为二叉树中所有结点数的度均不大于2。所以二叉树的结点数n = n0 + n1 +n2 -- (1)。

  又除根结点外,其余结点都有一个分支进入,设B为分支总数,则n=B+1。由于这些分支是由度为1或2的结点射出的,所以又有B=n1+2*n2,于是得n = B+1 = n1+2*n2+1 – (2)。

  由(1)和(2)知, n0 = n2 +1

原文地址:https://www.cnblogs.com/aimmiao/p/9373999.html

时间: 2025-01-12 11:43:05

内部排序->选择排序->树形选择排序的相关文章

算法二之树形选择排序

一.树形选择排序的基本思想 (1) 树形选择排序又称锦标赛排序(Tournament Sort),是一种按照锦标赛的思想进行选择排序的方法.首先对n个记录的关键字进行两两比较,然后在n/2个较小者之间再进行两两比较,如此重复,直至选出最小的记录为止. (2) 树形选择排序(Tree Selection Sort),这个过程可用一棵有n个叶子结点的完全二叉树表示. 例如,图表中的二叉树表示从8个数中选出最小数的过程. 8个叶子结点到根接点中的关键字,每个非终端结点中的数均等于其左右孩子结点中较小的

[golang] 数据结构-树形选择排序(锦标赛排序)

接上文 简单选择排序简单选择排序很容易理解,代码也很容易实现.但毕竟比较次数太多.树形选择排序则对这个问题进行了改进. 原理简单来说,树形选择排序(Tree selection sort)就是在选择完一轮找出最小值后,直接在与最小值比较中稍大的元素里筛选出最小的.这样避免了简单选择查询那种,抛弃了之前比较过的结果,每次都全部重新比较的情况. 流程举例 先列出所有待排序的元素如:8.4.12.7.35.9.22,并用他们组成满二叉树的叶子元素,不足的位置以∞作为补充.将元素两两相比较,分别得到较小

内部排序(1)——选择排序

选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完. 选择排序是不稳定的排序方法(比如序列[5, 5,3]第一次就将第一个[5]与[3]交换,导致第一个5挪动到第二个5后面). 选择排序算法步骤如下: 第1步:在未排序的n个数中找到最小数,讲它与a[0]交换. 第2步:在剩下未排序的n-1个数(a[1]~a[n-1])中找到最小数,将它与a[1]交换: -- 第

排序算法2--简单选择排序、堆排序

一.简单选择排序和堆排序都属于选择排序 选择排序的思想是:每一趟从待排序的记录中选出关键字最小的记录,按顺序放在以排序的记录序列的后面,知道全部拍完为止. 二.简单选择排序(直接选择排序) 1.简单选择排序法是每次循环找出最值,循环结束后将最值调整到合适位置,交换的次数少. 每次找出当前无序队列中的最小的元素与第一个交换位置,再选择第二小的与第二个交换位置 原始队列:   3 5 6 2 4 1(最小元素1与3交换) 第一步: 1 5 6 2 4 3 (当前最小元素2与5交换) 第二步: 1 2

排序算法之简单排序(冒泡、选择、插入)

1.基本概念 内部排序和外部排序 根据排序过程中,待排序的数据是否全部被放在内存中,分为两大类: 内部排序:指的是待排序的数据存放在计算机内存中进行的排序过程: 外部排序:指的是排序中要对外存储器进行访问的排序过程. 内部排序是排序的基础,在内部排序中,根据排序过程中所依据的原则可以将它们分为5类:插入排序.交换排序.选择排序.归并排序:根据排序过程的时间复杂度来分,可以分为简单排序.先进排序.冒泡排序.简单选择排序.直接插入排序就是简单排序算法. 评价排序算法优劣的标准主要是两条:一是算法的运

排序算法七:选择排序之堆排序

排序算法七:选择排序之堆排序 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 引言 在我的博文<"主宰世界"的10种算法短评>中给出的首个算法就是高效的排序算法.本文将对排序算法做一个全面的梳理,从最简单的"冒泡"到高效的堆排序等. 上博文讲述了选择排序中的简单排序算法,本文介绍的堆排序是树性选择排序,采用堆这个数据结构来辅助排序. 排序相关的的基本概念 排序:将一组杂乱无章的数据按一定的规律顺次排列起来. 数据

百万数据排序:优化的选择排序(堆排序)

  前一篇给大家介绍了<必知必会的冒泡排序和快速排序(面试必知)>,现在继续介绍排序算法          本博文介绍首先介绍直接选择排序,然后针对直接选择排序的缺点改进的"堆排序",堆排序非常适合:数组规模非常大(数百万或更多) + 严格要求辅助空间的场景.   直接选择排序 (一)概念及实现 直接选择排序的原理:将整个数组视为虚拟的有序区和无序区,重复的遍历数组,每次遍历从无序区中选出一个最小(或最大)的元素,放在有序区的最后,每一次遍历排序过程都是有序区元素个数增加,

14. 蛤蟆的数据结构进阶十四排序实现之简单选择排序

14. 蛤蟆的数据结构进阶十四排序实现之简单选择排序 本篇名言:"即是我们是一支蜡烛也应该 " 蜡烛成灰泪始干 " 即使我们只是一根火柴也要在关键时刻有一次闪耀即使我们死后尸骨都腐烂了解也要变成磷火在荒野中燃烧. -- 艾青" 继续来看什么是简单选择排序. 欢迎转载,转载请标明出处: 1.  简单选择排序 设所排序序列的记录个数为n.i取1,2,-,n-1,从所有n-i+1个记录(Ri,Ri+1,-,Rn)中找出排序码最小的记录,与第i个记录交换.执行n-1趟后就完

[jQuery编程挑战]004 针对选择框词典式排序

<!DOCTYPE html> <html lang="zh"> <head> <meta charset="utf-8"/> <title>针对选择框词典式排序</title> <script type="text/javascript" src="../js/jquery-1.11.0.js"></script> <scr