计数排序
计数排序是一种非比较性质的排序算法,元素从未排序状态变为已排序状态的过程,是由额外空间的辅助和元素本身的值决定的。计数排序过程中不存在元素之间的比较和交换操作,根据元素本身的值,将每个元素出现的次数记录到辅助空间后,通过对辅助空间内数据的计算,即可确定每一个元素最终的位置。比较排序算法的时间复杂度理论值是O(nlogn),计数排序某些情况下可以比比较排序更快。
- 时间复杂度:best:O(n+k); worst:O(n+k); average:O(n+k)
- 空间复杂度:O(k)
- 稳定性:稳定
- 适用于:元素集中,整数排序
- 算法过程:
- 根据待排序集合中最大元素和最小元素的差值范围,申请额外空间;
- 遍历待排序集合,将每一个元素出现的次数记录到元素值对应的额外空间内;
- 对额外空间内数据进行计算,得出每一个元素的正确位置(即将a[i]的值加上前面所有的值,因为额外空间的需要排序的元素(下标)是有序的,加上之后就表示a[i]对应的下标元素应该在的排序后的位置);
- 将待排序集合每一个元素移动到计算得出的正确位置上。
- 实现:
# python实现
def countingSort(arr): # the elements in the array are all integers
maximum, minimum = max(arr), min(arr)
countArr = [0] * (maximum - minimum + 1)
for i in arr: # record the number of times of every element in the array
countArr[i - minimum] += 1
for i in range(1, len(countArr)): # calculate the position of every element
countArr[i] += countArr[i-1]
targetArr = [None] * len(arr)
for i in range(len(arr)-1, -1, -1): # reverse-order traversal is for the stability
countIndex = arr[i] - minimum
targetArr[countArr[countIndex] - 1] = arr[i]
countArr[countIndex] -= 1
return targetArr
class Solution
{
public:
int* coutSort(int* data, int length)
{
if (data == nullptr || length <= 0)
return nullptr;
//确定数列最大值
int max = data[0];
int min = data[0];
for (int i = 1; i < length; ++i)
{
if (data[i] > max)
max = data[i];
if (data[i] < min)
min = data[i];
}
int d = max - min;
// 确定统计数组长度并进行初始化
int* coutData = new int[d + 1];
for (int i = 0; i <= d; ++i)
coutData[i] = 0;
// 遍历数组,统计每个数出现的次数
for (int i = 0; i < length; ++i)
++coutData[data[i] - min];
// 统计数组做变形,后面的元素等于前面的元素之和
for (int i = 1; i <= d; ++i)
coutData[i] += coutData[i - 1];
// 倒序遍历原始数列,从统计数组找到正确的位置,输出到结果数组
int* sortedArray = new int[length];
for (int i = length - 1; i >= 0; i--)
{
sortedArray[coutData[data[i] - min] - 1] = data[i]; // 找到data[i]对应的coutData的值,值为多少,表示原来排序多少,(因为从1开始,所以再减1)
coutData[data[i] - min]--; // 然后将相应的coutData的值减1,表示下次再遇到此值时,原来的排序是多少。
}
return sortedArray;
}
};
参考链接:
https://www.jianshu.com/p/86c2375246d7
https://www.cnblogs.com/wyr-123-wky/p/11093919.html