希尔排序与快速排序(详细注释)附带csdn代码复制错误的解决方法

(今天意外收获:发现用win10自带浏览器edge在csdn复制代码会出错,换个浏览器就好了)
今天竟然刷到了一道用快排超时而希尔不超时的题!https://pintia.cn/problem-sets/14/problems/743
感觉自己c++的库函数用多了都快忘了快排怎么了,遂写篇博客回顾一下快排,并学习一下之前没看过的希尔排序。
参考博文https://blog.csdn.net/MoreWindows/article/details/6684558
https://blog.csdn.net/morewindows/article/details/6668714
代码和文字参考如上链接的大佬的博文,感觉他讲的非常好,特别是他的对
记住这个流程快排的实现也不难了,这里我写点自己的理解。
一、快速排序
快排的主要思想是:选择一个基准数,将比其小的放到后面去,大的放在前面去,放完后基准数是已经在正确的位置上了,再用分治思想将序列分成两个左右区再快排至区间只有一个数。
快排思想不难理解,难在代码实现与细节。
快速排序代码与详细注释如下

/**
 * 快速排序
 * @param array
 */
public static void quickSort(int[] array) {
    int len;
    if(array == null
            || (len = array.length) == 0
            || len == 1) {
        return ;
    }
    sort(array, 0, len - 1);
}

/**
 * 快排核心算法,递归实现
 * @param array
 * @param left
 * @param right
 */
public static void sort(int[] array, int left, int right) {
    if(left > right) {
        return;
    }
    // base中存放基准数
    int base = array[left];
    int i = left, j = right;
    while(i != j) {
        // 顺序很重要,先从右边开始往左找,直到找到比base值小的数
        while(array[j] >= base && i < j) {
            j--;
        }

        // 再从左往右边找,直到找到比base值大的数
        while(array[i] <= base && i < j) {
            i++;
        }

        // 上面的循环结束表示找到了位置或者(i>=j)了,交换两个数在数组中的位置
        if(i < j) {
            int tmp = array[i];
            array[i] = array[j];
            array[j] = tmp;
        }
    }

    // 将基准数放到中间的位置(基准数归位)
    array[left] = array[i];
    array[i] = base;

    // 递归,继续向基准的左右两边执行和上面同样的操作
    // i的索引处为上面已确定好的基准值的位置,无需再处理
    sort(array, left, i - 1);
    sort(array, i + 1, right);
}

二、希尔排序
讲希尔排序前先回顾一下直接选择排序,思想如下
设数组为a[0…n-1]。
1初始时,a[0]自成1个有序区,无序区为a[1…n-1]。令i=1
2 将a[i]并入当前的有序区a[0…i-1]中形成a[0…i]的有序区间。
3.i++并重复第二步直到i==n-1。排序完成。
这个排序代码实现比较简单了,我觉得只有一个点需要注意就是第三行代码的j=i-1因为每次的起点都不同,一趟至少会排好一个数且在最前面。
选择排序

#include
int main()
{	 int i,j,t,n,a[29];
    printf("请输入总数据个数(小于30):\n");
    scanf("%d",&n);
    for(i=0;ia[j])
            {
                t=a[i];
                a[i]=a[j];
                a[j]=t;
            }//交换使选择出来的到最前面 
    printf("排序后的顺序是:\n");
    for(i=0;i

然后可以发现直接排序在最坏情况要进行n-1次选择,每次要进行n-1次比较,这个时间复杂度显然是不能接受,所以希尔排序诞生了。我们可以发现在元素少且相对有序时选择排序还是ok的,比如只有两个元素,复杂度为n。
所以我们先将整个待排元素序列分割成若干个子序列(每个元素之间隔了一个值,我们姑且叫做差值)从每组的最后一个开始选择排序,然后依次缩减差值再进行排序,待差值缩小到1或0时,再做简单的插入排序。
因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序快了很多。
下面附上希尔排序的差值从n/2开始,每次再减半,直到最后为1的代码,差值当然也有别的选择方案,但能力有限不多说。
代码与注释如下

void shellsort3(int a[], int n)

{

	int i, j, gap;
    for (gap = n / 2; gap > 0; gap /= 2)//每次差值除2,边界为gap不大于0,其实gap为1就和对全体元素直接选择排序没区别了,所以gap为0时就结束了不用排了,此时必为有序了。

		for (i = gap; i < n; i++)/!开始选择排序!/

			for (j = i - gap; j >= 0 && a[j] > a[j + gap]; j -= gap)
			//每个元素隔一个差值,所以j = i - gap;

				Swap(a[j], a[j + gap]);

}

第一次写这么长博文,还只是个学生,请多指教

你可能感兴趣的:(希尔排序与快速排序(详细注释)附带csdn代码复制错误的解决方法)