八大排序算法 —— 堆排序

堆排序

堆的概念:
堆:本质是一种数组对象。特别重要的一点性质:任意的叶子节点小于(或大于)它所有的父节点。对此,又分为大顶堆和小顶堆,大顶堆要求节点的元素都要大于其孩子,小顶堆要求节点元素都小于其左右孩子,两者对左右孩子的大小关系不做任何要求。利用堆排序,就是基于大顶堆或者小顶堆的一种排序方法。下面,我们通过大顶堆来实现。

堆排序:
堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。
(1)用大根堆排序的基本思想:

① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区 
② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新
的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key 
③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次
同样要将R[1..n-2]调整为堆。 

图解:
初始化数据

初始化数据

这里写图片描述

构建大顶堆的过程

堆排序的时间复杂度是O(nLog2n) ,空间复杂度是O(1)。由于在构建堆得时候使得仙童大小的元素可能出现顺序颠倒的情况,所以堆排序也是一个不稳定的排序方法。

算法代码实现 :

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int []data  = new int[8];
        for(int i= 0;i<data.length ;i++){
            data[i] = sc.nextInt();
        }
        //堆排序
        Main main = new Main();
        data = main.heapSort(data);

        for(int i = 0;i<data.length ;i++){
            System.out.print(data[i]+" ");
        }
    }
    /*堆排序建队算法*/
    public int[] filterHeap(int data[],int root,int upper){
        /*heap为待筛选的堆,root为堆的根结点,upper为无序区的上界*/
        int child; //指向孩子结点
        int item;   //作为过渡变量
        int r=root;    //r指向根结点
        child=2*root+1;  //初始时为根结点的左孩子
        while(child<upper){
            /*比较左右孩子的关键字值,并取大者*/
            if(child+1<upper && data[child+1]> data[child]){
                child=child+1;
            }
            /*若根结点不满足堆的条件,则与孩子交换*/
            if(data[r]<data[child]){
                item=data[r];
                data[r]=data[child];
                data[child]=item;
                r=child;
                child=2*child+1;  //使child>=upper,满足退出的条件
            }else break;   //若根满足堆的条件,则不交换,并退出筛选
        }
        return data;
    }

    public int[] heapSort(int[] data){
        /*heap为待排序序列,n为序列长度*/
        int i;
        int item;//过渡变量
        int n = data.length;
        for(i=(n-1)/2;i>=0;i--){  //从第一个非叶子结点开始创建初始堆
            filterHeap(data,i,n);
        }

        for(i=n-1;i>0;i--){  //做n-1趟排序,每次堆的大小减1
            /*将堆顶元素与当前大根堆的最后一个元素交换*/
            item=data[0];
            data[0]=data[i];
             data[i]=item;

            /*筛选,将0~i的元素重新调整*/
            filterHeap(data,0,i);
        }
        return data;
    }
}

猜你喜欢

转载自blog.csdn.net/cqx13763055264/article/details/81674408