【算法】排序算法

参考资料

复习基础排序算法(Java)

快速排序

快速排序是不稳定的
切分算法的要点:

  1. 随机选择一个基准元素,为什么要随机,因为如果数组是有序或者逆序的情况下,会变得非常慢,等同于每次切分只返回第一个元素或者最后一个元素的坐标,这样二分算法就失去了意义了。
import java.util.Random;
class Solution {
    private static final Random RANDOM = new Random();
    public int[] sortArray(int[] nums) {
        quickSort(nums,0,nums.length-1);
        return nums;
    }
    public void quickSort(int[] nums,int start,int end){
        if(start >= end){
            return;
        }
        int k = partition(nums,start,end);
        quickSort(nums,start,k-1);
        quickSort(nums,k+1,end);
    }

    public int partition(int[] nums,int start,int end){
        int randomIndex = RANDOM.nextInt(end - start + 1) + start;
        swap(nums, start, randomIndex);
        int priot = nums[start];
        int index = start;// 循环不变量,保证区间[start,index-1]<priot,[index+1,end]>=priot是成立的
        for(int i= start+1;i<=end;i++){
            if(nums[i]<priot){
                index++;
                swap(nums,i,index);
            }
        }
        swap(nums,start,index);
        return index;
    }

    public void swap(int[] nums,int i, int j){
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

插入排序

插入排序是稳定的。

  • 总体思想:
  1. 将一个新的元素插入到一个有序数组中
  2. 在插入的过程中,需要移动比新的数大的数,所以用一个临时变量将新的数存储起来,后面的数覆盖掉前面的数
  3. 最后在挪出来的新位置放入新的数
  • 插入排序的优势是:
    内循环是可以提前终止的,如果顺序相对有序,或者是小数组,小数组直接的差距不是特别大,可以使用插入排序
    public int[] sort(int[] nums) {
        for (int i = 0; i < nums.length - 1; i++) {
            int j = i + 1; // [0..i]是有序的,[0..j-1] <= tmp
            int tmp = nums[j];
            while (j > 0 && nums[j - 1] > tmp) {
                nums[j] = nums[j - 1];
                j--;
            }
            nums[j]=tmp;
        }
        return nums;
    }

归并排序

归并排序是稳定的

public class MergeSort {
    public void mergeSort(int[] nums) {
        if (nums.length == 0) {
            return;
        }
        int start = 0;
        int end = nums.length - 1;
        sort(start, end, nums);
    }

    private void sort(int start, int end, int[] nums) {
        if (start >= end) {
            return;
        }
        int middle = start + (end - start) / 2;
        sort(start, middle, nums);
        sort(middle + 1, end, nums);
        merge(start, middle, middle + 1, end, nums);
    }
    
    private void merge(int left, int leftEnd, int right, int rightEnd, int[] nums) {
        int k = 0;
        int[] a = new int[rightEnd - left + 1];
        int i = left;
        int j = right;
        while (i <= leftEnd || j <= rightEnd) {
            if (i <= leftEnd && j <= rightEnd) {
                if (nums[i] <= nums[j]) {
                    a[k++] = nums[i++];
                } else {
                    a[k++] = nums[j++];
                }
            } else if (i <= leftEnd) {
                a[k++] = nums[i++];
            } else if (j <= rightEnd) {
                a[k++] = nums[j++];
            }
        }

        for (int l = left; l <= rightEnd; l++) {
            nums[l] = a[l - left];
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值