本文介绍: 学习和介绍归并排序和快速排序

       冒泡排序、插入排序、选择排序这三种排序算法,它们的时间复杂度都是O(n^2),比较高,适合小规模数据的排序。如果数据量大,我们就需要使用到时间复杂度低的排序算法,归并排序快速排序是复杂度为O(nlogn)的排序算法。

1-归并排序(Merge Sort)

       如果要排序一个数组,我们先把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。具体的流程如下:

       从图中,我们看到归并排序实际是用到了分治的思想。将一个大问题分解成小的子问题来解决。小的子问题解决了,大问题也就解决了。

@Slf4j
public class MergeSort {
    public static void main(String[] args) {
        int []arr = {23,18,37,16,45,40,3,28,19};
        sort(arr);
        log.info("排序后的数组:arr={}",arr);

    }
    public static void sort(int []arr){
        int []temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
        sort(arr,0,arr.length-1,temp);
    }

    private static void sort(int[] arr,int left,int right,int []temp){
        if(left<right){
            int mid = (left+right)/2;
            sort(arr,left,mid,temp);//左边归并排序,使得左子序列有序
            sort(arr,mid+1,right,temp);//右边归并排序,使得右子序列有序
            merge(arr,left,mid,right,temp);//将两个有序子数组合并操作
        }
    }
    private static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i = left;//左序列指针
        int j = mid+1;//右序列指针
        int t = 0;//临时数组指针
        while (i<=mid && j<=right){
            if(arr[i]<=arr[j]){
                temp[t++] = arr[i++];
            }else {
                temp[t++] = arr[j++];
            }
        }
        while(i<=mid){//将左边剩余元素填充进temp中
            temp[t++] = arr[i++];
        }
        while(j<=right){//将右序列剩余元素填充进temp中
            temp[t++] = arr[j++];
        }
        t = 0;
        //将temp中的元素全部拷贝到原数组中
        while(left <= right){
            arr[left++] = temp[t++];
        }
    }
}

(1)归并排序是一个稳定的排序算法;
(2)最好情况、最坏情况,还是平均情况,时间复杂度都是O(nlogn);
(3)空间复杂度是O(n)。

2-快速排序

       快速排序算法(Quicksort),我们习惯性把它简称为“快排”。快排利用的也是分治思想。快排的思想是这样的:如果要排序数组中下标从p到r之间的一组数据,我们选择p到r之间的任意一个数据作为pivot(分区点)。

下面的流程就是快排的一个轮回:

快速排序的代码实现:

@Slf4j
public class QuickSort2 {
    public static void main(String[] args) {
        //初始化需要排序的数组
        int array[] = {9, 2, 11, 7, 12, 5};
        //快速排序
        quickSort(array, 0, array.length - 1);
        //打印出排序好的序列
        log.info("排序好的数组,array={}", array);
    }

    //快速排序
    private static void quickSort(int[] array, int low, int high) {
        if (low < high) {
            //找到分区的位置,左边右边分别进行快速排序
            int index = partition(array, low, high);
            quickSort(array, 0, index - 1);
            quickSort(array, index + 1, high);
        }
    }

    //快速排序分区操作
    private static int partition(int[] array, int low, int high) {
        //选择基准
        int pivot = array[low];       
        //当左指针小于右指针时,重复操作
        while (low < high) {
            while (low < high && array[high] >= pivot) {
                high = high - 1;
            }
            array[low] = array[high];
            while (low < high && array[low] <= pivot) {
                low = low + 1;
            }
            array[high] = array[low];
        }
        //最后赋值基准
        array[low] = pivot;       
        //返回基准所在位置,基准位置已经排序好
        return low;
    }
}

      快排是一种原地、不稳定的排序算法。快排的平均时间复杂度是O(nlogn),最好的时间复杂度O(nlogn),最差的时间复杂度是O(n^2)。

原文地址:https://blog.csdn.net/ycmy2017/article/details/134807264

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_51189.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注