你好,我是史丰源
欢迎你的来访,希望我的博客能给你带来一些帮助。
我的Gitee:代码仓库
在进入正文之前,一般排序的方法就是:
1.比较关键字的大小
2.不合适就移动数据
这里的归并排序与基数排序是一样的。
归并排序
概念(来自Wikipedia)
归并排序(也通常拼写为归并排序)是一种高效、通用且基于比较的 排序算法。大多数实现产生一个稳定的排序,这意味着相等元素的顺序在输入和输出中是相同的。归并排序是约翰·冯·诺依曼在 1945年发明的一种分而治之的算法。 [2]自下而上归并排序的详细描述和分析早在 1948 年就出现在Goldstine和 von Neumann 的报告中。 [3 ]
实现算法(来自Wikipedia)
从概念上讲,归并排序的工作原理如下:
- 将未排序列表划分为n个子列表,每个子列表包含一个元素(一个元素的列表被视为已排序)。
- 重复合并子列表以产生新的排序子列表,直到只剩下一个子列表。这将是排序列表。
归并时需要借助额外的数组tmp
看下面这个待排序的数组,我们将会把它分为两个部分(类似递归,直到分到最后一个数据元素)。
区间有序就进行归并,然后逐级返回并且归并,就可以完成排序。
void _MergeSort(int* a,int begin,int end,int* tmp)
{
if(begin>=end)//不须分割了
return ;
int mid = (begin+end)/2;
//左区间(begin,mid)右区间(mid+1,end)
_MergeSort(a,begin,mid,tmp);
_MergeSort(a,mid+1,end,tmp);//不断细分的一个过程
//归并 归并完就是有序的了
int begin1 = begin,end1 =mid;
int begin2 = mid+1,end2 = end;
int i = begin1;//下标标识
while(begin1 <= end1 && begin2 <= end2)
{
if(a[begin1] < a[begin2])
{
tmp[i++] = a[begin1++]; //往tmp里拷数字
}
else
{
tmp[i++] = a[begin2++];
}
}
while(begin1<=end1)
{
tmp[i++] = a[begin1++];
}
while(begin2<=end2)//有一个必然结束
{
tmp[i++] = a[begin2++];
}
//把归并数据拷贝回原数组
memcpy(a+begin,tmp+begin,(end-begin+1)*sizeof(int));
}
void MergeSort(int *a,int n)
{
int *tmp =(int*)malloc(sizeof(int)*n);
if(tmp == NULL)
{
printf("malloc fail\n");
exit(-1);
}
_MergeSort(a,0,n-1,tmp);
free(tmp);
}
基数排序
概念(来自Wikipedia)
基数排序是一种非比较 排序算法。它通过根据radix创建元素并将其分配到存储桶中来避免比较。对于具有多个有效数字的元素,对每个数字重复此分桶过程,同时保留前一步的顺序,直到所有数字都被考虑在内。因此,基数排序也被称为**桶排序和数字排序**。
基数排序可以应用于可以按字典顺序排序的数据,无论是整数、单词、穿孔卡片、扑克牌还是邮件。
举例(来自Wikipedia)
有两种模式MSD最高位优先 LSD最低位优先
我们这里讲实现LSD最低位优先规则.
LSD最低位优先:
从最低位排序,排序完再向上取高位再排序。重复这个过程,直到排序完成。
回收数据
核心思想:
1.分发数据
2.回收数据
#include<queue>
#define K 3
#define RADIX 10
queue<int> Q[RADIX];
//构造10个队列 10个基数 先进先出
int GetKey(int value,int k)//根据第几次取关键字 对应取关键字
{
int key = 0;
while(k>=0)
{
key = value%10;
value/=10;
k--;
}
return key;
}
void Distribute(int arr[],int left,int right,int k)
{
for(int i =left;i<right;++i)
{
int key = GetKey(arr[i],k);
Q[key].push(arr[i]);
}
}
void Collect(int arr[])
{
int k = 0;
for(int i =0;i<RADIX;++i)
{
while(!Q[i].empty())
{
arr[k++] = Q[i].front();
Q[i].pop();
}
}
}
void RadixSort(int arr[],int left,int right)
{
for(int i = 0;i<K;++i)
{
//分发数据
Distribute(arr,left,right,i);
//回收数据
Collect(arr);
}
}
int main()
{
int arr[] = {278,109,63,930,589,184,505,269,8,83};
int n = sizeof(arr)/sizeof(arr[0]);
for(int i = 0;i<n;++i)
{
printf("%d ",arr[i]);
}
printf("\n");
RadixSort(arr,0,n);
for(int i = 0;i<n;++i)
{
printf("%d ",arr[i]);
}
printf("\n");
}