Java教程

数据结构与算法---17.堆排序

本文主要是介绍数据结构与算法---17.堆排序,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

堆排序基本介绍

1) 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序(不能保证相同的两个数的位置和原来一样)。

2) 堆是具有以下性质的完全二叉树(叶子节点只出现在最后一层或倒数第二层):每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆, 注意 : 没有要求结点的左孩子的值和右孩子的值的大小关系。

3) 每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆

4) 大顶堆举例说明

 

 6) 一般升序采用大顶堆,降序采用小顶堆

堆排序基本思想:

1) 将待排序序列构造成一个大顶堆

2) 此时,整个序列的最大值就是堆顶的根节点。

3) 将其与末尾元素进行交换,此时末尾就为最大值。

4) 然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。

 

 

 

 

 

 

 

代码实现: 

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

public class HeapSort {
    public static void main(String[] args) {
        //要求将数组升序排列
        int[] arr={3,7,5,2,6,4,1,9,8};

        System.out.println("排序前");
        String date1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        System.out.println(date1);

        //堆排序
        heapSort(arr);

        System.out.println("排序后");
        String date2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        System.out.println(date2);

//        System.out.println(Arrays.toString(arr));
    }

    //编写一个升序排列的方法
    public static void heapSort(int[] arr){

        int temp=0;

        //将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆
        for (int i= arr.length/2-1;i>=0;i--){
            adjustHeap(arr,i, arr.length);
        }

        //将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
        //重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
        for (int j= arr.length-1;j>0;j--){
            //交换
            temp=arr[j];
            arr[j]=arr[0];
            arr[0]=temp;

            adjustHeap(arr,0,j);
        }
    }

    //将一个数组(二叉树),调整成为一个大顶堆

    /**
     *
     * @param arr 待调整的数组
     * @param i 表示非叶子节点在数组中索引
     * @param length 表示对多少个元素继续调整,length是在逐渐减少
     */
    public static void adjustHeap(int arr[],int i,int length){

        int temp=arr[i];

        for (int k = i*2+1; k < length; k=k* 2+1) {

            if (k+1<length&&arr[k]<arr[k+1]){
                //说明左子节点的值小于右子节点的值
                k++;//k指向右子结点
            }

            if (arr[k]>temp){//如果子结点大于父结点

                arr[i]=arr[k];//把较大的值赋给当前结点
                arr[k]=temp;//将temp值放到调整后的位置
                i=k;//!!!i指向k,继续循环比较
            }else {
                break;
            }
        }
    }
}

这篇关于数据结构与算法---17.堆排序的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!