基础 | 7大排序算法java总结(下)

6.归并排序
基本思想:

将一个数组分为两块,两块再分两块……最终只需保证两块内数据有序即可
在这里插入图片描述
在这里插入图片描述

  • 代码如下:
public static void mergeSort(int[] arr) {
    for (int i = 1; i < arr.length; i *= 2) {
        merge(arr,i);
    }
}

public static void merge(int[] arr, int gap) {
    int left1 = 0;//第一个归并段的起始位置
    int right1 = left1 + gap - 1;//第一个归并段的终止位置
    int left2 = right1 + 1;//第二个归并段的起始位置
    int right2 = left2 + gap - 1 < arr.length ? left2 + gap - 1 : arr.length - 1;//第二个归并段的终止位置
    int[] brr = new int[arr.length];
    int i = 0;//遍历brr下标

    //有两个归并段 <第二个归并段至少有一个数据>
    while (left2 < arr.length) {
        while (left1 <= right2 && left2<=right2) {
            if(arr[left1] < arr[left2]) {
                brr[i++] = arr[left1++];
            }else{
                brr[i++]=arr[left2++];
            }
        }
        if(left1>right1){
            for(int j=left2;j<=right2;) {
                brr[i++] = arr[j++];
            }
        }
        if(left2>right2){
            for(int j=left1;j<=right1;) {
                brr[i++] = arr[j++];
            }
        }
        left1=right2+1;
        right1=left1+gap-1;
        left2=right1+1;
        right2=left2 + gap - 1 < arr.length ? left2 + gap - 1 : arr.length - 1;
    }
    //只有一个归并段
    for (int j = left1; j < arr.length; ) {
        brr[i++] = arr[j++];
    }
    for(int j=0;j<arr.length;j++){
        arr[j]=brr[j];
    }
}
7.堆排序

知识点补充
一、堆排序是对简单选择排序算法的一种改进;

二、堆是具有以下性质的完全二叉树
1.大顶堆(大根堆):每个节点的值都大于或等于其左右孩子节点的值
2.小顶堆(小根堆):每个节点的值都小于或等于其左右孩子节点的值

基本思想:

1.从倒数第一个非叶子节点开始,将待排序序列调整为大根堆形式

注意: 调整需要保证 该节点的所有分支节点 全部为大根堆形式
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
调整倒数第三个非叶子节点时就需要考虑该节点所有分支节点均为大根堆形式
在这里插入图片描述
2.调整后整个序列的最大值就是堆顶的根节点。将 其与堆数组的末尾元素交换,此时末尾元素就是最大值,然后 将剩余的n-1个数据重新构造成一个堆,得到n个元素中的次小值,如此反复执行,得到一个有序序列。

  • 代码如下:
public static void heapSort(int[] arr) {
    for (int i = arr.length/ 2-1; i >= 0; i--) {
        //将堆调整为大根堆形式
        adjust(arr, i, arr.length);
    }
    //交换0号下标与“相对最后”数据
    for(int j=arr.length-1;j>0;j--){
        int temp = arr[0];
        arr[0] = arr[j];
        arr[j] = temp;
        adjust(arr, 0, j);
    }
}

public static void heapAdjust(int[] arr,int begin,int end){
    //挑选左右孩子最大值
    int temp = arr[begin];
    for (int i = 2 * begin + 1; i < end; i = 2 * i + 1) {
        if (i + 1 < end && arr[i] < arr[i + 1]) {//i保存左右孩子较大值
            i++;
        }
        //较大值与begin位置元素比较->交换
        if (arr[i] <= temp)
            break;
        arr[begin] = arr[i];
        begin = i;
    }
    arr[begin] = temp;
}

总结一下上述堆排序代码:
从代码中可以看出,整个堆排序过程分为 两个for循环
第一个循环:将现在的待排序序列调整为一个大顶堆;
第二个循环:逐步将每个最大的根节点与末尾元素交换,并且再调整为大顶堆。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值