Hark的数据结构与算法练习之锦标赛排序
算法说明
锦标赛排序是选择排序的一种。
实际上堆排序是锦标赛排序的优化版本,它们时间复杂度都是O(nlog2n),不同之处是堆排序的空间复杂度(O(1))远远低于锦标赛的空间复杂度(O(2n-1))
堆排序是基于二叉树的, 所以锦标赛排序也是基于二叉树的,并且是完美二叉树。
我尝试用最通俗的方法来做一下解释,如果我说的不大清楚,建议大家直接看下边的代码啦。
1、例如我们要对int[] arrayData = { 5, 9, 6, 7, 4, 1, 2, 3, 8 };进行升序排序
2、我们根据锦标赛算法的要求,建立一个满足以上数组要求的完美二叉树数组,并且以上数组中的值是在二叉树的叶节点,并且叶节点必须满足完美二叉树,如果不满足者,给上Integer.MAX_VALUE(20至25行代码,29至37行)
代码中大家发现使用的并不是int数组,而是Node类的数组,该类中有data和id两个字段。 data是实际的值, id是在数组中的实际索引。 好,大家记住这个,id这块后边会用,并且是算法中的精髓
3、叶节点我们在上边已经填充上数字了,然后我们需要计算父节点们的值。 父节点i是i*2+1与i*2+2的值比较后,小的值。(代码40至46行)
4、OK,我们发现,在我们建立竞赛数组成功后,竞赛数组索引0就是最小值啦,哈哈,同时我们知道该最小值在竞赛数组中的索引位置(Node对象中的i就是索引位置啦)。 那么!!重要的来了,我们从这个最小值索引位置与邻节点两两比较,然后向上比最终比到nodes[0]。 然后就又是一个最小值出现啦!!!!重复这个过程,那么最终原始数组就变成降序喽~~!!!!(51至55行代码)
5、至此,结束,希望大家能看懂。。。。
PS:锦标赛排序我看了N个博客,我发现最后还是搞不懂,最后看了下边《参考》中的博客中的代码,才最终弄懂。 再次感叹我的资质真的挺差劲的……
代码
使用的是java
package hark.sort.selectionsort; import java.awt.Adjustable; /*
* 锦标赛排序
*/
public class TournamentTreeSort {
public static void main(String[] args) {
int[] arrayData = { 5, 9, 6, 7, 4, 1, 2, 3, 8 };
TournamentTreeSortMethod(arrayData);
for (int integer : arrayData) {
System.out.print(integer);
System.out.print(" ");
}
} public static void TournamentTreeSortMethod(int[] arrayData) {
// 第一步,建立锦标赛使用的是竞赛树节点
int leafNum = 1; // 叶子节点的数量,因为是需要完美二叉树,所以叶节点数量需要一直乘以2
while (leafNum < arrayData.length) {
leafNum *= 2;
}
int nodeCount = leafNum * 2 - 1; // 这个是竞赛数组的数量
Node[] nodes = new Node[nodeCount]; // 将叶子节点数据进行初始化, 即将arrayData数据初始化至nodes节点中,并且是叶节点,如果不够,
// 则初始化为Integer.MAX_VALUE
int dataIndex;
for (int i = leafNum - 1; i < nodeCount; i++) {
dataIndex = i - (leafNum - 1);
if (dataIndex < arrayData.length) {
nodes[i] = new Node(arrayData[dataIndex], i);
} else {
nodes[i] = new Node(Integer.MAX_VALUE, i);
}
} // 计算父节点的值。 父节点(n)的值是n*2+1与n*2+2的值的比较
for (int i = leafNum - 2; i >= 0; i--) {
if (nodes[i * 2 + 1].GetData() < nodes[i * 2 + 2].GetData()) {
nodes[i] = nodes[i * 2 + 1];
} else {
nodes[i] = nodes[i * 2 + 2];
}
} // 这里是真正的排序
// 在建竞赛树的时候,nodes中的索引0已经是最小值了,所以将它放到原始数据索引0中,因为它是最小的。
// 接着我们知道最小值在竞赛数组中的索引位置,那么我们将该值向上进行两两比较,最终比较至最顶点
for (int i = 0; i < arrayData.length; i++) {
arrayData[i] = nodes[0].GetData();
nodes[nodes[0].GetId()].SetData(Integer.MAX_VALUE);
Adjust(nodes, nodes[0].GetId());
}
} /*
* 当去除最小的元素后,我们需要从该元素的索引往上进行数组(是个树哟)的调整
*/
public static void Adjust(Node[] nodes, int index) {
while (index > 0) {
// 如果是奇数节点,则临节点是i+1,父节点是(i-1)/2
// 如果是偶数节点,则临节点是i-1,父节点是i/2-1 if (index % 2 == 1) { // 奇数节点
if (nodes[index].GetData() < nodes[index + 1].GetData()) {
nodes[(index - 1) / 2] = nodes[index];
} else {
nodes[(index - 1) / 2] = nodes[index + 1];
}
index = (index - 1) / 2;
} else { // 偶数结点
if (nodes[index].GetData() < nodes[index - 1].GetData()) {
nodes[index / 2 - 1] = nodes[index];
} else {
nodes[index / 2 - 1] = nodes[index - 1];
}
index = index / 2 - 1;
}
}
}
} class Node {
private int data;
private int id; public int GetData() {
return data;
} public void SetData(int data) {
this.data = data;
} public int GetId() {
return id;
} public Node(int data, int id) {
this.data = data;
this.id = id;
}
}
参考
http://blog.csdn.net/hopeztm/article/details/7921686
Hark的数据结构与算法练习之锦标赛排序的更多相关文章
- Hark的数据结构与算法练习之圈排序
算法说明 圈排序是选择排序的一种.其实感觉和快排有一点点像,但根本不同之处就是丫的移动的是当前数字,而不像快排一样移动的是其它数字.根据比较移动到不需要移动时,就代表一圈结束.最终要进行n-1圈的比较 ...
- Hark的数据结构与算法练习之Bogo排序
算法说明 Bogo排序是交换排序的一种,它是一种随机排序,也是一种没有使用意义的排序,同样也是一种我觉得很好玩的排序. 举个形象的例子,你手头有一副乱序的扑克牌,然后往天上不停的扔,那么有一定机率会变 ...
- Hark的数据结构与算法练习之珠排序
---恢复内容开始--- 算法说明 珠排序是分布排序的一种. 说实在的,这个排序看起来特别的巧妙,同时也特别好理解,不过不太容易写成代码,哈哈. 这里其实分析的特别好了,我就不画蛇添足啦. 大家看一 ...
- Hark的数据结构与算法练习之梳排序
算法说明梳排序是交换排序的一种,它其实也是改自冒泡排序,不同之处是冒泡排序的比较步长恒定为1,而梳排序的比较步长是变化的. 步长需要循环以数组长度除以1.3,到最后大于等于1即可. 光说可能比较抽象, ...
- Hark的数据结构与算法练习之奇偶排序
算法说明 奇偶排序又叫奇偶换位排序,砖排序.它是一种交换排序,也是冒泡的一个变种 顾名思义,奇偶排序,其实就是先循环奇数位,然后将奇数位与偶数位比较计算. 然后再循环偶数位,再和奇数位比较运算.看一下 ...
- Hark的数据结构与算法练习之鸡尾酒排序
算法说明 鸡尾酒排序又叫定向冒泡排序,鸡尾酒搅拌排序,搅拌排序,涟漪排序,回来排序,快乐小时排序. 鸡尾酒排序是交换排序的一种,它是冒泡排序的一个轻微的变种.冒泡是从低向高比较排序,鸡尾酒从低向高,从 ...
- Hark的数据结构与算法练习之煎饼排序
算法说明 假设煎锅里边有N个煎饼摞在了一起,它们大小不一并且顺序不一致,我们需要通过拿铲子将它们不停的翻个,进行排序,最终得到一个底下是大的煎饼,上边是小的煎饼的序列.这个排序的过程就是煎饼排序. 这 ...
- Hark的数据结构与算法练习之图书馆排序
算法说明 图书馆排序是插入排序的变种,典型的以空间换时间的一种方法.我个人感觉这种思路可以学习借鉴,但直接使用的场景应该不大. 我们知道,真正的插入排序通常往前边插入元素后,我们要把后边所有的元素后移 ...
- Hark的数据结构与算法练习之耐心排序
算法说明 耐心排序是插入排序的一种,至少wikipedia是这么分的. 话说我明白这个算法的实现思路了,但是不明白这么做的意义何在? 如果明白的朋友帮忙留个言说一下,以后如果我明白的话,我会来修改这个 ...
随机推荐
- 第7章 使用RAID与LVM磁盘阵列技术
章节简述: 您好,此章节为新增加的知识内容,正在努力的排版完善,预习2016年9月中旬完成,感谢您的支持,QQ群:340829. 7.1 磁盘冗余阵列 1988年由加利福尼亚大学伯克利分校发表的文章 ...
- linux查看python安装路径,版本号
一.想要查看ubuntu中安装的Python路径 方法一:whereis python 方法二:which python 二.想要查看ubuntu中安装的python版本号 python
- ios 应用程序图标、启动画面、itune图标设置
http://blog.sina.com.cn/s/blog_4cd8dd1301014hfz.html 先说说应用程序图标,一般有下面几种: Icon.png(57x57) - Homescreen ...
- [BZOJ1786][BZOJ1831]逆序对
[BZOJ1786][BZOJ1831]逆序对 试题描述 输入 输出 输入示例 - - 输出示例 数据规模及约定 见“输入” 题解 首先这题有一个性质,即,填的数从左到右一定不降.证明不妨读者自己yy ...
- MyEclipse安装JS代码提示(Spket插件)
近期需要大量使用JS来开发,但是MyEclipse2014自带的JS编辑器没有代码提示的功能,开发效率有点低,所以安装了一个Spket的插件,过程非常简单,SVN插件的安装比这个更简单. Spket插 ...
- Ubuntu 14.04/14.10下安装VMware Workstation 11图文教程
VMware workstation 是一个可以进行桌面操作的虚拟软件.它可以让我们在一台电脑或者虚拟机中运行多个虚拟机. 由VMware公司研发和维护.由于是商业软件,我们需要买他们家的许可证或者说 ...
- 暑假热身 E. 无聊的LSY
LSY大牛没事就爱玩游戏,包括很多很无聊的游戏.某日,LSY大牛又找到了一个无聊的游戏:每一局游戏的开始,LSY大牛将代表自己的棋子放在一个线性棋盘的最左端(第0个格子,可以认为向右端无限延伸),接着 ...
- Apache配置文件中的deny和allow的使用
Apache配置文件中的deny和allow的使用 由于产品的需要,最近在配置apache的负载均衡功能,但是在配置虚拟主机的访问权限的时候我们遇到了一些问题.主要问题是deny和allow的执行顺序 ...
- iOS 使用interface builder 创建太复杂的constrains时容易产生crash
今天写程序,遇到了crash,在界面初始化时不会有,想切换到别的tab页就报错了.主要内容如下: Cannot find an outgoing row head for incoming head ...
- web开发中目录路径问题的解决
web开发当中,目录路径的书写是再常用不过了,一般情况下不会出什么问题,但是有些时候出现了问题却一直感到奇怪,所以这里记录一下,彻底解决web开发中路径的问题,开发分为前端和服务端,那么就从这两个方面 ...