算法——利用递归做堆排序

要想学会堆排序,就要知道什么是堆。

堆,分为大根堆和小根堆,学过数据结构的人都知道二叉树,而堆就类似于数据结构中的完全二叉树
在这里插入图片描述
在这里插入图片描述
如果想要正常排序,我们需要先把这个堆调成大根堆,或者小根堆
大根堆:根节点永远大于叶子节点
小根堆:根节点永远小于叶子节点

那么如何调整这棵二叉树调整成大根堆呢?
在这里插入图片描述
像以上这种调整,便可完成一次大根堆调整,那么如何用代码实现呢 ?
以下是我用递归实现的做一次大根堆调整

 public static void swap(int[]array,int n,int m){
            int temp=array[n];
            array[n]=array[m];
            array[m]=temp;
        }
           public static void heap(int[] array,int start,int end){
            if(start>=end){
                return;
            }
            int c1=2*start+1;
            int c2=2*start+2;
            int max=start;
            if(c1<end&&array[c1]>array[max]){
                max=c1;
            }
            if(c2<end&&array[c2]>array[max]){
                max=c2;
            }
            if(max!=start){
                swap(array,max,start);
                heap(array,max,end);
            }
            }

以上是我进行了一次大根堆调整,如果要进行一整个堆的大根堆调整,则只需要

假设数组的长度是n,那么不难求得它的父节点为 (n-1)/2,然后根据上面堆的特性,我们可以知道,只需从最后一个父节点开始往前遍历,每一个数调整一次即可

  public static void buildHeap(int[] array,int end){
            int n=end-1;
            int parent=(n-1)/2;
            for(int i=parent;i>=0;i--){
                heap(array,i,end);
            }
        }

那么之后如何得到一个正常个顺序的一列数组呢?
当建立好一个大根堆之后
在这里插入图片描述
如上图所示,我们可以确认的是,最上面的根节点一定是最大的,所以首先需要将第一个拿出来,和最后一个节点做交换,然后将最后一个根节点放出来,此时剩下的二叉树就不是一个大根堆了,然后重新进行堆化,再重复以上操作即可,代码实现如下:

public static void HeapSort(int [] array,int length){
            buildHeap(array,length);
            for(int i=length-1;i>=0;i--){//根据数组的长度将数组第一个和最后一个交换
                swap(array,i,0);
                buildHeap(array,i);
            }
        }

以上,一个堆排序就完成了。
完整代码如下:

   public static void swap(int[]array,int n,int m){
            int temp=array[n];
            array[n]=array[m];
            array[m]=temp;
        }
        public static void HeapSort(int [] array,int length){
            buildHeap(array,length);
            for(int i=length-1;i>=0;i--){//根据数组的长度将数组第一个和最后一个交换
                swap(array,i,0);
                buildHeap(array,i);
            }
        }
        public static void buildHeap(int[] array,int end){
            int n=end-1;
            int parent=(n-1)/2;
            for(int i=parent;i>=0;i--){
                heap(array,i,end);
            }
        }
           public static void heap(int[] array,int start,int end){
            if(start>=end){
                return;
            }
            int c1=2*start+1;
            int c2=2*start+2;
            int max=start;
            if(c1<end&&array[c1]>array[max]){
                max=c1;
            }
            if(c2<end&&array[c2]>array[max]){
                max=c2;
            }
            if(max!=start){
                swap(array,max,start);
                heap(array,max,end);//循环做一个往回倒的堆化
            }
       }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值