希尔排序和归并排序

1.首先说一下为什么要搞这些东西。当然是数据结构考试啦,再来复习一下数据结构以及一些常用的算法,平时都是用的

是sort真的自己敲了一下发现还是不容易一次敲对的。

2.首先是希尔排序,ShellSort,没错这个排序方法就是希尔发明的,作为第一个打破排序时间复杂度O(n^2)的方法。首先我们需要知道什么是交换排序,其实交换排序就是很简单的一个思想,假设第一个元素已经是OK的,那么后边的元素一次找到自己的位置,这个排序方法是很暴力的。Shell看到这个十分暴力的方法之后,找到了一种优化的方法,但是这种优化也让这种基于插入排序的方法失去了插入排序的一些特性。所以说任何事情都是要付出代价的。

3.希尔排序的原理:希尔排序又叫做缩小增量排序,这个增量的引入使得排序的速度加快。我们看一组数据。

这组数据的长度为8,我们首先选取8/2=4的长度为间隔,然后怎么做呢?其实很简单,我们把下标相差4的元素作比较,也就是1和5,3和6,7和4,9和8.假设我们现在正在按照从小到大排序,那么如果前边的比后边的小就交换,否则不交换,这样我们逐渐的缩小间隔,一种类似于夹逼的思想就会把间隔缩的越来越小,这样就完成了排序。那么分析时间复杂度是nlogn的。这比n^2要好很多,但是由于多次插入,导致希尔排序不再是稳定的排序。下边给出实现的代码:

void ShellSort(int a[], int n)
{
	int j, gap = n / 2, i, x;
	for (gap; gap > 0; gap /= 2)//枚举间隔
	{
		for (i = gap; i < n; i++)//枚举每一段子序列
		{
			x=a[i];
			for (j = i - gap; j >= 0&&x < a[j]; j -= gap)
			{
				a[j + gap] = a[j];
			}
			a[j + gap] = x;
		}
	}
}

希尔排序间隔的选取是很重要的,一般都是一种基于二分的思想,但是很多情况表明二分不是最好的方法,有的是基与gap=gap/3+1来做的,还有研究表明,使用素数效率更高。当然,原理都是一样的。

3.归并排序原理。归并排序其实有一种快速排序的思想,二者都是基与分而治之的思想来做的。但是,也有很大的区别。快排是出了名的不稳定排序,但是归并排序是稳定的。我们首先看一下归并排序的思想:分而治之。

归并的图解

这是一种基与二叉树的思想,首先把序列分散到叶子结点,然后在回溯的时候合并整个序列,这样就可以完成排序。这当然是一种基于递归的算法了,下面给出具体的代码实现。

void merge(int a[], int start, int mid, int end)
{
	int *tmp = (int *)malloc((end - start + 1) * sizeof(int));   
	int i = start;           
	int j = mid + 1;       
	int k = 0;               

	while (i <= mid && j <= end)
	{
		if (a[i] <= a[j])
			tmp[k++] = a[i++];
		else
			tmp[k++] = a[j++];
	}

	while (i <= mid)
		tmp[k++] = a[i++];

	while (j <= end)
		tmp[k++] = a[j++];
	for (i = 0; i < k; i++)
		a[start + i] = tmp[i];

	free(tmp);
}
void merge_sort(int a[], int start, int end)
{
	if (a == NULL || start >= end)
		return;
	int mid = (end + start) / 2;
	merge_sort(a, start, mid); 
	merge_sort(a, mid + 1, end);
	merge(a, start, mid, end);
}

好了,基本上就是这样了。当然还有很多排序算法,这里就不再一一讨论了。反正大多数sort是可以搞定的。感兴趣的可以看一下sort的实现。

猜你喜欢

转载自blog.csdn.net/weixin_41863129/article/details/85165997