>>>八大排序总结(1)——冒泡排序(Bubble Sort)(c语言实现)<<<
>>>八大排序总结(2)——选择排序(Selection Sort)(c语言实现)<<<
>>>八大排序总结(3)——插入排序(Insertion Sort)(c语言实现)<<<
>>>八大排序总结(4)——快速排序(Quick Sort)(c语言实现)<<<
>>>八大排序总结(5)——归并排序(Merge Sort)(c语言实现)<<<
>>>八大排序总结(6)——希尔排序(Shell Sort)(c语言实现)<<<
>>> 八大排序总结(7)——堆排序(Bubble Sort)(c语言实现)<<<
>>>八大排序 时间复杂度,空间复杂度,稳定性的比较<<<
1.桶排序(Bucket Sort)
代码+分析
2.基数排序
代码+分析
3.计数排序
代码+分析
基本思路是:
1. 将待排序元素划分到不同的痛。先扫描一遍序列求出最大值 maxV 和最小值 minV ,设桶的个数为 k ,则把区间 [minV, maxV] 均匀划分成 k 个区间,每个区间就是一个桶。将序列中的元素分配到各自的桶。
2.对每个桶内的元素进行排序。可以选择任意一种排序算法。
3. 将各个桶中的元素合并成一个大的有序序列。
4.假设数据是均匀分布的,则每个桶的元素平均个数为 n/k 。假设选择用快速排序对每个桶内的元素进行排序,那么每次排序的时间复杂度为 O(n/klog(n/k)) 。总的时间复杂度为 O(n)+O(m)O(n/klog(n/k)) = O(n+nlog(n/k)) = O(n+nlogn-nlogk 。当 k 接近于 n 时,桶排序的时间复杂度就可以金斯认为是 O(n) 的。即桶越多,时间效率就越高,而桶越多,空间就越大。
#include
#include
#include
extern void quick_sort(int a[], int p, int q);/* not necessary */
struct barrel {
int node[10];
int count;/* the num of node */
};
void bucket_sort(int data[], int size)
{
int max, min, num, pos;
int i, j, k;
struct barrel *pBarrel;
max = min = data[0];
for (i = 1; i < size; i++)
{
if (data[i] > max)
max = data[i];
else if (data[i] < min)
min = data[i];
}
num = (max - min + 1) / 10 + 1;
pBarrel = (struct barrel*)malloc(sizeof(struct barrel) * num);
memset(pBarrel, 0, sizeof(struct barrel) * num);
/* put data[i] into barrel which it belong to */
for (i = 0; i < size; i++)
{
k = (data[i] - min + 1) / 10;/* calculate the index of data[i] in barrel */
(pBarrel + k)->node[(pBarrel + k)->count] = data[i];
(pBarrel + k)->count++;
}
pos = 0;
for (i = 0; i < num; i++)
{
quick_sort((pBarrel+i)->node, 0, (pBarrel+i)->count);/* sort node in every barrel */
for (j = 0; j < (pBarrel+i)->count; j++)
{
data[pos++] = (pBarrel+i)->node[j];
}
}
free(pBarrel);
}
这是一种非比较排序算法,时间复杂度是 O(n) 。它的主要思路是,
1. 将所有待排序整数(注意,必须是非负整数)统一为位数相同的整数,位数较少的前面补零。一般用10进制,也可以用16进制甚至2进制。所以前提是能够找到最大值,得到最长的位数,设 k 进制下最长为位数为 d 。
2. 从最低位开始,依次进行一次稳定排序。这样从最低位一直到最高位排序完成以后,整个序列就变成了一个有序序列。
举个例子,有一个整数序列,0, 123, 45, 386, 106,下面是排序过程:
1.第一次排序,个位,000 123 045 386 106,无任何变化
2.第二次排序,十位,000 106 123 045 386
3.第三次排序,百位,000 045 106 123 386
4.最终结果,0, 45, 106, 123, 386, 排序完成。
#include
#include
#define Max_ 10 //数组个数
#define RADIX_10 10 //整形排序
#define KEYNUM_31 31 //关键字个数,这里为整形位数
// 打印结果
void Show(int arr[], int n)
{
int i;
for ( i=0; i
是一种O(n)的排序算法,其思路是开一个长度为 maxValue-minValue+1 的数组,然后
举个例子, nums=[2, 1, 3, 1, 5] , 首先扫描一遍获取最小值和最大值, maxValue=5 , minValue=1 ,于是开一个长度为5的计数器数组 counter ,
1. 分配。统计每个元素出现的频率,得到 counter=[2, 1, 1, 0, 1] ,例如 counter[0] 表示值 0+minValue=1 出现了2次。
2. 收集。 counter[0]=2 表示 1 出现了两次,那就向原始数组写入两个1, counter[1]=1 表示 2 出现了1次,那就向原始数组写入一个2,依次类推,最终原始数组变为 [1,1,2,3,5] ,排序好了。
计数排序本质上是一种特殊的桶排序,当桶的个数最大的时候,就是计数排序。
//计数排序 参数:数组及其长度
void BucketSort(int* arr , int len)
{
int tmpArrLen = GetMaxVal(arr , len) + 1;
int tmpArr[tmpArrLen]; //获得空桶大小
int i, j;
for( i = 0; i < tmpArrLen; i++) //空桶初始化
tmpArr[i] = 0;
for(i = 0; i < len; i++)
tmpArr[ arr[i] ]++;
for(i = 0, j = 0; i < tmpArrLen; i ++)
{
while( tmpArr[ i ] != 0) //对每个不是空的桶子进行排序。
{
arr[j ] = i; //从不是空的桶子里把项目再放回原来的序列中。
j++;
tmpArr[i]--;
}
}
}
int GetMaxVal(int* arr, int len)//遍历数组取最大值
{
int maxVal = arr[0]; //假设最大为arr[0]
for(int i = 1; i < len; i++) //遍历比较,找到大的就赋值给maxVal
{
if(arr[i] > maxVal)
maxVal = arr[i];
}
return maxVal; //返回最大值
}
算法 | 时间复杂度 | 空间复杂度 | 适用场景 |
桶排序 | O(nd)_ | O(n+k) | 1.非负整数.2.maxV和minV尽可能小 |
基数排序 | O(n+k) | O(n+k) | 元素尽可能均匀分布 |
计数排序 | O(n+maxV-minV) | O(maxV-minV) | maxV和minV差距尽可能小 |
其中, d 表示位数, k 在基数排序中表示 k 进制,在桶排序中表示桶的个数, maxV 和 minV 表示元
素最大值和最小值。
欢迎大家评论指正,谢谢◕‿◕