其他排序
堆排序
归并排序
插入排序和希尔排序
快速排序
冒泡排序和选择排序
基数排序
前备知识
注:我们知道,对于一个数如果我们想获取它得个位,只需对10取余,想获取十位的数,可以除10然后再对10取余,获取百位除100然后再对10取余,获取千位除1000再对10取余...
核心思想
:根据数字的位(个位、十位、百位…)来进行的排序算法,有点类似于哈希表,基数排序首先应该找到数字中最大的数,然后算出这个数有几位,其次依次根据个位、十位、百位、千位、…、最大位来进行排序
实现过程
如上图所示,对上述数据进行由小到大排序:
1.首先,找出所有数中最大的数,计算它的位数
从上图我们可以看出最大值为1356
,即此时位数int nBit = 4;
2.然后,我们需要一次按照个位、十位、百位、千位(因为最大位数只有4)进行排序
在进行排序之前,我们需要有一个空间能存储排序的数据,由于我们是按位进行排序,所以我们需要包括所有可能取得的值0-9,然后获取对应位数的值后放入相应位置。
先按照个位排序,排序结果如下:
经过个位排序之后,结果如上图所示,此时我们已经将数组按照个位拍好序,之后我们将拍好序的值重新放回原数组,然后释放原有空间,接着再按照十位排序,返回原数组之后结果如下:
接着,按照十位排序,结果如下:
放回原数组,结果如下(这个过程和上面类似,不再细说):
按照百位排序,如下:
放回原数组,结果如下:
按照千位排序,如下
如上图所示,将数据放回原数组,结束(因为千位为最大位数,这也是我们为什么刚开始要找打最大的数字)
总结,从上述的实现过程我们可以看出,每次按照位数进行排序时,在对应的每个位置都是一个链表,而且总共是有十个链表组成在一起,因此我们排序时所需要申请的空间为一个指针数组来保存这些数据。
代码实现
#include <stdio.h>
#include <stdlib.h>
typedef struct Radix
{
int nValue;
struct Radix *pNext;
}Radix;
void RadixSort(int arr[],int nLen)
{
if(arr == NULL || nLen <= 0)
return;
int nBit = 1;
int nMax = arr[0];
//找出最大数
for(int i = 1;i < nLen;i++)
{
if(nMax < arr[i])
{
nMax = arr[i];
}
}
//计算位数
while(nMax /= 10)
{
nBit++;
}
int n = 1;
//定义一个指针数组来存数据,并开辟10个Radix空间
Radix **pRadix = (Radix **)malloc(sizeof(Radix *)*10);
Radix *pTemp = NULL;
Radix *pMark = NULL;
int nCount;
Radix *pDel = NULL;
//初始化为空
for(int i = 0;i < 10;i++)
{
pRadix[i] = NULL;
}
for(int i = 0;i < nBit;i++)
{
//按位排序
for(int j = 0;j < nLen;j++)
{
pTemp = (Radix*)malloc(sizeof(Radix));
pTemp->nValue = arr[j];
pTemp->pNext = NULL;
if(pRadix[arr[j]/n%10] == NULL)
{
pRadix[arr[j]/n%10] = pTemp;
}
else
{
pMark = pRadix[arr[j]/n%10];
while(pMark->pNext != NULL)
{
pMark = pMark->pNext;
}
pMark->pNext = pTemp;
}
}
nCount = 0;
//将数据重新放回原数组
for(int j = 0;j < 10;j++)
{
while(pRadix[j] != NULL)
{
arr[nCount++] = pRadix[j]->nValue;
pDel = pRadix[j];
pRadix[j] = pRadix[j]->pNext;
free(pDel);
pDel = NULL;
}
}
n *= 10;
}
}
void Print(int arr[],int nLen)
{
if(nLen <= 0) return;
for(int i = 0;i < nLen;i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
}
int main()
{
//int arr[] = {1,78,2,54,56,2,78,12,4555,8};
int arr[] = {8,13,231,156,29,1356,50,200,6};
RadixSort(arr,sizeof(arr)/sizeof(arr[0]));
Print(arr,sizeof(arr)/sizeof(arr[0]));
return 0;
}
平均时间复杂度
:O( n*k)k:为最大的位数
空间复杂度
:O(m+n)空间复杂度我们也可以看出来,主要就是取决于链表的数量以及序列元素的数量
,所以空间复杂度为O(n+k)
稳定性
:稳定
适用场合
:数组量大且较无序
排序名称 | 最好时间复杂度 | 平均时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 稳定性 | 适用场合 |
---|---|---|---|---|---|---|
BubbleSort | O(n) | O(n2) | O(n2) | O(1) | 稳定 | |
SelectSort | O(n2) | O(n2) | O(n2) | O(1) | 不稳定 | |
InsertSort | O(n) | O(n2) | O(n2) | O(1) | 稳定 | |
ShellSort | O(n) | O(n1.3) | O(n2) | O((log2n) | 不稳定 | |
QuickSort | O(nlogn) | O(nlogn) | O(n2) | O(logn)~O(n) | 不稳定 | |
MergeSort | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | 稳定 | |
HeapSort | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 稳定 | |
RadixSort | 稳定 |