自学内容网 自学内容网

排序算法(归并排序、快速排序)

给你n个乱序的整数,让你将它们按照从小到大的顺序排列,这个问题看起来很简单,今天我来介绍几种非常著名的排序算法

归并排序

归并排序是经典的分治思想,要一下子完成n个数的排序不容易,可以把它从中间分割开,分别对左半部分和由半部分的数字排序,然后将两个有序的数组合并起来就得到最终的有序数组

同理,如果左右部分还是很长怎么办?继续分,直到只有一个数的时候,这个局部数组是有序的直接返回

伪代码

归并排序思想的伪代码如下:

递归函数:

如果当前只有一个元素,返回

递归排序左半部分

递归排序右半部分

合并两边的数组

假设有一组样例     7,2,4,5,1,8

依照归并排序的思想可以将数组作以下划分

当数组递归到只有一个元素返回后,它的上一层递归就可以将两个有序数组合并,然后继续返回到上一次,以此合并两个有序数组并返回的过程如下图:

 代码

//归并排序
public class MergerSort {
    int[] b;
    public MergerSort(int[] b) {
        //初始化中间数组
        this.b = b;
    }
    public void sort(int[] a,int left,int right) {
        //只有一个元素不用排序
        if(left==right) {
            return;
        }
        //大于1个元素
        int mid=(left+right)/2;
        //分治策略,将数组分成两半分别排序
        sort(a,left,mid);
        sort(a,mid+1,right);

        //左右两部分都排序完毕,将它们合并
        //左半部分数组的下标
        int l_index=left;
        //右半部分数组的下标
        int r_index=mid+1;
        //中间数组b的下标
        int index=left;
        //将两个有序数组合并到一起,直到一个数组为空
        while(l_index<=mid&&r_index<=right) {
            if(a[l_index]<a[r_index]) {
                b[index]=a[l_index];
                l_index++;
            }else{
                b[index]=a[r_index];
                r_index++;
            }
            index++;
        }
        //剩下的数组是有序的直接插入到数组b的后面即可
        while(l_index<=mid){
            b[index++]=a[l_index++];
        }
        while(r_index<=right){
            b[index++]=a[r_index++];
        }

        //将有序的数组复制到原数组中
        for(int i=left;i<=right;i++){
            a[i]=b[i];
        }
    }
}

快速排序

快速排序和归并排序很像,也是利用分治的思想,快速排序每次从数组中选一个数当作中间值,把小于这个中间值的数组放到数组的左边,把大于这个数的值放到数组的右边,然后递归调用自己分别对左半部分和右半部分执行如上操作

中间值的选取

只是说了要选一个中间值,那么到底该选数组中的哪个数作为中间值呢?

常用的就是选择数组中的第一个数当作中间值,不过在极端情况下时间复杂度会退化到n方。

也可以随机选取数组中的一个数当作中间值

还有一种,就是比较左右两端和中间的数字,选介于中间的那个数当作中间值

这里我就用第一种,选择数组中的第一个数当作中间值

伪代码

快速排序:

如果当前只有一个元素,返回

设置两个指针变量(i,j)分别指向数组头和尾
选择第一个数当作中间值 pivot
while(i<j){
    从后往前找到第一个小于pivot的
    从前往后找到第一个大于pivot的
    如果i<j,交换这两个数
}

将下标j对应的数和数组第一个数交换

递归对左半部分数组做同样操作
递归对右半部分数组做同样操作

代码

public class QuickSort {

    public void sort(int[] a,int low,int high) {

        if(low>=high) {
            return;
        }
        int partition = partition(a, low, high);

        sort(a,low,partition-1);
        sort(a,partition+1,high);
    }

    //选第一个元素当标准,并划分左右两部分数组
    public int partition(int[] a,int low,int high) {

        int pivot = a[low];
        int i = low;
        int j = high;
        while(i<j) {
            while(i<j&&a[j]>=pivot) j--;
            while(i<j&&a[i]<=pivot) i++;
            //交换
            if(i<j){
                int temp = a[i];
                a[i] = a[j];
                a[j] = temp;
            }
        }
        //将数组中第一个元素即中间值和下标j对应的元素交换
        a[low] = a[j];
        a[j] = pivot;
        return j;
    }
}

 


原文地址:https://blog.csdn.net/weixin_74141526/article/details/145042419

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!