排序——归并排序 / 非归并排序——《 计数排序 》

插入排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89345756
选择排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89363420
交换排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89394853
归并排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89449893
非比较排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89449893

一. 归并排序

归并排序的主要思想:首先将这个列数组分解成两个部分,然后在分,直到分解到个数的时候,不能再分了,然后再进行排序,组合,组合成两个组,然后再把再把两个组按照小的先入的原则,在分别在进入,组合。

下面我们拿这个图片,看一下。
在这里插入图片描述
这里我主要是,拿了一部分的例子说明一下,让我们可以看懂一下。

下面我们看一下实现的代码:

void _MergeSort(int* a, int begin, int end, int* tmp)
{
	int mid = 0;
	int begin1 = 0;
	int end1 = 0;
	int begin2 = 0;
	int end2 = 0;
	int index = 0;
	if (begin >= end)
		return;
	if (end - begin <= 8)        小区间优化;
	{
		InsertSort(a + begin, end - begin + 1);
	}
	mid = begin + ((end - begin) >> 1);
	begin1 = begin;
	end1 = mid;        //把这里写成了begin;直接就错了;
	begin2 = mid + 1;
	end2 = end;
	index = begin;
	//子问题
	_MergeSort(a, begin, mid, tmp);
	_MergeSort(a, mid + 1, end, tmp);
	//[left , mid]
	//[mid+1 , right]
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			tmp[index++] = a[begin1++];
		}
		else
		{
			tmp[index++] = a[begin2++];
		}
	}
	while (begin1 <= end1)    //第二部分结束,第一个剩下的在入进去
	{
		tmp[index++] = a[begin1++];
	}
	while (begin2 <= end2)    //第一部分结束,第二个剩下的在入进去
	{
		tmp[index++] = a[begin2++];
	}
	//归并结果考回原数组;
	index = begin;
	while (begin <= end)
		a[index++] = tmp[begin++];

}
void MergeSort(int* a, int n)  
{
	int* tmp = (int*)malloc(sizeof(int)* n);
	_MergeSort(a, 0, n - 1, tmp);
	free(tmp);
}

其中重要的是:当数列为有序的时候,它是在其他几个里面最快的。
归并的缺点:
1.开空间,
2.拷贝数据

虽然归并排序的时间非常快,但是为什么我们常用快排,而不是使用归并排序,是因为归并排序它有空间复杂度的消耗比较大。

归并排序的思想是非常重要的,我们可以看上面的思想加上实现的代码,就可以理解了。

二,非归并排序 ——计数排序

非归并排序的思想:就是把一个要排的序列,先统计它的个数,但后在开辟这么大空间数组,把最小的数,放在数组下标为位置,把最大的数放在数组下面为N的位置。《开辟多大的空间呢?最大的数 — 最小的数 +1 = 开辟的空间的大小》

下面我们先看一下我画理解图:
在这里插入图片描述

下面是我们实现的代码:

void CountSort(int* a, int n)  
{
	int max = 0;
	int min = 0;
	int i = 0;
	int j = 0;
	for (i = 0; i< n; i++)
	{
		if (a[i] > max)
		{
			max = a[i];
		}
		if (a[i] < min)
		{
			min = a[i];
		}
	}
	int range = max - min + 1; //它的范围
	int* count = (int*)malloc(range*sizeof(int));
	memset(count, 0, sizeof(int)*range);
	for (i = 0; i < n; i++)
	{
		count[a[i] - min]++;
	}
	for (i = 0; i < range; i++)**加粗样式**
	{
		while (count[i]--)
		{
			a[j++] = i + min;  //不加min就错位了。把不是0的数,就按照0,排序了。
		}
	}
}

上面就是我们的非归并排序——也叫计数排序。

非归并排序:通过我们测试,发现它的时间是非常快的。比快排还要快。

如何让他变慢?那就是给他加一个很大的数,他就慢下来了,但是它的性能还是很快的。

它的缺陷:它只能排整型

下面我们看就一下归并排序,和非归并排序的差别,和自己的分析;

归并排序;

1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
2. 时间复杂度:O(N*logN)
3. 空间复杂度:O(N)
4. 稳定性:稳定

非归并排序

O(MAX(N,范围))
时间复杂度为:O(N + 范围);
空间复杂度为:O(范围)
稳定性:稳定

插入排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89345756
选择排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89363420
交换排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89394853
归并排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89449893
非比较排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89449893

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值