算法二之树形选择排序
2017-11-26 17:56
246 查看
一、树形选择排序的基本思想
(1) 树形选择排序又称锦标赛排序(Tournament Sort),是一种按照锦标赛的思想进行选择排序的方法。首先对n个记录的关键字进行两两比较,然后在n/2个较小者之间再进行两两比较,如此重复,直至选出最小的记录为止。
(2) 树形选择排序(Tree Selection Sort),这个过程可用一棵有n个叶子结点的完全二叉树表示。
例如,图表中的二叉树表示从8个数中选出最小数的过程。
8个叶子结点到根接点中的关键字,每个非终端结点中的数均等于其左右孩子结点中较小的数值,则根结点中的数即为叶子结点的最小数。在输出最小数之后,割据关系的可传递性,欲选出次小数,仅需将叶子结点中的最小数(13)改为“最大值”,然后从该叶子接点开始,和其左(或右)兄弟的数值进行比较,修改从叶子结点到根的路径上各结点的数,则根结点的数值即为最小值。同理,可依次选出从小到大的所有数。
(3) 由于含有n个子结点的完全二叉树的深度为log2n+1,则在树形选择排序中,除了最小数值之外,每选择一个次小数仅需要进行log2n次比较,因此,它的时间复杂度为O(nlogn)。但是,这种排序方法尚有辅助存储空间较多、和“最大值”进行多余比较等缺点。为了弥补,威洛姆斯(J. willioms)在1964年提出了另一种形式的选择排序——堆排序。
(1) 树形选择排序又称锦标赛排序(Tournament Sort),是一种按照锦标赛的思想进行选择排序的方法。首先对n个记录的关键字进行两两比较,然后在n/2个较小者之间再进行两两比较,如此重复,直至选出最小的记录为止。
(2) 树形选择排序(Tree Selection Sort),这个过程可用一棵有n个叶子结点的完全二叉树表示。
例如,图表中的二叉树表示从8个数中选出最小数的过程。
8个叶子结点到根接点中的关键字,每个非终端结点中的数均等于其左右孩子结点中较小的数值,则根结点中的数即为叶子结点的最小数。在输出最小数之后,割据关系的可传递性,欲选出次小数,仅需将叶子结点中的最小数(13)改为“最大值”,然后从该叶子接点开始,和其左(或右)兄弟的数值进行比较,修改从叶子结点到根的路径上各结点的数,则根结点的数值即为最小值。同理,可依次选出从小到大的所有数。
(3) 由于含有n个子结点的完全二叉树的深度为log2n+1,则在树形选择排序中,除了最小数值之外,每选择一个次小数仅需要进行log2n次比较,因此,它的时间复杂度为O(nlogn)。但是,这种排序方法尚有辅助存储空间较多、和“最大值”进行多余比较等缺点。为了弥补,威洛姆斯(J. willioms)在1964年提出了另一种形式的选择排序——堆排序。
二、算法实现
算法从叶子节点中选出最大值,逆向存储在数据队列中,形成升序排序。public static void treeSelectionSort(int[] data) { //长度小于2,无需排序 if(data.length<2){ return; } int leafCount = 1; //满二叉树的叶子节点数,非完全二叉树叶子节点数 //计算出满二叉树的叶子节点数,节点数大于等于数据队列的长度 while (leafCount < data.length) { leafCount *= 2; } int[] tree = new int[leafCount * 2]; //树,tree[0]不存储数据 //data里面的值赋值到树叶子节点 for (int i = 0; i < data.length; i++) { tree[tree.length - i - 1] = data[i]; } //初始化还没有赋值的树叶子结点,赋值叶子节点最小值 for (int i = data.length; i < leafCount; i++) { tree[tree.length - i - 1] = Integer.MIN_VALUE; } //初始化,构建整棵树 for (int i = tree.length - 1; i > 1; i -= 2) { tree[i / 2] = Math.max(tree[i], tree[i - 1 b30c ]); } data[data.length-1] = tree[1]; //将树根节点赋值于data int maxIndex; //堆最大值所对应的叶子节点的下标 //继续寻找剩下的最大值,逆向存储,升序排序 for (int i = data.length-2; i >=0; i--) { maxIndex = tree.length - 1; //默认堆最后一个位置 //寻找树根值所在的叶子节点的位置 while (tree[maxIndex] != tree[1]) { maxIndex--; } tree[maxIndex]=Integer.MIN_VALUE; //该叶子节点赋值最小值 //调整树,根节点值最大 while(maxIndex>1){ //左叶子结点 if (maxIndex % 2 == 0) { tree[maxIndex / 2] = Math.max(tree[maxIndex] , tree[maxIndex + 1]); } else { tree[maxIndex / 2] = Math.max(tree[maxIndex] , tree[maxIndex - 1]); } maxIndex/=2;//指向父节点 } data[i] = tree[1]; //将树根节点赋值于data } }
相关文章推荐
- java中的排序算法——简单选择排序,树形选择排序与堆排序(一)
- 算法二之树形选择排序
- 算法小记:选择排序
- Java数据结构与算法之数组排序——选择
- 冒泡排序、选择排序、堆排序、快速排序、插入排序算法复杂度分析与算法实现(自己总结与转)
- 算法兴趣----- 一亿数据获取前100个最大值(仅供参考,基于快速排序的实现时间不稳定,基于最小堆实现。如果我们只要求前K个最大(小)值的时候,用堆是最好的选择,因为这里不用每次都排序了)
- 【算法】选择排序
- 【算法拾遗(java描写叙述)】--- 选择排序(直接选择排序、堆排序)
- 几种常见排序算法之Java实现(插入排序、希尔排序、冒泡排序、快速排序、选择排序、归并排序)
- 算法-选择排序
- 数据结构:排序算法之堆排序和选择排序
- java选择排序算法案例
- 算法 - 选择排序(C#)
- 选择排序、树形排序、堆排序的java代码实现
- PHP数据结构基本算法一:矩阵转置 求素数 冒泡排序 选择排序
- 算法 -- Java实现选择排序(图解 + 代码实现)
- 第十五周项目1 验证算法(5)选择排序之堆排序
- 算法--数组冒泡排序和选择排序原理分析
- 【算法】 选择排序
- 算法笔记(1)-选择排序