• 排序系列 之 堆排序算法 —— Java实现


       基本概念:

      二叉堆是完全二叉树或者是近似完全二叉树。

      当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆

      当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆

      一般将二叉堆简称为堆。

     基本思想:

      1.把n个元素建立最大堆,把堆顶元素A[0]与待排序序列的最后一个数据A[n-1]交换;

      2.把剩下的n-1个元素重新建立最大堆,把堆顶元素A[0]与待排序序列的最后一个元素A[n-2]交换;

      3.把剩下的n-2个元素重新建立最大堆,把堆顶元素A[0]与待排序序列的最后一个元素A[n-3]交换;

      重复以上步骤,直到把最后两个元素建成最大堆并进行交换,得到的序列就是排序后的有序序列。

     

     堆排序是不稳定的排序算法,时间复杂度为:O(NlogN).

     Java实现:

    package sort;
    public class  HeapSort{
        public static void main(String[] args) 
        {
            new HeapSort().run();
        }
        public void run(){
             int [] a={17,8,45,84,2,94};
            int len=a.length;  
            /**
             * 循环建堆  
             */
            for(int i=0;i<len-1;i++){  
                /**
                 * 建堆,建一次最大堆,寻到一个待排序序列的最大数  
                 */
                buildMaxHeap(a,len-1-i);  
                /**
                 * 交换堆顶(待排序序列最大数)和最后一个元素  
                 */
                swap(a,0,len-1-i);  
            }  
            
            for(int j=0;j<len;j++){
                System.out.print(a[j]+" ");
            }
        }
        /**
         * 对数组 从0到lastIndex建大顶堆
         */
        public void buildMaxHeap(int[] arr, int lastIndex){
             /**
              * 从最后一个节点(lastIndex)的父节点开始 
              */
            for(int i=(lastIndex-1)/2;i>=0;i--){
                /**
                 * k保存正在判断的节点 
                 */
                int k=i;
                /**
                 * 如果当前k节点的子节点存在  
                 */
                while(k*2+1<=lastIndex){
                    /**
                     * k节点的左子节点的索引 
                     */
                    int biggerIndex=2*k+1;
                    /**
                     * 如果k节点的左子节点biggerIndex小于lastIndex,即biggerIndex+1代表的k节点的右子节点存在
                     */
                    if(biggerIndex<lastIndex){  
                        /**
                         * 若果右子节点的值较大  
                         */
                        if(arr[biggerIndex]<arr[biggerIndex+1]){  
                            /**
                             * biggerIndex总是记录较大子节点的索引  
                             */
                            biggerIndex++;  
                        }  
                    }  
                    /**
                     * 如果k节点的值小于其较大的子节点的值 ,交换他们
                     */
                    if(arr[k]<arr[biggerIndex]){  
                        swap(arr,k,biggerIndex);  
                        /**
                         * 将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值  
                         */
                        k=biggerIndex;  
                    }else{
                        /**
                         * 当前判断结点k(父结点),大于他的两个子节点时,跳出while循环
                         */
                        break;  
                    }  
                }
            }
        }
        /**
         * 交换下标为i、j的两个元素
         */
        private void swap(int[] data, int i, int j) {  
            int tmp=data[i];  
            data[i]=data[j];  
            data[j]=tmp;  
        } 
    }

     结果展示:

      (本文仅供学习交流,如有更好的思路,欢迎留下意见供大家探讨学习~) 

  • 相关阅读:
    Java基础之单元测试与包装类
    Java基础之多态性
    Java基础之继承性与super
    Java 基础之方法的重写
    LeetCode 【困难】数据库-第579:查询员工的累计薪水
    LeetCode 【困难】数据库-第618:学生地理信息报告(分组行列转换)
    python 合并指定的excel表中的sheet中的行。 去重,留唯一
    LeetCode 【困难】数据库-第569:员工薪水中位数
    LeetCode 【困难】数据库-第571:给定数字的频率查询中位数
    LeetCode 【困难】数据库-第185:部门工资前三高的所有员工
  • 原文地址:https://www.cnblogs.com/snowcan/p/6595813.html
Copyright © 2020-2023  润新知