排序算法(下)

归并排序

归并排序是将两个较小的有序数组归并为一个较大的有序数组。将一个数组排序,可以先将该数组分成两半,将这两半分别排序,最后将两个有序的子序列归并。根据这种思想,人们发明了一种简单的递归排序算法,归并排序。
归并排序的步骤可以用下图的一个例子进行说明:
这里写图片描述
首先利用分割的方法将带排序的序列分割成一个个的子序列,直到每个子序列只剩一个元素(有序),再对每个子序列进行合并。具体的实现代码如下:

/*
     * 归并排序
     */
    public static void mergeSort(int[] A){
        sort(A,0,A.length - 1);
    }

    /*
     * 排序
     */
    private static void sort(int[] A,int lo,int hi){
        if(hi <= lo)
            return;
        int mid = lo + (hi - lo) / 2;  //防止溢出
        sort(A, lo, mid);   //将左半边排序
        sort(A, mid + 1, hi);   //将右半边排序
        merge(A,lo,mid,hi); //归并结果
    }
    /*
     * 原地归并
     */
    private static void merge(int[] a, int lo, int mid, int hi) {
        //将两个数组归并
        int i = lo,j = mid + 1;
        int[] aux = new int[hi + 1];
        for (int k = lo; k <= hi; k++) {//将原来的数组复制到辅助数组中
            aux[k] = a[k];
        }
        for(int k = lo;k <= hi;k++){//归并
            if(i > mid) //左边元素用尽
                a[k] = aux[j++];
            else if(j > hi) //右边元素用尽
                a[k] = aux[i++];
            else if(aux[i] > aux[j])    //右半边元素小于左半边元素,取右半边
                a[k] = aux[j++];
            else                        //左半边元素小于右半边元素,取左半边
                a[k] = aux[i++];
        }
    }

归并排序的特点如下:
1、归并排序是一种渐进最优的基于比较排序的算法,其时间复杂度为n*lgn;
2、归并排序算法的空间复杂度与元素个数成正比;
3、归并排序算法是稳定的;
4、归并排序算法对输入的初始次序不敏感。

快速排序

快速排序是应用最广泛的的排序算法,采用递归调用对元素进行排序,是基于比较排序算法的一个著名算法。主要思想如下:

算法由以下步骤组成:
1、如果数组中只有一个元素或者没有元素则返回;
2、选择数组中的一个元素作为枢轴点;
3.将数组分为两部分,一部分大于枢轴点,一部分小于枢轴点;
4、对两部分数组递归调用该方法。
这里写图片描述

算法实现代码如下:

public class Quicksort {

    public static void quickSort(int[] A){
        sort(A,0,A.length - 1);
    }

    private static void sort(int[] A,int lo,int hi){
        if(hi <= lo)    //只有一个元素或者数组为空,则直接返回
            return;
        int pivot = partition(A,lo,hi);//切分数组
        sort(A,lo,pivot - 1);//对左半部分排序
        sort(A,pivot+1,hi);//对右半部分排序
    }
    /*
     * 对数组进行切分
     */
    private static int partition(int[] a, int lo, int hi) {
        int left = lo,right = hi+1;
        int pivot = a[lo];//选择第一个元素为基准进行切分
        while(left < right){
            while(a[++left] <= pivot){
                if(left == hi)
                    break;
            }
            while(a[--right] >= pivot)
                if(right == lo)
                    break;
            if(left < right)
                swap(a,left,right); 
        }
        swap(a,lo,right);
        return right;
    }
    /*
     * 交换
     */
    private static void swap(int[] A,int i, int j) {
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }

测试代码如下:

public static void main(String[] args) {
        int[] A = {4,8,5,3,6,3,7,29,10,11};
        for (int i = 0; i < A.length; i++) {
            System.out.print(A[i] + "   ");
        }
        System.out.println();
        System.out.println("=========================================");
        quickSort(A);
        for (int i = 0; i < A.length; i++) {
            System.out.print(A[i] + "   ");
        }
    }

快速排序的特点:
1、快速排序在平均情况或者最好情况下,时间复杂度均为O(N*lgN),最坏情况下的时间复杂度为O(n*n)。
2、快速排序实现简单,适用于各种不同的输入数据,在一般应用中比其他算法快得多;
3、快速排序算法非常脆弱,在实现是要非常小心才能避免低劣的性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值