归并排序和快速排序的JAVA代码实现

文章详细介绍了如何使用JAVA编程语言实现归并排序和快速排序两种经典算法,包括它们的核心思想、时间复杂度分析以及具体的代码实现。归并排序的时间复杂度为O(nlogn),而快速排序在最好情况下时间复杂度也为O(nlogn),但最坏情况下为O(n^2)。

归并排序的JAVA实现

归并排序的核心思想是分治,写成代码就是递归。
递归终止条件是:数组中只有一个元素
时间复杂度是 O ( n l o g n ) O(nlogn) O(nlogn)。个人理解,分解合并的高度一共为 2 l o g n 2logn 2logn。每一层的时间复杂度为n,比如说合并时,合并一排数字时间复杂度为n。与层高相乘就是 n l o g n nlogn nlogn。此处仅仅个人理解,谨慎参考。至于为什么分解合并的高度一共为 2 l o g n 2logn 2logn,参考二分查找的时间复杂度进行理解。
二分查找的时间复杂度分析
图片来自 极客时间 中的专栏 数据结构与算法之美。
图片来自 极客时间 数据结构与算法之美 中

public class Sort {
    public static void main(String[] args) {
        int[] nums = {1, 5, 6, 2, 3, 4};
        merger_sort(nums, 0, nums.length - 1);
        for (int a: nums) {
            System.out.println(a);
        }
    }

    //归并排序
    //merger_sort函数的作用:将数组nums中下标从start到end的元素排序。
    public static void merger_sort(int[] nums, int start, int end) { //左闭右闭
        if (start >= end) { //终止条件,数组中只有一个元素
            return ;
        }
        int mid = (start + end) / 2;
        merger_sort(nums, start, mid);
        merger_sort(nums, mid + 1, end);
        merge(nums, start, mid, end);
    }

    public static void merge (int[] nums, int start, int mid, int end) { //合并
        int[] temp = new int[end - start + 1];
        int i = start;
        int j = mid + 1;
        int k = 0;
        while (i <= mid && j <= end) {
            if (nums[i] < nums[j]) {
                temp[k++] = nums[i];
                i++;
            } else {
                temp[k++] = nums[j];
                j++;
            }
        }
        while (i <= mid) {
            temp[k++] = nums[i++];
        }
        while (j <= end) {
            temp[k++] = nums[j++];
        }
        k = 0;
        i = start;
        for(; i <= end; i++,k++) {
            nums[i] = temp[k];
        }
    }

}

快速排序的JAVA实现

核心思想
每次选择一个数据作为分区点,然后将数组中小于这个数字的元素放到左边,将数组中大于这个数字的元素放到右边。也就是说,每次会将一个元素放到正确的位置,然后同样的处理,排序后,这个元素两边的子数组。
时间复杂度
关于快排时间复杂度的个人理解。每次排序都需要处理n个数字。
当数组有序时,每次支点不能分割数组,所以,一共需要n次找支点的过程。故相乘之后之间复杂度为 O ( n 2 ) O(n^{2}) O(n2)
当数组无序时,最好情况,每次分割可以正好将数组分成两半,所以,一共需要 l o g n logn logn次找支点的过程,故相乘之后的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

public class Sort{
    public static void main(String[] args) {
        int[] nums = {1,3,5,4,2};
        quickSort(nums, 0, nums.length - 1);
        for (int a : nums) {
            System.out.println(a);
        }
    }

    //快速排序
    public static void quickSort(int[] nums, int start, int end) { //左闭右闭
        if (start >= end) { //当数组中只有一个元素的时候终止
            return ;
        }
        int pIndex = findPIndex(nums, start, end);
        quickSort(nums, start, pIndex - 1);
        quickSort(nums, pIndex+1, end);
    }

    //获取分区数组的正确下标
    public static int findPIndex(int[] nums, int start, int end) {
        //选择最后一个数字作为支点 nums[end]
        int left = start;
        int right = end - 1;
        while(left <= right) {
            while (nums[left] < nums[end]) { //找到左边的比该元素数字大的元素
                left ++;
            }
            while (nums[right] >= nums[end]) { //找到右边的比该元素数字小的元素
                right --;
            }
            if (left < right) { //交换刚才找到的两个数字
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
            }
        }
        int temp = nums[left]; //将支点归位,因为left指针指向的是比支点大的元素,所以交换以后,这个元素放到了支点右边是合适的。
        nums[left] = nums[end];
        nums[end] = temp;
        return left;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值