您的位置:首页 > 其它

排序算法-----归并排序、计数排序

2018-03-12 20:12 274 查看

1. 归并排序

将待排序序列分成两个长度相同的子序列,对每个子序列进行排序,直至子序列剩余一个数,在将其合并成一个序列

[b]具体步骤:[/b]

分组:将待排序序列一分为2,在将子序列进行划分,直至子序列只有一个元素



归并:将每个子序列进行排序,将排好序的两个子序列进行合并



算法分析

稳定性

最稳定算法,归并和分组过程中都不会使元素的相对位置发生变化

时间复杂度

这里采用了二分的思想,使其效率有所提高,时间复杂度为O(nlgn)

空间复杂度

在归并的过程中需要开辟临时数组,故时间复杂度为O(n)

代码

void Merge(DataType* a, int left, int mid, int right)
{
DataType* tmp = (DataType*)malloc((right - left + 1)*sizeof(int));
assert(tmp);
memset(tmp,0,(right - left + 1)*sizeof(int));
int index = 0;
int begin1 = left, end1= mid;//第一个数组的范围
int begin2 = mid + 1, end2 = right;//第二个数组的范围

//选两个数组中较小的数据在tmp数组中
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] <= a[begin2])
{
tmp[index++] = a[begin1++];
}
else
{
tmp[index++] = a[begin2++];
}
}

//数组1中还有数据
if (begin1 <= end1)
{
while (begin1 <= end1)
{
tmp[index++] = a[begin1++];
}
}

//数组2中还有数据
if (begin2 <= end2)
{
while (begin2 <= end2)
{
tmp[index++] = a[begin2++];
}
}

//将临时数组的数据拷回原数组
index = 0;
while (index < right - left + 1)
{
a[index+left] = tmp[index];
++index;
}

free(tmp);
}

//归并排序
void MergeSort(DataType* a,  int left, int right)
{

assert(a);

if (left >= right)
return;

//分组
if (right - left + 1 > 5)
{
int mid = left + ((right - left) >> 1);
MergeSort(a, left, mid);
MergeSort(a, mid + 1, right);
//归并
Merge(a, left, mid, right);
}
else
{
InsertSort(a+left, right - left + 1);
}

}


2.计数排序

计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用

[b]具体步骤:[/b]

遍历数组,统计待排序数组的范围range

开辟数组,大小为统计的范围,并初始化为0

遍历数组,统计每个数出现的次数

将统计好数组元素出现的次数保存在哈希表对应位置上,对应位置即为数组元素大小

注意:待排序数组中不能有负数

算法分析

稳定性

不稳定,在将数字重新拷贝至原数组时,元素相对位置会发生改变

时间复杂度

时间复杂度为O(n)

空间复杂度

需要开辟空间,因此为O(n)

代码

//计数排序
void CountSort(DataType* a, size_t n)
{
assert(a);

//统计待排序数组的范围
DataType max = a[0], min = a[n - 1];
for (size_t i = 0; i < n; ++i)
{
if (a[i] < min)
{
min = a[i];
}

if (a[i]>max)
{
max = a[i];
}
}

size_t range = max - min + 1;

//开辟范围大小的数组
DataType* count = (DataType*)malloc(sizeof(int)*range);
assert(count);
memset(count, 0, sizeof(int)*range);

//统计每个数出现的次数
for (size_t index = 0; index < n; ++index)
{
count[a[index]]++;
}

//将数字拷至原数组中
size_t index = 0;
for (size_t i = 0; i < range; ++i)
{
for (int j = 0; j < count[i]; ++j)
{
a[index++] = min + i;
}

}
free(count);
}


4000
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  归并排序