zoukankan      html  css  js  c++  java
  • 学习堆排序

      首先,看一下堆的定义;

      n个元素的序列{k1,k2,…,kn}当且仅当满足下列关系之一时,称之为堆。

      情形1:k<= k2i 且k<= k2i+1 最小化堆小顶堆

      情形2:k>= k2i 且k>= k2i+1 (化堆大顶堆

      其中i=1,2,…,n/2向下取整;            

          该排序的思想是;首先建立二叉堆,这个阶段花费O(N)时间,然后我们执行N次deleteMin操作。按照顺序,最小的元素先离开堆,通过将这些元素记录到第二数组,最后在将数组拷贝回来,得到N个元素的顺序,由于每个deleteMIn花费时间O(logN), 因此,总的运行时间是O(NlogN). 优先队列,可以用于O(NlogN)时间排序, 基于该思想的算法叫做堆排序。

         该算法的主要问题是使用一个附加的数组,一次存储需求增加一倍,为了回避使用第二个数组的,可以在每次deleteMin之后,堆缩减1,因此,位于堆中左后的单元,可以存储刚刚存放删除的元素。使用这种策略,该数组将以递减的的顺序包含这些元素.

          java代码的例子:

       

    public class HeapSort {
    
        public static void main(String[] args) throws Exception{
            Integer [] a  = new Integer[]{32,12,345,5,66,23};
            heapSort(a);
    
            Arrays.stream(a).forEach(System.out::println);
        }
    
        /**
         * Internal method for heapSort that is used in  deleteMax and buiildHeap
         * @param i the position from which to percolate down
         * @param n the binary size of the binary heap
         */
        public static void percDown(Integer[] a,int i, int n){
            int child;
            int temp;
    
            for(temp= a[i]; leftChild(i) < n; i = child){
                child = leftChild(i);
    
                if(child != n-1  && a[child] < a[child+1])
                    child++;
    
                if(temp < a[child])
                    a[i] = a[child];
                else
                    break;
            }
             a[i] = temp;
        }
    
    
        private static int leftChild(int i){
            return 2 * i + 1;
        }
    
        public static void heapSort(Integer[] a){
    
            /**初始化堆的时候是对所有的非叶子结点进行筛选。
            最后一个非终端元素的下标是[n/2]向下取整,所以筛选只需要从第[n/2]向下取整个元素开始,从后往前进行调整。
             */
            for(int i = a.length/2-1; i>=0; i--){ //buildHeap
                percDown(a,i,a.length);
            }
    
            for(int i=a.length-1; i > 0; i--){
                swapReferences(a,0,i);  //deleteMax
                percDown(a,0,i);
            }
        }
    
        //deleteMax
        public static void swapReferences(Integer[] a, int i, int n){
            Integer temp=a[i];
            a[i] = a[n];
            a[n] = temp;
        }
    
    }

      堆排序方法对记录数较少的文件并不值得提倡,但对n较大的文件还是很有效的。因为其运行时间主要耗费在建初始堆和调整建新堆时进行的反复“筛选”上

      堆排序在最坏的情况下,其时间复杂度也为O(nlogn)。相对于快速排序来说,这是堆排序的最大优点。

      

       

            

      

         

        

             

       

  • 相关阅读:
    20200713 T3 图论
    20200713 T1序列问题
    【题解】P1441 砝码称重
    【题解】P2858 [USACO06FEB]Treats for the Cows G/S
    【比赛】AISing Programming Contest 2019
    20200709 T3 城堡
    20200709 T2 括号
    20200709 T1 笔记
    20200628 T3 网络检查
    个人技术总结
  • 原文地址:https://www.cnblogs.com/xjz1842/p/6097276.html
Copyright © 2011-2022 走看看