十大排序算法java实现

因为面试美团的时候,面试官让我写个快排我20分钟都没写出来,后面经高人指点,把十大经典排序算法抄十遍,因此有了这篇博客的出现。

1. 冒泡排序

//平均n2,最好n,最坏n2,空间1,稳定
class Solution {
    public int[] buubleSort(int[] nums) {
        if (nums == null || nums.length == 0) return nums;
        for (int i = 0; i < nums.length; i++) {
            //要-1是因为这里j+1会溢出
            //因为每遍历一次,都能够保证数组最后一个元素是最大,因此j要-i
            for (int j = 0; j < nums.length - i - 1; j++) {
                if (nums[j] > nums[j + 1]) {
                    int temp = nums[j];
                    nums[j] = nums[j + 1];
                    nums[j + 1] = temp;
                }
            }
        }
        return nums;
    }
}

2. 选择排序

//平均n2,最好是n,最差是n2,空间1,不稳定
class Solution {
    public int[] selectionSort(int[] nums) {
        if (nums == null || nums.length == 0) return nums;
        //找最小的
        for (int i = 0; i < nums.length; i++) {
            int minIndex = i;
            for (int j = i; j < nums.length; j++) {
                //有更小的就改变标记
                if (nums[j] < nums[minIndex]) {
                    minIndex = j;
                }
            }
            //交换
            int temp = nums[minIndex];
            nums[minIndex] = nums[i];
            nums[i] = temp;
        }
        return nums;
    }
}

3. 插入排序

//平均n2,最好n,最坏n2,空间1,稳定
//从未排序中依次选择插入
class Solution {
    public int[] insertionSort(int[] nums) {
        if (nums == null || nums.length == 0) return nums;
        for (int i = 0; i < nums.length - 1; i++) {
            int current = i;
            int base  = nums[i + 1];
            while (current >= 0 && nums[current] > base) {
                nums[current + 1] = nums[current];
                current--;
            }
            nums[current + 1] = base;
        }
        return nums;
    }
}

4. 希尔排序

//平均nlog2n,最好nlog2n,最坏nlog2n,空间1,不稳定
class Solution {
    public int[] shellSort(int[] nums) {
        if (nums == null || nums.length == 0) return nums;
        int gap = nums.length / 2;
        while (gap > 0) {
            for (int i = gap; i < nums.length; i++) {
                int temp = nums[i];
                int sorted = i - gap;
                //分组进行插入排序
                while (sorted >= 0 && nums[sorted] > temp) {
                    nums[sorted + gap] = nums[sorted];
                    sorted -= gap;
                }
                //这里 + gap是因为上面多进行了一次sorted -= gap
                nums[sorted + gap] = temp;
            }
            gap /= 2;
        }
        return nums;
    }
}

5. 归并排序

import java.util.Arrays;

//平均nlogn,最好nlogn,最坏nlogn,空间n,稳定,外排序
//用到了递归思想
class Solution {
    public int[] mergeSort(int[] nums) {
        //如果长度小于2则结束递归拆分
        if (nums.length < 2) return nums;
        //if (nums == null || nums.length == 0) return nums;
        int mid = nums.length / 2;
        //进行拆分
        int[] left = Arrays.copyOfRange(nums, 0, mid);
        int[] right = Arrays.copyOfRange(nums, mid, nums.length);
        return helper(mergeSort(left), mergeSort(right));
    }

    //进行归并
    private int[] helper(int[] left, int[] right) {
        int[] result = new int[left.length + right.length];
        int i = 0, j = 0;
        for (int index = 0; index < result.length; index++) {
            //这里顺序很重要,因为if和elseif只会执行一个,所以先判断是否溢出
            if (i >= left.length) result[index] = right[j++];
            else if (j >= right.length) result[index] = left[i++];
            else if (left[i] > right[j]) result[index] = right[j++];
            else result[index] = left[i++];
        }
        return result;
    }
}

6. 快速排序

//平均nlogn,最好nlogn,最坏n2,空间logn,不稳定
class Solution {
    public int[] fastSort(int[] nums) {
        if (nums == null || nums.length == 0) return nums;
        return helper(nums, 0, nums.length - 1);
    }

    private int[] helper(int[] nums, int low, int high) {
        //if (nums.length <= 2) return nums;
        int base = nums[low];
        int i = low, j = high;
        while (i < j) {
            while (i < j && base <= nums[j]) j--;
            while (i < j && base >= nums[i]) i++;
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
        nums[low] = nums[j];
        nums[j] = base;
        if (i - low > 1) helper(nums, low, i);
        if (high - j > 2) helper(nums, j + 1, high);
        return nums;
    }
}

7. 堆排序

//平均nlogn,最好nlogn,最坏nlogn,空间1,不稳定
class Solution {
    int len;

    public int[] sortArray(int[] nums) {
        len = nums.length;
        if (len < 1) return nums;
        //构建一个最大堆
        buildMaxHeap(nums);
        //循环将堆首位(最大值)与末位交换,然后在重新调整最大堆
        while (len > 0) {
            swap(nums, 0, len - 1);
            len--;
            //调整成为最大堆
            adjustHeap(nums, 0);
        }
        return nums;
    }

