1、基数排序
基数排序是一种不进行比较的稳定的排序方法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。
void radixsort(vector<int>& v, int n) //基数排序
{
//找到最大的数,计算出分配次数
int maxv = *max_element(v.begin(), v.end());
int k = to_string(maxv).size();
//声明tmp数组,用于收集数据
vector<int> tmp(n, 0);
//声明桶的个数
vector<int> backet(10, 0);
int base = 1;
for (int i = 0; i < k; i++) {
//记录数据到桶
backet.assign(10, 0);
for (int i = 0; i < n; i++)
{
int p = (v[i] / base) % 10;
backet[p]++;
}
for (int i = 1; i < 10; i++)
{
backet[i] += backet[i - 1];
}
//收集数据
for (int i = n-1; i >= 0; i--)
{
int p = (v[i] / base) % 10;
tmp[backet[p] - 1] = v[i];
backet[p]--;
}
for (int i = 0; i < n; i++)
v[i] = tmp[i];
base *= 10;
}
}
注意以上代码不适合排序负数
2、希尔排序
希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;
希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。
先写个插入排序,然后直接在上面改动
void insert(vector<int>&v)
{
int n = v.size() - 1;
for (int i = 1; i <= n; i++)
{
int j = i - 1;
int x = v[i];
while (j >= 0 && v[j] > x)
{
v[j + 1] = v[j];
j--;
}
v[j+1] = x;
}
}
void shellsort(vector<int>&v)
{
int n = v.size() - 1;
int gap = n / 2;
while (gap >= 1)
{
for (int i = gap; i <= n; i++)
{
int j = i - gap;
int x = v[i];
while (j >= 0 && v[j] > x)
{
v[j + gap] = v[j];
j-= gap;
}
v[j + gap] = x;
}
gap /= 2;
}
}
3、堆排序
大根堆 从小到大排列,建立大根堆
void adjustdown(vector<int>& v,int parent,int len)
{
int n = v.size();
int child = 2 * parent + 1;
while (child < len)
{
if (child+1< len && v[child] < v[child + 1])
child++;
if (v[parent] < v[child])
swap(v[parent], v[child]);
else if (v[parent] == v[child])
break;
parent = child;
child = 2 * parent + 1;
}
}
int main()
{
vector<int> v = {- 2,3,1,5,7,4,84,6 };
//建堆
int n = v.size();
for (int i = n / 2; i >= 0; i--)
{
adjustdown(v, i,n);
}
for (int i = n - 1; i > 0; i--)
{
swap(v[0], v[i]);
adjustdown(v, 0,i);
}
}