快排的递归实现和非递归实现、归并排序、堆排序(java)

  • 这三种排序算法平均时间复杂度都是O(n*log(n))。
  • 其中快排和堆排序是不稳定,归并排序是稳定的。

快排递归版本

  • 快排是我们必须要掌握的排序算法之一,面试也是常问的考点。快排的思想时采用双指针和选取key不断地去交替值,达到👈为小于key的值;👉为大于key的值。这样说很抽象,直接上代码了。
  • 本方法写的还有点小优化,比传统快排的值的替换的次数少。
import java.util.Arrays;

/**
 * @author: linjianshan
 * @date: 2020/8/15
 * @description: top.san.java.algorithm.sort
 * @version: 1.0
 * 快速排序
 */
public class QuickSort {
    static int[] sq = new int[]{10, 56, 32, 564, 86, 325, 45, 69, 32, 5, 6, 3, 4, 45, 41, 414, 141, 415, 145, 5414, 848471, 8, 191, 9, 191, 656156};

    public static void main(String[] args) {
        new QuickSort().quickSort(sq, 0, sq.length - 1);
        System.out.println(Arrays.toString(sq));
    }

    public void quickSort(int[] arr, int left, int right) {
        int l = left;
        int r = right;
        int mid = arr[(l + r)/2];

        while (l < r){
            while (arr[l] < mid){
                l += 1;
            }
            while (arr[r] > mid){
                r -= 1;
            }
            //l >=r 表示已排好序了
            if (l >= r){
                break;
            }

            int temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;

            //arr[l]则表明右边排好了,到达了mid这个结点,才会把mid换给左边
            if (arr[l] == mid){
                r -= 1;
            }
            //相反
            if (arr[r] == mid){
                l += 1;
            }
        }
        //不加会递归出不去。
        if (l == r){
            l += 1;
            r -= 1;
        }
        if (left < r){
            quickSort(arr,left,r);
        }
        if (l < right){
            quickSort(arr,l,right);
        }
    }
}

快排非递归版本

  • 基于递归版本推出的非递归版本,因为递归都是使用栈来实现的,我直接使用栈来存取中间变化的量,即可实现非递归版本。
import java.util.Arrays;
import java.util.Stack;

/**
 * @author: linjianshan
 * @date: 2020/8/19
 * @description: top.san.java.algorithm.sort
 * @version: 1.0
 */
public class QuickSort0819 {
    static int[] sq = new int[]{10, 56, 32, 564, 86, 325, 45, 69, 32, 5, 6, 3, 4, 45, 41, 414, 141, 415, 145, 5414, 848471, 8, 191, 9, 191, 656156};

    public static void main(String[] args) {

        Stack stack = new Stack();
        stack.push(0);
        stack.push(sq.length-1);
        quickSort0819(sq,stack);
        System.out.println(Arrays.toString(sq));

    }
    public static void quickSort0819(int[] arr, Stack stack){

        while (!stack.empty()){
            int right = (int) stack.pop();
            int r = right;
            int left = (int) stack.pop();
            int l = left;
            int midValue = arr[(l+r)/2];
            while (l < r){
                while (arr[l] < midValue){
                    l++;
                }
                while (arr[r] > midValue){
                    r--;
                }
                if (l >= r){
                    break;
                }
                int temp = arr[l];
                arr[l] = arr[r];
                arr[r] = temp;
                if (arr[l] == midValue){
                    r--;
                }else if (arr[r] == midValue){
                    l++;
                }
            }
            if (l == r){
                l++;
                r--;
            }
            if (left < r){
                stack.push(left);
                stack.push(r);
            }
            if (l < right){
                stack.push(l);
                stack.push(right);
            }
        }
    }
}

归并排序

归并排序主要是利用分治的思想,先逻辑上将排列数拆成当个,再不断地合并成一个数列,且得到的数列是不断的排序得到的有序序列。

import java.util.Arrays;