    private void adjustHeap(int[] nums, int i) {
        int maxIndex = i;
        //如果有左子树,且左子树大于父节点,则将最大指针指向左子树
        if (i * 2 + 1 < len && nums[i * 2 + 1] > nums[maxIndex])
            maxIndex = i * 2 + 1;
        //如果有右子树,且右子树大于父节点,则将最大指针指向右子树
        if (i * 2 + 2 < len && nums[i * 2 + 2] > nums[maxIndex])
            maxIndex = i * 2 + 2;
        //如果父节点不是最大值,则将父节点与最大值交换,并且递归调整与父节点交换的位置。
        if (maxIndex != i) {
            swap(nums, maxIndex, i);
            adjustHeap(nums, maxIndex);
        }
    }

    private void buildMaxHeap(int[] nums) {
        //从最后一个非叶子节点开始向上构造最大堆
        for (int i = (len/2 - 1); i >= 0; i--) { 
            adjustHeap(nums, i);
        }
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

8. 计数排序

import java.util.Arrays;

//平均n+k,最好n+k,最坏n+k,空间k,外排序,稳定
class Solution {
    public int[] sortArray(int[] nums) {
        if (nums.length == 0) return nums;
        int bias, min = nums[0],max = nums[0];
        //标记最大和最小的元素
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] > max) max = nums[i];
            if (nums[i] < min) min = nums[i];
        }
        bias = 0 - min;
        int[] bucket = new int[max - min + 1];
        Arrays.fill(bucket, 0);
        //统计数组中各个值出现的次数
        for (int i = 0; i < nums.length; i++) {
            bucket[nums[i] + bias]++;
        }
        int index = 0, i = 0;
        //进行反填充
        while (index < nums.length) {
            if (bucket[i] != 0) {
                nums[index] = i - bias;
                bucket[i]--;
                index++;
            } else {
                i++;
            }
        }
        return nums;

    }
}

9. 桶排序

import java.util.ArrayList;
import java.util.Collections;
//平均n+k,最好n+k,最差n2,空间n+k,外排序,稳定
/**桶的大小和桶的个数可以这样确定
 * 桶的大小gap,桶的个数k,nums长度len,最小元素min,最大元素max
 * gap = (max - min) / len + 1
 * k = (max - min) /gap + 1
 * 同一个桶中元素相差最多为gap-1
 * 对于nums[i],放入哪个桶的公式为(nums[i] - min) / gap
 * */
class Solution {
    public int[] sortArray(int[] nums) {
        if (nums == null || nums.length < 2) return nums;
        int len = nums.length;
        int max = nums[0], min = nums[0];
        //确认最大最小值
        for (int i = 0; i < len; i++) {
            if (nums[i] < min) min = nums[i];
            if (nums[i] > max) max = nums[i];
        }
        int gap = (max - min) / len + 1; //桶的大小
        int k = (max - min) / gap + 1; //桶的个数
        ArrayList<ArrayList<Integer>> bucketList = new ArrayList<>(k);
        //ArrayList<Integer> result = new ArrayList<>();
        //创建桶链表
        for (int i = 0; i < k; i++) {
            bucketList.add(new ArrayList<Integer>());
        }
        //遍历nums元素,加入桶链表中
        for (int i = 0; i < len; i++) {
            //先get要加入的桶的位置,再add
            bucketList.get((nums[i] - min) / gap).add(nums[i]);
        }
        //对桶中元素进行排序
        for (int i = 0; i < k; i++) {
            Collections.sort(bucketList.get(i));
        }
        int j = 0;
        for (int i = 0; i < len; i++) {
            int index = 0;
            while (bucketList.get(j).get(index) != null) {
                nums[i] = bucketList.get(j).get(index);
            }
            j++;
        }
        return nums;
    }
}

10. 基数排序

import java.util.ArrayList;
//平均n*k,最好n*k,最坏n*k,空间n+k,外排序,稳定
class Solution {
    public int[] sortArray(int[] nums) {
        if (nums == null || nums.length < 2) return nums;
        //算出最大数的位数
        int max = nums[0];
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > max) max = nums[i];
        }
        int maxDigit = 0;
        while (max != 0) {
            max /= 10;
            maxDigit++;
        }
        int mod = 10, div = 1;
        ArrayList<ArrayList<Integer>> bucketList = new ArrayList<ArrayList<Integer>>();
        for (int i = 0; i < 10; i++)
            bucketList.add(new ArrayList<Integer>());
        for (int i = 0; i < maxDigit; i++, mod *= 10, div *= 10) {
            for (int j = 0; j < nums.length; j++) {
                int num = (nums[j] % mod) / div;
                bucketList.get(num).add(nums[j]);
        }
            int index = 0;
            for (int j = 0; j < bucketList.size(); j++) {
                for (int k = 0; k < bucketList.get(j).size(); k++)
                nums[index++] = bucketList.get(j).get(k);
                bucketList.get(j).clear();
        }
    }
    return nums;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值