内部排序->选择排序->树形选择排序
文字描述
树形选择排序又称锦标赛排序; 比如,在8个运动员中决出前3名至多需要11场比赛, 而不是7+6+5=18场比赛(它的前提是甲胜乙,乙胜丙,则甲必能胜丙)
首先对n个记录的关键字进行两两比较,然后在(n/2)个较小者之间再进行两两比较,直至选出最小关键字的记录为止,这个过程可用一颗有n个叶子结点的完全二叉树表示。关于完全二叉树的定义和与本排序算法用到的性质见附录1
示意图
算法分析
由于含n个叶子结点的完全二叉树的深度为[log2n]+1, 则在树形选择排序中,除了最小关键字外,每选择一个次小关键字仅需进行log2n次比较,因此它的时间复杂度为nlogn.。但是它需要的辅助空间为2*n-1。而且它在选择过程中,和"最大值"进行了多余的比较。 另外,该算法是不稳定的。
代码实现
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*
* double log2(double x); 以2为底的对数
* double ceil(double x); 取上整
* double floor(double x); 取下整
* double fabs(double x); 取绝对值
*/ #define DEBUG #define EQ(a, b) ((a) == (b))
#define LT(a, b) ((a) < (b))
#define LQ(a, b) ((a) <= (b)) #define MAXSIZE 100
#define INF 1000000
typedef int KeyType;
typedef char InfoType;
typedef struct{
KeyType key;
InfoType otherinfo;
}RedType; typedef struct{
RedType r[MAXSIZE+];
int length;
}SqList; void PrintList(SqList L){
int i = ;
printf("下标值:");
for(i=; i<=L.length; i++){
printf("[%d] ", i);
}
printf("\n关键字:");
for(i=; i<=L.length; i++){
if(EQ(L.r[i].key, INF)){
printf(" %-3c", '-');
}else{
printf(" %-3d", L.r[i].key);
}
}
printf("\n其他值:");
for(i=; i<=L.length; i++){
printf(" %-3c", L.r[i].otherinfo);
}
printf("\n\n");
return ;
} /*树形选择排序算法*/
void TreeSelectSort(SqList *L)
{
//为实现该排序所需的辅助树
SqList tree;
//辅助树的大小
tree.length = L->length- + L->length; tree.r[].otherinfo = '';
int i = , low = ;
//由后向前填充此树的叶子结点
for(i=; i<L->length; i++){
tree.r[tree.length-i] = L->r[L->length-i];
}
//由后向前填充此树的非叶子结点
for(i=(tree.length-L->length); i>=; i--){
tree.r[i] = (LT(tree.r[*i].key, tree.r[*i+].key)?tree.r[*i]:tree.r[*i+]);
}
//纪录当前辅助树的最小结点
RedType minred;
//记录最小结点在叶子结点中的下标值
int minindex = ;
while(low <= L->length){
minred = tree.r[];
#ifdef DEBUG
printf("第%d趟树形选择排序后,输出当前数最小值%d, %c\n", low, minred.key, minred.otherinfo);
PrintList(tree);
#endif
//不断移走最小结点
L->r[low++] = minred;
minindex = tree.length;
//找到最小值在辅助树叶子结点中的下标值
for(minindex=tree.length; (minindex>(tree.length-L->length)); minindex--){
if(EQ(tree.r[minindex].key, minred.key) && EQ(tree.r[minindex].otherinfo, minred.otherinfo)){
break;
}
}
//设置一个最大值标志,INF表示无穷大
tree.r[minindex].key = INF;
//重新调整此辅助树,使根结点关键字值最小
for(i=(minindex/); i>=; i/=){
tree.r[i] = (LT(tree.r[*i].key, tree.r[*i+].key)?tree.r[*i]:tree.r[*i+]);
}
}
#ifdef DEBUG
printf("按照树形选择排序后的原顺序表:\n");
PrintList(*L);
#endif
} int main(int argc, char *argv[])
{
if(argc < ){
return -;
}
SqList L;
int i = ;
for(i=; i<argc; i++){
if(i>MAXSIZE)
break;
L.r[i].key = atoi(argv[i]);
L.r[i].otherinfo = 'a'+i-;
}
L.length = (i-);
L.r[].key = ;
L.r[].otherinfo = '';
printf("输入数据:\n");
PrintList(L);
//对顺序表L作树形选择排序
TreeSelectSort(&L);
return ;
}
树形选择排序
运行
附录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
内部排序->选择排序->树形选择排序的更多相关文章
- 简单选择排序 Selection Sort 和树形选择排序 Tree Selection Sort
选择排序 Selection Sort 选择排序的基本思想是:每一趟在剩余未排序的若干记录中选取关键字最小的(也可以是最大的,本文中均考虑排升序)记录作为有序序列中下一个记录. 如第i趟选择排序就是在 ...
- 数据结构 - 树形选择排序 (tree selection sort) 具体解释 及 代码(C++)
树形选择排序 (tree selection sort) 具体解释 及 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 算法逻辑: 依据节点的大小, ...
- [译]async/await中使用阻塞式代码导致死锁 百万数据排序:优化的选择排序(堆排序)
[译]async/await中使用阻塞式代码导致死锁 这篇博文主要是讲解在async/await中使用阻塞式代码导致死锁的问题,以及如何避免出现这种死锁.内容主要是从作者Stephen Cleary的 ...
- Java常见排序算法之直接选择排序
在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let ...
- 用Python实现十大经典排序算法-插入、选择、快速、冒泡、归并等
本文来用图文的方式详细讲解了Python十大经典排序算法 —— 插入排序.选择排序.快速排序.冒泡排序.归并排序.希尔排序.插入排序.桶排序.基数排序.计数排序算法,想要学习的你们,继续阅读下去吧,如 ...
- php 实现冒泡算法排序、快速排序、选择排序,插入排序
许多人都说 算法是程序的核心,一个程序的好于差,关键是这个程序算法的优劣.作为一个初级phper,虽然很少接触到算法方面的东西 .但是对于冒泡排序,插入排序,选择排序,快速排序四种基本算法,我想还是要 ...
- 排序系列 之 简单选择排序及其改进算法 —— Java实现
简单选择排序算法: 基本思想: 在待排序数据中,选出最小的一个数与第一个位置的数交换:然后在剩下的数中选出最小的数与第二个数交换:依次类推,直至循环到只剩下两个数进行比较为止. 实例: 0.初始状态 ...
- 八大排序方法汇总(选择排序,插入排序-简单插入排序、shell排序,交换排序-冒泡排序、快速排序、堆排序,归并排序,计数排序)
2013-08-22 14:55:33 八大排序方法汇总(选择排序-简单选择排序.堆排序,插入排序-简单插入排序.shell排序,交换排序-冒泡排序.快速排序,归并排序,计数排序). 插入排序还可以和 ...
- [jQuery编程挑战]004 针对选择框词典式排序
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="utf-8&quo ...
随机推荐
- shell生成连续天数日期
#!/bin/bash #两个参数:起始时间和终止时间,循环输出每天 #输入格式:20171201 20171225 #输出格式:2017-12-01 2017-12-25 startdate=`da ...
- LeetCode: First Missing Positive 解题报告
First Missing Positive Given an unsorted integer array, find the first missing positive integer. For ...
- 基于jQuery虾米音乐播放器样式代码
分享一款基于jQuery虾米音乐播放器样式代码.这是一款基于jquery+html5实现的虾米音乐播放器源码下载.效果图如下: 在线预览 源码下载 实现的代码. html代码: <div c ...
- 【iCore1S 双核心板_ARM】例程十二:DMA实验——存储器到存储器的传输
实验原理: DAM(直接存储器访问)传输不需要占用CPU,可以在存储器至存储器实现高速的数据 传输.本实验采用DAM2控制器的数据流0,选用通道0进行数据传输.通过LED的颜色来 判断传输是否成功. ...
- Laravel 的 Homestead 开发环境部署
---恢复内容开始--- Laravel 努力在整个PHP开发过程中提供令人愉快的开发体验,当然也包括本地的开发环境. 首先明白以下几个概念 VirtualBox -- Oracle 公司的虚拟机软件 ...
- [Bayes] prod: M-H: Independence Sampler for Posterior Sampling
M-H是Metropolis抽样方法的扩展,扩展后可以支持不对称的提议分布. 对于M-H而言,根据候选分布g的不同选择,衍生出了集中不同的变种: (1)Metropolis抽样方法 (2)随机游动Me ...
- [Algorithm] Asymptotic Growth Rate
f(n) 的形式 vs 判定形势 但,此题型过于简单,一般不出现在考题中. Extended: link Let's set n = 2^m, so m = log(n) T(n) = 2*T(n^( ...
- 8 -- 深入使用Spring -- 5...2 使用@Cacheable执行缓存
8.5.2 使用@Cacheable执行缓存 @Cacheable可用于修饰类或修饰方法,当使用@Cacheable修饰类时,用于告诉Spring在类级别上进行缓存 ------ 程序调用该类的实例的 ...
- 【问题集】redis集群set报错(error) MOVED 11469 192.168.181.201:7002
没有启动集群模式(即缺少了那个"-c"): redis-cli -c -h yourhost -p yourpost
- JQuery EasyUI DataGrid获取当前行
1.获取当前行索引 var rowIndex = $('#dg').datagrid('getRowIndex', row); 2.根据索引删除当前行 $('#dg').datagrid('delet ...