堆排序-递归实现和非递归实现

递归和非递归的转化--

大部分情况下,递归实现和非递归实现在思路上没有太大的差别,递归实现首先考虑递归结束条件;循环考虑循环变量和单次循环内需要做的事; 

package org.example;

import java.util.Arrays;

public class HeapSort {
    public static void main(String[] args) {
        int[] arr={12,11,10,9,8,7,6,5,4,3,2,1};
        heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void heapSort(int[] arr){
        for (int i = arr.length/2-1; i >=0; i--) {
            adjustHeap1( arr,i,arr.length);
        }
        int temp=0;
        /*
         将其与末尾元素进行交换,此时末尾就为最大值。
         然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。*/
        for (int j=arr.length-1;j>0;j--){
            temp=arr[j];
            arr[j]=arr[0];
            arr[0]=temp;
            adjustHeap1(arr,0,j);
        }

    }
    //非递归实现

    //思路:
    //分别和左右子节点比较,如果左右子节点中有更大的,则交换,然后继续调整被交换的子节点;
    //如果没有发生交换或者没有子节点,则说明堆结构调整完成;

    /*入参:数组,学要调整的堆顶下标,堆长度(堆中最后一个子节点的下标)*/
    static void adjustHeap(int[]arr,int heaphead,int heaplength){
        while(heaphead<heaplength){
            int left=heaphead*2+1;
            int right=heaphead*2+2;
                //右子节点存在时(左子节点也存在)
            if(right<heaplength){
                if(arr[heaphead]<arr[left]&&arr[left]<arr[right]||arr[heaphead]>arr[left]&&arr[left]<arr[right]){
                    int temp=arr[heaphead];
                    arr[heaphead]=arr[right];
                    arr[right]=temp;
                    heaphead=right;
                }else if(arr[heaphead]<arr[left]&&arr[left]>arr[right]){
                    int temp=arr[heaphead];
                    arr[heaphead]=arr[left];
                    arr[left]=temp;
                    heaphead=left;
                }else{
                    break;
                }
                //只存在左子节点
            }else if(left<heaplength){
                if(arr[heaphead]<arr[left]){
                    int temp=arr[heaphead];
                    arr[heaphead]=arr[left];
                    arr[left]=temp;
                }
                break;
                //本身就是叶子节点
            }else{
                break;
            }
        }
    }


    public static void adjustHeap2(int[] arr,int i,int length){
        //第一步把数组 {4,6,8,5,9}调整排序为{4,9,8,5,6}
        //k=i*2+1 是循环对应的左子树元素
        //记录当前要调整的元素
        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++;
            }
            if (arr[k]>temp){
                //交换位置
                arr[i]=arr[k];
                i=k;
            }else{
                break;
            }
        }
        arr[i]=temp;
    }


    //递归实现
    static  void adjustHeap1(int[]arr,int heaphead,int heaplength){
        if(heaphead>=heaplength)
            return;
        int left=heaphead*2+1;
        int right=heaphead*2+2;
        if(left>=heaplength)
            return;
        //右子节点存在时(左子节点也存在)
        if(right<heaplength){
            if(arr[heaphead]<arr[left]&&arr[left]<arr[right]||arr[heaphead]>arr[left]&&arr[left]<arr[right]){
                int temp=arr[heaphead];
                arr[heaphead]=arr[right];
                arr[right]=temp;
                adjustHeap1(arr,right,heaplength);
            }else if(arr[heaphead]<arr[left]&&arr[left]>arr[right]){
                int temp=arr[heaphead];
                arr[heaphead]=arr[left];
                arr[left]=temp;
                adjustHeap1(arr,left,heaplength);
            }else{
                return;
            }
            //只存在左子节点
        }else if(left<heaplength){
            if(arr[heaphead]<arr[left]){
                int temp=arr[heaphead];
                arr[heaphead]=arr[left];
                arr[left]=temp;
            }
            return;
            //本身就是叶子节点
        }
    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值