There are doubts about the heap sort? Just five steps to completely get heapsort

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/wangliangluang/article/details/90691037

? There are doubts about the heap sort just five steps, get a thorough heap sort:

Before saying heap sort, you should first clear some concepts:

A concept:

1.完全二叉树:
    a.从作为第一层的跟开始,除了最后一层外,第N层的元素的个数,都必须是2的N次方.
    b.最后一行的元素,必须从左边开始放,且中间不能有空格.
    说明:满足这两个特点的二叉树就是完全二叉树.
2.最大堆:
    在满足完全二叉树的条件下,每个父节点的值都大于其子结点的值,一般最大堆用于升序排序.
3.最小堆:
     在满足完全二叉树的条件下,每个父节点的值都小于其子节点的值,一般最小堆用于降序排序.

The next way to ask questions so that you get to know HEAPSORT:

II. The general idea

After all of the array imagine the number of nodes in the complete binary tree, this complete binary tree to build the biggest pile, looking for an array that is the maximum value, the maximum value to the maximum found on the last, and then the remaining the number of building maximum heap again (to find the second largest value), so can be repeated

III. Specific steps. (A total of five big step)

1. Construction of a binary tree (this step is to understand like, do not need to implement the code):

  • One problem: the need to build a binary tree is really it?

        不需要,在每个数组一确定之后,对应的二叉树就已经构建好了,这个二叉树只是人 们想象出来的,
    便于进行排序思考的模型.只不过这个模型需要遵循一定的规则.
    
  • Second problem: So what rules you need to follow it?

  •   其实就是二叉树中的父节点和子节点在数组中的对应关系.
    规定:父节点如果是第i个,左子节点就是2i+1,右子节点就是2i+2.
    

2. Sort 1 (that is to build the largest heap of the process, why build the largest heap? Because you want to find the maximum value in the array)

    从下往上,从第一个非叶子节点(有子节点)的节点开始,如果该结点大于它的子节点,  则无需交
 换,否则与最大子节点交换.
  • One problem: how to find it in the array corresponds to the first non-leaf node it?

       i=arr.length/2-1,这个i就是,那么这个i前面就一定是非叶子节点,所以寻找下一个非叶子
    结点直接n-1即可.
    
  • Question two: why i = arr.length / 2-1?

  • 这个是根据数学推出来的,我们知道数组中最后一个数一定是最后一个非叶子结点通过2i+1或2i+2算出来的.
         也就是: 2i+1=arr.length-1.
                 2i+2=arr.length-1.
         就是一个中学数学题,求i.发现两个式子都可以求出i=arr.length/2-1.(因为3/2和2/2的结果是一样的,都是1)
    

    * Note: For the whole, is a sort of bottom-up process, and for a single junction point, the sort is a top-down process.
    Example: 936,745,242
    After this exchange 3 and 7, still need to compare down , and 4 still need to exchange.

3. exchange.

   满足最大堆特点之后,其实就是找到了数组中的最大值.而且放在数组的第0位.
   我们现在要做的当然就是把最大值放到最后面去
   (对应二叉树中也就  是把跟结点和最后一行的最右边结点进行交换).**

4. Sort 2.

 这里和排序1稍有区别,因为我们已经排好了最大值,所以不需要最大值参与进来了.
 也就是除了最大值以外,其余所有的数再进行排序,
 构建最大堆.目的就是为了寻找第二个最大值.

The 3 and 4 is then repeated until all of them can be sorted.

Finally, attach the entire program:


/**
 * 堆排序
 */
public class HeapSort {
    public static int[] HeapSort(int[] arr){
        if(arr==null||arr.length<1){
            throw new RuntimeException("Invalid Parament");
        }
        //构建最大堆,for实现从下而上的思路.里面的sort排序实现对单个结点从上而下
        for (int i = arr.length/2-1; i >=0 ; i--) {
            sort(arr,i,arr.length);
        }
        //开始交换,这里是对最后一个点的循环,每次把最大值移至最后,把前面的进行排序,重新构建最大堆
        for (int i = arr.length-1; i >0 ; i--) {
            //交换
            swap(arr,i,0);
            //对除去最大值之外的数组重新按最大堆模型进行排序
            //注意这里排序的范围是逐渐减小的
            sort(arr,0,i);
        }
        return arr;
    }

    /**
     * 进行最大堆的构建,也就是排序
     * @param arr 要排序的数组
     * @param i   从哪一个结点开始比较,排序
     * @param length 排序的范围,也就是排序到哪一个结点的范围
     */
    private static void sort(int[] arr, int i,int length) {
        int max;//指向两个子节点中大的结点
        //比较两个子节点,给出最大值
        //这个循环是对父节点的i的循环.2i+2<=length-1.从而对父节点做出限制.
        for (int node= i; node < length/2-1; ) {
            //这里如果最大值排在最后,i不变,还是会把最大值参与进来,所以要用length进行限制.
            if((2*node+2)<length){
                max=arr[2*node+1]>arr[2*node+2] ? 2*node+1 : 2+node+2;
            }else{
                max=2*node+1;
            }
            //如果父节点小于子节点中的最大值,交换
            if(arr[node]<arr[max]){
                swap(arr,node,max);
                //此时max指向交换后的子结点,需要继续向下比较,所以要让i指向交换后的子节点.
                node=max;
            }else {
                //如果父节点大,直接退出循环
                break;
            }
        }
    }
    private static void swap(int[] arr, int i, int max) {
        int flag=arr[i];
        arr[i]=arr[max];
        arr[max]=flag;
    }
    //测试
    public static void main(String[] args) {
        int[] arr={3,5,2,3,1};
        int[] ints = HeapSort(arr);
        for (int anInt : ints) {
            System.out.println(anInt);
        }
    }
}

Guess you like

Origin blog.csdn.net/wangliangluang/article/details/90691037