浅谈大顶堆与堆排序

大顶堆:顾名思义就是任何一个节点的值大于其左右孩子节点,大顶堆的数据是线性存储,假设父节点的坐标是 n ,可以得到左子节点的下标是 2*n+1 ,右节点的下标是 2*n+2,同理,知道任一节点的下标就可以知道其父节点的下标是(n-1)/2,有了上面这个概念我们就可以写出大顶堆的构建思路:

首先创建一个数组

         int[] arr = new int[] {1,2,3,4,5,6,7,8,9,1,3,2,5}; 

然后将数组作为参数传入转换数组

public static void TraverseNodeNotLeave(int arr[],int size) 
    {
        //首先从最后一个非叶子节点开始
        int parents  = (arr.length-2) /2;
        while(parents>=0) {
            changeToHeap(arr,size,parents--);
        }
        
    }
    
    //将数组转成大顶堆
    public static void changeToHeap(int[] arr,int size,int start)
    {
        
        //找到左右两个孩子
        int leftChild = start*2+1;
        int rightChild = start*2+2;
        
        if(leftChild>size || rightChild > size) return;
        
        //然后找到最大的数字
        int max = start;
        if(leftChild<size && arr[max]<arr[leftChild])
        {
            max = leftChild;
        }
        if(rightChild < size && arr[max]<arr[rightChild])
        {
            max = rightChild;
        }
        //发生交换
        if(max != start) {
            int temp = arr[max];
            arr[max] = arr[start];
            arr[start] = temp;
            changeToHeap(arr,size,max);
        }

    }

这样我们就将原来的数组转换成为了大顶堆

堆排序:堆排序的是每一次取出大顶堆的第一个元素,然后将剩下的元素重新向大顶堆转换

代码如下:

public static void HeapSort(int arr[])
    {
        int size = arr.length;
        while(size>0) {
            //转换大顶堆
            TraverseNodeNotLeave(arr,size);
           //取出最大元素
            int temp = arr[0];
            arr[0] = arr[size-1];
            arr[--size] = temp;
        }
        
        
    }            

 

以上就完成到了大顶堆的构建和堆排序工作

 

posted @ 2021-03-10 19:25  二五树  阅读(166)  评论(0编辑  收藏  举报