算法基础篇:排序(二)

改进排序算法及其Java实现

前言

       上节讲了经典的三个排序算法,这节将对改进的排序算法进行分析,有快速排序和归并排序。对于排序和数据结构,推荐一个很棒的网站,支持能动态的看排序过程,可以单步,调节快慢:学习利器

快速排序

       快速排序(Quicksort)是对冒泡排序的一种改进。

       快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。快速排序对海量数据来说,相对其他排序方式是较快的, 他的时间复杂度比经典排序小且常系数也比较小才称为快速排序。以数组{49,38,65,97,76,13,27,49}为例,选择第一个元素49为基准,初始化关键字: [49,38,65,97,76,13,27,49]

                              

算法思想

       首先随机选择数列中的一个数(可用随机数产生,但也可以就选第一个数),然后进行一个partition函数,他的思想是扫描一遍数列把大于这个基数的数都放在右边,小于这个基数的数都放在左边。最后利用分治的思想,对基数的右边和左边分别在进行这个partition操作,最后数列就有序了。我这里为了代码尽量简洁,写出以下代码。

算法实现

//快速排序,s代表数列,l是数列第一项索引,r是数列最后一项的索引
public static void quicksort(int[] s,int l,int r){
//用i,j接住首位和末位,后面分别代表小于区间和??等于区间。x代表基数,这里用首位代表基数,没有随机产生
    int i=l,j=r,x=s[l];
    //执行操作条件
    if(l<r){
        //循环结束条件
        while(i<j){
            //从右至左找小于基数的数
            while(i<j&&s[j]>=x)
                j--;//如果大于等于基数j--,因为它们顺序正确
             //找到之后放在左边,此处精妙的使用i++
            if(i<j)
                s[i++]=s[j];
            //从左至右找大于等于基数的数
            while(i<j&&s[i]<x)
                i++;
            //放在
            if(i<j)
                s[j--]=s[i];
        }
        //最后把基数放在i位置上,完成了partition操作
        s[i]=x;
        //对数列左边和右边分别递归
        quicksort(s,l,i-1);
        quicksort(s,i+1,r);
    }
}

归并排序

算法思想

       基本原理如下:对于给定的一组记录,利用递归与分治技术将数据序列划分成为越来越小的半子表,在对半子表排序,最后再用递归方法将排好序的半子表合并成为越来越大的有序序列。 经过第一轮比较后得到最小的记录,然后将该记录的位置与第一个记录的位置交换;接着对不包括第一个记录以外的其他记录进行第二次比较,得到最小记录并与第二个位置记录交换;重复该过程,直到进行比较的记录只剩下一个为止。

      以数组{50,10,90,30,70,40,80,60,20}为例,排序过程如下图:

算法实现

public static void merge(int[] a, int low, int mid, int high) {
    int[] temp = new int[high - low + 1];
    int i = low;// 左指针
    int j = mid + 1;// 右指针
    int k = 0;
    // 把较小的数先移到新数组中
    while (i <= mid && j <= high) {
        if (a[i] < a[j]) {
            temp[k++] = a[i++];
        } else {
            temp[k++] = a[j++];
        }
    }
    // 把左边剩余的数移入数组
    while (i <= mid) {
        temp[k++] = a[i++];
    }
    // 把右边边剩余的数移入数组
    while (j <= high) {
        temp[k++] = a[j++];
    }
    // 把新数组中的数覆盖nums数组
    for (int k2 = 0; k2 < temp.length; k2++) {
        a[k2 + low] = temp[k2];
    }
}

public static void mergeSort(int[] a, int low, int high) {
    int mid = (low + high) / 2;
    if (low < high) {
        // 左边
        mergeSort(a, low, mid);
        // 右边
        mergeSort(a, mid + 1, high);
        // 左右归并
        merge(a, low, mid, high);
        System.out.println(Arrays.toString(a));
    }

}

            

说明

  文中出现的图片,文字描述有些来自互联网,但是出处无法考究,如果侵犯您的相关权益,请联系我,核实后我会马上加上转载说明。谢谢!!!