[排序算法] 树形选择排序 (C++)
树形选择排序解释
树形选择排序 又称为锦标赛排序,其实理解起来很简单。
数组的 n 个元素就好像在进行锦标赛一样,每一轮小比赛每两个一组决出胜负(比较谁更小)。
再将每一轮的胜者每两个一组进行小比赛,直到最后决出唯一的胜者(即当前最小元素)。很明显,锦标赛构成图的形状就是一个满二叉树捏。
每一次锦标赛决出的最终胜者(最小元素),我们要将其退出比赛,即放到原数组中。
重复上述操作,n 次锦标赛,即可完成排序。
那么具体如何实现呢?
我们需要用定义一个 tree[] 数组用来存储这个满二叉树。
首先我们需要录入叶子节点,也就是我们需要排序的数组中的所有元素。
然后根据二叉树在数组中的表示方法,我们知道 若二叉树某个节点的下标为 i,可得其左孩子节点的下标为 2 * i + 1,右孩子节点下标为 2 * i + 2。
由此通过现有的叶子节点,可以得到其父节点的值,形象地说就是可以得到两个叶子节点的决胜者,即较小值。
当每次得到当前最小值,我们需要定义一个 minindex 在 tree[] 中寻找到当前这个最小值的索引,并将其置 MAX(这样就好像是它退出锦标赛了)
树形选择排序动态演示
我们以 [1, 4, 2, 3] 为例进行动态演示
第一次锦标赛得到决胜者
第二次锦标赛得到决胜者
第三次锦标赛得到决胜者
第四次锦标赛得到决胜者
树形选择排序时间复杂度
每次决出当前最小值,需要进行 log2n 次比较,总共需要进行 n 次锦标赛,所以时间复杂度
树形选择排序核心代码
void TreeSelectSort(int a[], int n){
int nodesum = n * 2 - 1; //满二叉树节点总数
int *tree = new int[nodesum];
/* 录入叶子节点 */
for(int i = n - 1, j = 0; i >= 0; i--, j++)
tree[nodesum - j - 1] = a[i];
/* 录入非叶子节点 */
for(int i = nodesum - n - 1; i >= 0; i--)
tree[i] = tree[2 * i + 1] < tree[2 * i + 2] ? tree[2 * i + 1] : tree[2 * i + 2];
/* 每次找出最小元素并复制到原数组 */
int k = 0, minindex = -1;
while(k < n){
int min = tree[0]; //当前的树根节点值即为最小元素
a[k++] = min;
minindex = nodesum - 1;
/* 从最后叶子节点开始,找到最小值位置,并将其置MAX */
while(tree[minindex] != min)
minindex--;
tree[minindex] = INT_MAX;
/* 若此节点有父节点,将其兄弟节点值提升到父节点位置 */
while(minindex > 0){
if(minindex % 2 == 1){
//该节点为左节点
tree[(minindex - 1)/2] = tree[minindex] < tree[minindex + 1] ? tree[minindex] : tree[minindex + 1];
minindex = (minindex - 1)/2;
}else{
//该节点为右节点
tree[minindex/2 - 1] = tree[minindex] < tree[minindex - 1] ? tree[minindex] : tree[minindex - 1];
minindex = minindex/2 - 1;
}
}
}
delete[] tree;
}
完整程序源代码
#include<iostream>
#include<ctime>
using namespace std;
void TreeSelectSort(int a[], int n){
int nodesum = n * 2 - 1; //满二叉树节点总数
int *tree = new int[nodesum];
/* 录入叶子节点 */
for(int i = n - 1, j = 0; i >= 0; i--, j++)
tree[nodesum - j - 1] = a[i];
/* 录入非叶子节点 */
for(int i = nodesum - n - 1; i >= 0; i--)
tree[i] = tree[2 * i + 1] < tree[2 * i + 2] ? tree[2 * i + 1] : tree[2 * i + 2];
/* 每次找出最小元素并复制到原数组 */
int k = 0, minindex = -1;
while(k < n){
int min = tree[0]; //当前的树根节点值即为最小元素
a[k++] = min;
minindex = nodesum - 1;
/* 从最后叶子节点开始,找到最小值位置,并将其置MAX */
while(tree[minindex] != min)
minindex--;
tree[minindex] = INT_MAX;
/* 若此节点有父节点,将其兄弟节点值提升到父节点位置 */
while(minindex > 0){
if(minindex % 2 == 1){
//该节点为左节点
tree[(minindex - 1)/2] = tree[minindex] < tree[minindex + 1] ? tree[minindex] : tree[minindex + 1];
minindex = (minindex - 1)/2;
}else{
//该节点为右节点
tree[minindex/2 - 1] = tree[minindex] < tree[minindex - 1] ? tree[minindex] : tree[minindex - 1];
minindex = minindex/2 - 1;
}
}
}
delete[] tree;
}
void show(int *a, int n){
for(int i = 0; i < n; i++)
cout<<*(a + i)<<" ";
cout<<endl;
}
main(){
int a[50];
srand((int)time(0));
int k = 0;
while(k < 50)
a[k++] = rand() % 100 + 1;
show(a, 50);
TreeSelectSort(a, 50);
cout<<endl<<endl;
show(a, 50);
}
程序运行结果图
[排序算法] 树形选择排序 (C++)的更多相关文章
- Python排序算法之选择排序定义与用法示例
Python排序算法之选择排序定义与用法示例 这篇文章主要介绍了Python排序算法之选择排序定义与用法,简单描述了选择排序的功能.原理,并结合实例形式分析了Python定义与使用选择排序的相关操作技 ...
- 八大排序算法~简单选择排序【记录下标k变量的作用】
八大排序算法~简单选择排序[记录下标k变量的作用] 1,思想:打擂台法,数组中的前n-1个元素依次上擂台"装嫩",后边的元素一个挨着一个不服,一个一个上去换掉它 2,优化:通过记录 ...
- 排序算法总结------选择排序 ---javascript描述
每当面试时避不可少谈论的话题是排序算法,上次面试时被问到写排序算法,然后脑袋一懵不会写,狠狠的被面试官鄙视了一番,问我是不是第一次参加面试,怎么可以连排序算法都不会呢?不过当时确实是第一次去面试,以此 ...
- 八大排序算法之四选择排序—堆排序(Heap Sort)
堆排序是一种树形选择排序,是对直接选择排序的有效改进. 基本思想: 堆的定义如下:具有n个元素的序列(k1,k2,...,kn),当且仅当满足 时称之为堆.由堆的定义可以看出,堆顶元素(即第一个元素) ...
- 【DS】排序算法之选择排序(Selection Sort)
一.算法思想 选择排序是一种简单直观的排序算法.它的工作原理如下: 1)将序列分成两部分,前半部分是已经排序的序列,后半部分是未排序的序列: 2)在未排序序列中找到最小(大)元素,放到已排序序列的末尾 ...
- 八大排序算法之三选择排序—简单选择排序(Simple Selection Sort)
基本思想: 在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换:然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素 ...
- 常用排序算法之——选择排序(C语言+VC6.0平台)
选择排序是另一种经典排序算法,核心思想是:在一趟找最小(大)数的过程中,先假设待排数据中的第一个数据即为最小(大)数据,然后循环将其他数据与该数据比较,每次比较时若小于该数据则让新数据成为最小(大)数 ...
- Java排序算法之选择排序
一.算法原理 简单选择排序的基本思想:给定数组:int[] arr={里面n个数据}:第1趟排序,在待排序数据arr[1]~arr[n-1]中选出最小的数据,将它与arrr[0]交换:第2趟,在待排序 ...
- 【排序算法】选择排序(Selection sort)
0. 说明 选择排序(Selection sort)是一种简单直观的排序算法. 它的工作原理如下. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最 ...
- 我的Java开发学习之旅------>Java经典排序算法之选择排序
一.算法原理 对比数组中前一个元素跟后一个元素的大小,如果后面的元素比前面的元素小则用一个变量k来记住他的位置, 接着第二次比较,前面"后一个元素"现变成了"前一个元素& ...
随机推荐
- KingbaseES OOM 可能原因汇总
背景 不久前,遇到过一个问题.KingbaseES数据库主机系统触发OOM现象是数据库进程被KILL, 数据库进入crash然后restart(when restart_after_crash=on) ...
- 跟羽夏学 Ghidra ——引用
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...
- .Net下的高效分页
本文技术方案支持.Net/.Net Core/.Net Framework 数据分页,几乎是任何应用系统的必备功能.但当数据量较大时,分页操作的效率就会变得很低.大数据量分页时,一个操作耗时5秒.10 ...
- SDN实验环境安装配置
- Python数据科学手册-机器学习介绍
机器学习分为俩类: 有监督学习 supervised learning 和 无监督学习 unsupervised learning 有监督学习: 对数据的若干特征与若干标签之间 的关联性 进行建模的过 ...
- 【原创】FFMPEG录屏入门指南
下载ffmpeg 点击 ffmpeg官网,选择windows,然后点击Windows builds from gyan.dev: 也可以直接点击 https://www.gyan.dev/ffmpeg ...
- ProxySQL(10):读写分离方法论
文章转载自:https://www.cnblogs.com/f-ck-need-u/p/9318558.html 不同类型的读写分离 数据库中间件最基本的功能就是实现读写分离,ProxySQL当然也支 ...
- 第六章:Django 综合篇 - 8:信号 signal
django自带一套信号机制来帮助我们在框架的不同位置之间传递信息.也就是说,当某一事件发生时,信号系统可以允许一个或多个发送者(senders)将通知或信号(signals)发送给一组接受者(rec ...
- FastDFS 分布式文件系统的安装与使用---两台服务器搭建FastDFS环境
写在前面 有不少小伙伴在实际工作中,对于如何存储文件(图片.视频.音频等)没有一个很好的解决思路.都明白不能将文件存储在单台服务器的磁盘上,也知道需要将文件进行副本备份.如果自己手动写文件的副本机制, ...
- 1_requests基础用法
requests模块的基本使用 什么是requests模块? Python中封装好的一个基于网络请求的模块 requests模块的作用? 用来模拟浏览器发请求 requests模块的环境安装: pip ...