• 排序算法---堆排序


    不稳定 O(nlogn)

    大顶堆(从大到小排序):每个结点的值都大于等于其左右孩子的值的二叉树

    小顶堆(从小到大排序):每个结点的值都小于等于其左右孩子的值的二叉树

    如何排序?

    将待排序序列构建成一个小顶堆,堆顶的元素即为所有元素中的最小值

    在输出堆顶的最小值之后,调整堆,使剩余的n-1个元素又建成一个小顶堆,此时的堆顶元素为次小元素

    以此类推,直到堆为空

    如何在输出堆顶元素之后调整堆?

    (1)以堆中的最后一个元素代替堆顶元素,此时堆顶元素的左右子树均符合小顶堆或者大顶堆,只需从上到下调整即可

    (2)比较对顶元素和其左右孩子,

      如果右孩子的值最小,则,将右孩子和堆顶元素交换,此时,可能导致堆顶元素的右子树不满足条件,以相同方法调整右子树

      如果左孩子的值最小,则,将左孩子和堆顶元素交换,此时,可能导致堆顶元素的左子树不满足条件,以相同方法调整左子树

      如果堆顶元素就是最小的,不用调整。

    如何将待排序序列构建成一个堆?

    将待排序序列看成一个完全二叉树,有n个元素,标号从1开始,则最后一个标号就是n,最后一个元素即为完全二叉树的最后一个叶子节点,最后一个叶子节点的父节点即为最后一个非叶子节点。编号为n的节点的父结点的编号为n/2向下取整,从最后一个非叶子节点开始,像上述调整过程一样,从下到上调整完全二叉树为小顶堆或者大顶堆。

     

        public static void heapSort(int[] array){
            //1.根据待排序序列构建一个小顶堆
            createHeap(array);
            System.out.println("建立小顶堆完成");
            //2.输出堆顶元素,然后调整堆
            //输出堆顶元素,用最后一个元素替换堆顶元素,然后调整堆为小顶堆,循环上述过程,直到最后一个元素
            for(int i=0;i<array.length;i++){
                System.out.print(array[0]+" ");
                array[0] = array[array.length-1-i];
                //用最后一个元素代替堆顶元素之后,可能只会导致堆顶和它的左右孩子不满足要求,调整堆顶即可
                judgeHeap(array, 0, array.length-i-1);
            }
        }
        public static void createHeap(int[] array){
            int length = array.length;
            //从第n/2向下取整个元素开始调整,第n/2向下取整个元素在数组中的下标为n/2向下取整-1
            for(int i=length/2-1;i>=0;i--){
                judgeHeap(array, i, length);
            }
            
        }
        
        public static void judgeHeap(int array[],int k,int length){
            //根据完全二叉树的定义,一个节点i如果有左孩子,左孩子的编号为2*i,右孩子为2*i+1
            //左孩子在数组中的下标为2(i+1)-1=2*i+1   右孩子在数组中的下标为2(i+1)+1-1=2*(i+1)
            //每次调整的时候,都要从当前节点一直调整到当前节点下的叶子节点
            for(int i=k;i<length;){
                if(2*i+1>=length){//表示当前节点就是叶子节点
                    break;
                }
                int root = array[i];
                int leftChild = Integer.MAX_VALUE;
                int rightChild = Integer.MAX_VALUE;
                //判断是否有左孩子
                if(2*i+1  < length){
                    leftChild = array[2*i+1];
                }
                if(2*(i+1) < length){
                    rightChild = array[2*(i+1)];
                }
                int index = 0;//记录当前节点和它的左右孩子中最小的那个数的下标
                if(leftChild<=rightChild){
                    index = 2*i+1;
                }else{
                    index = 2*(i+1);
                }
                
                if(root<array[index]){
                    index = i;
                }
                //System.out.println("要替换的下标:"+index+"--"+i);
                if(index != i){//一个节点跟它的左右孩子节点中,最小的不是根节点,交换
                    int temp = array[index];
                    array[index] = array[i];
                    array[i] = temp;
                    //交换之后,可能会导致被交换的那个节点组成的子树不满足小顶堆,因此,要再调整
                    
                    i = index;
                }else{
                    //如果没有交换,则不会打乱小顶堆,什么也不做,直接调整下一个节点
                    break;
                }
                
                //listArray(array);
            }
    
        }
    原始数据:49 38 65 97 76 13 27 49 
    要替换的下标:7--3
    49 38 65 49 76 13 27 97 
    要替换的下标:5--2
    49 38 13 49 76 65 27 97 
    要替换的下标:1--1
    要替换的下标:2--0
    13 38 49 49 76 65 27 97 
    要替换的下标:6--2
    13 38 27 49 76 65 49 97 
    建立小顶堆完成
    要替换的下标:2--0
    27 38 97 49 76 65 49 97 
    要替换的下标:6--2
    27 38 49 49 76 65 97 97 
    要替换的下标:1--0
    38 97 49 49 76 65 97 97 
    要替换的下标:3--1
    38 49 49 97 76 65 97 97 
    要替换的下标:1--0
    49 65 49 97 76 65 97 97 
    要替换的下标:1--1
    要替换的下标:2--0
    49 65 76 97 76 65 97 97 
    要替换的下标:1--0
    65 97 76 97 76 65 97 97 
    要替换的下标:0--0

     

  • 相关阅读:
    MVC中的helper标签
    自适应网页设计(Responsive Web Design)
    网站设计的最简主义
    Windows Forms数据绑定技术
    [C#]写自己的类库
    C#数据库连接字符串
    CSS float属性
    CSS之UL
    NET教程:MVC4使用Bundling,CSS中图片路径问题
    ASP.net 中Get和Post的用法
  • 原文地址:https://www.cnblogs.com/duanjiapingjy/p/9557586.html
Copyright © 2020-2023  润新知