/**
 * @author: linjianshan
 * @date: 2020/8/17
 * @description: top.san.java.algorithm.sort
 * @version: 1.0
 * 分治思想
 */
public class MergetSort0817 {
    static int[] sq = new int[]{10, 56, 32, 564, 86, 325, 45, 69, 32, 5, 6, 3, 4, 45, 41, 414, 141, 415, 145, 5414, 848471, 8, 191, 9, 191, 656156};

    public static void main(String[] args) {
        int[] temp = new int[sq.length];
        mergetSort(sq, 0, sq.length - 1, temp);
        System.out.println(Arrays.toString(sq));
    }

    public static void mergetSort(int[] arr, int left, int right, int[] temp) {
        if (left < right) {
            int mid = (left + right) / 2;
            //向左分
            mergetSort(arr, left, mid, temp);
            //向右分
            mergetSort(arr, mid + 1, right, temp);
            //从被分到的最小快开始合并
            merget(arr, left, mid, right, temp);
        }
    }

    public static void merget(int[] arr, int left, int mid, int right, int[] temp) {
        int ls = left; //块的左边开始
        int rs = mid+1; //快的右边开始
        int t = 0; //记录数组的起始结点
        //遍历寻找某块左右两边的最小值首先放入temp
        while (ls <= mid && rs <= right) {
            if (arr[ls] < arr[rs]) {
                temp[t++] = arr[ls++];
            } else {
                temp[t++] = arr[rs++];
            }
        }
        //某一块的左右两边某一边遍历完,说明另一边剩下的全是有序的,且比较大  左边
        while (ls <= mid) {
            temp[t++] = arr[ls++];
        }
        //某一块的左右两边某一边遍历完,说明另一边剩下的全是有序的,且比较大  右边
        while (rs <= right) {
            temp[t++] = arr[rs++];
        }

        //将记录再temp的有序序列赋值回传入的块当中
        ls = left;
        t = 0;
        while (ls <= right) {
            arr[ls++] = temp[t++];
        }
    }
}

堆排序

  • 堆排序是数组序列借助了树的思想去排列,其中大顶堆满足arr[i] >arr[2i+1]&&arr[i] > arr[2i+2]。
package top.san.java.algorithm.sort;

import java.util.Arrays;

/**
 * @author: linjianshan
 * @date: 2020/8/18
 * @description: top.san.java.algorithm.sort
 * @version: 1.0
 */
public class HeapSort0818 {
    static int[] sq = new int[]{10, 56, 32, 564, 86, 325, 45, 69, 32, 5, 6, 3, 4, 45, 41, 414, 141, 415, 145, 5414, 848471, 8, 191, 9, 191, 656156};

    public static void main(String[] args) {
        heapSort0818(sq);
        System.out.println(Arrays.toString(sq));
    }

    public static void heapSort0818(int[] arr) {
        for (int i = arr.length / 2 - 1; i >= 0; i--) {
            adjustHeap0818(arr, i, arr.length);
        }
        for (int j = arr.length - 1; j >= 0; j--) {
            int temp = arr[0];
            arr[0] = arr[j];
            arr[j] = temp;
            adjustHeap0818(arr, 0, j);
        }
    }
    //大顶堆的建立
    public static void adjustHeap0818(int[] arr, int start, int end) {
        int temp = arr[start];
        for (int k = start * 2 + 1; k < end; k = k * 2 + 1) {
            //<1>这里逻辑arr[k] < arr[k + 1]改arr[k] > arr[k + 1]
            if (k + 1 < end && arr[k] < arr[k + 1]) {
                k++;
            }
            //<2>这里逻辑arr[k] < temp改arr[k] < temp ,结合<1>可以构建小顶堆
            if (arr[k] > temp) {
                //先让大的上去,k的位置不用赋值,因为下面start指针的位移和arr[k] > temp的判断已经决定了arr[k]逻辑上是arr[start]
                arr[start] = arr[k]; 
                start = k;
            }
        }
        arr[start] = temp;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值