算法二之树形选择排序

一、树形选择排序的基本思想

(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]);
        }
        data[data.length-1] = tree[1];   //将树根节点赋值于data

        //继续寻找剩下的最大值,逆向存储,升序排序
        for (int i = data.length-2; i >=0; i--) {

            int 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
        }
    }
时间: 2024-08-06 19:49:19

算法二之树形选择排序的相关文章

Java排序算法(二):简单选择排序

[基本思想] 在要排序的一组数中.选出最小的一个数与第一个位置的数交换:然后在剩下的数中再找出最小的与第二个位置的数交换,如此循环至倒数第二个数和最后一个数比較为止. 算法关键:找到最小的那个数.并用变量记住它的下标. [java实现] public class SimpleSelectionSort { public static void main(String[] args) { int[] arr = { 9, 1, 5, 8, 3, 7, 4, 6, 2 }; System.out.p

白话经典算法系列之四 直接选择排序及交换二个数据的正确实现

分类: 白话经典算法系列 2011-08-09 11:15 16682人阅读 评论(29) 收藏 举报 算法面试c 直接选择排序和直接插入排序类似,都将数据分为有序区和无序区,所不同的是直接播放排序是将无序区的第一个元素直接插入到有序区以形成一个更大的有序区,而直接选择排序是从无序区选一个最小的元素直接放到有序区的最后. 设数组为a[0…n-1]. 1.      初始时,数组全为无序区为a[0..n-1].令i=0 2.      在无序区a[i…n-1]中选取一个最小的元素,将其与a[i]交

算法一之简单选择排序

一.  选择排序的思想 选择排序的基本思想是:每一趟在n-i+1(i=1,2,-n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录.基于此思想的算法主要有简单选择排序.树型选择排序和堆排序. 简单选择排序的基本思想:第1趟,在待排序记录r[1]~r[n]中选出最小的记录,将它与r[1]交换:第2趟,在待排序记录r[2]~r[n]中选出最小的记录,将它与r[2]交换:以此类推,第i趟在待排序记录r[i]~r[n]中选出最小的记录,将它与r[i]交换,使有序序列不断增长直到全部排序完毕.

【数据结构】——排序算法——3.1、选择排序

      [数据结构]--排序算法--3.1.选择排序 一.先上维基的图: 分类 排序算法 数据结构 数组 最差时间复杂度 О(n2) 最优时间复杂度 О(n2) 平均时间复杂度 О(n2) 最差空间复杂度 О(n) total, O(1)auxiliary 二.描述: 选择算法算是最直观的一个了.每次在队列里抽取一个极大(或极小)值进行排列.每次都需要遍历未被抽取的元素队列. 三.Java程序: static void selection_sort(int[] unsorted) { for

内部排序-&gt;选择排序-&gt;树形选择排序

文字描述 树形选择排序又称锦标赛排序; 比如,在8个运动员中决出前3名至多需要11场比赛, 而不是7+6+5=18场比赛(它的前提是甲胜乙,乙胜丙,则甲必能胜丙) 首先对n个记录的关键字进行两两比较,然后在(n/2)个较小者之间再进行两两比较,直至选出最小关键字的记录为止,这个过程可用一颗有n个叶子结点的完全二叉树表示.关于完全二叉树的定义和与本排序算法用到的性质见附录1 示意图 算法分析 由于含n个叶子结点的完全二叉树的深度为[log2n]+1, 则在树形选择排序中,除了最小关键字外,每选择一

常见排序算法导读(3)[简单选择排序]

这一节将介绍简单选择排序(Simple Selection Sort). 在介绍简单排序算法之前,先给出排序的确切定义,并简单介绍一下排序算法的稳定性. 排序的确切定义 假设含有n个对象的序列为{R[0], R[1], ..., R[n-1]}, 其对应的关键字(key)序列为{K[0], K[1], ..., K[n-1]}. 所谓排序, 就是确定0, 1, ..., n-1的一种排列p[0], p[1], ..., p[n-1], 使各个关键字满足如下的非递减(升序)或非递增(降序)关系:

算法——蛮力法之选择排序和冒泡排序c++实现

这次实现的是蛮力法中的两个例子,选择排序法和冒泡排序法,使用的编译环境是vs2013,下面对这两个算法做一个简单介绍,然后是两个算法的c++实现代码. 选择排序法比较的范围是整个列表,每次扫描结束找出最小的一个元素一次放在前面的位置:而冒泡排序法每次是将相邻两个元素进行比较,将较大的元素放在后面,这样一次扫描结束后就将当前最大的那个元素放在了列表的后面. 两个排序方法的算法如下: 选择排序法 SelectionSort(A[0....n-1]) //输入:一个可排序数组A[0....n-1],

(二)选择排序之二:简单选择排序

选择排序分为:简答选择排序.树形选择排序.堆排序,今天来学一下简答选择排序. 具体代码如下: package com.cust.heap; /** * * 描述:简单选择排序 * @author cookie */ public class 简单选择排序 { public static void main(String[] args) { int[] array = new int[]{2,5,6,9,4,1,7}; print(array);//打印 for(int i = 0; i < ar

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

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