《插入排序》链接: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