这里有一些看起来比较好看的排序代码模板~
快排
void q_sort(int l, int r)
{
int i = l, j = r;
if(l > r) return;
while(i < j)
{
while(a[j] >= a[l] && i < j)
j --;
while(a[i] <= a[l] && i < j)
i ++;
if(i < j) swap(a[i], a[j]);
}
swap(a[i], a[l]);
q_sort(l, i - 1);
q_sort(i + 1, r);
}
归并排序
int tmp[N], a[N], n;
//这里为需要背诵的部分,要求:给一个相关题目,能快速写出该模板并调试通过。
//归并排序
void merge_sort(int q[], int l, int r)
{
//递归出口
if (l >= r) return;
//第一步,分成两个子区间
int mid = l + r >> 1;
//第二部,递归处理子区间
//要注意这里用的mid和mid+1来划分两区间,建议不要用mid-1和mid来划分
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
//第三步,合并排序好的子区间
//tips:k为tmp下标,i和j为两个子区间起始位置
int k = 0, i = l, j = mid + 1;
//排序好的两边取大小,暂存数组tmp挑小的取
while (i <= mid && j <= r)
{
if (q[i] <= q[j]) tmp[k++] = q[i++];
else tmp[k++] = q[j++];
}
//很可能存在有一子区间没有比较完,由于该区间是排好序的,后面的没比较完,说明都是最大的,直接往tmp后面加即可。
while (i <= mid) tmp[k++] = q[i++];
while (j <= r) tmp[k++] = q[j++];
//在[l, r]范围中,将tmp数组存的有序值赋给q数组完排序,注意<=r的等号不要漏
for (int i = l, j =0; i <= r; i++, j++) q[i] = tmp[j];
}
堆排序
1.首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端
2.将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n-1
3.将剩余的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组
注意:升序用大根堆,降序就用小根堆(默认为升序)
int cnt;
int h[N], a[N], n;
void down(int x)
{
int t = x;
if (x * 2 <= cnt && h[x * 2] < h[t])
t = x * 2;
if (x * 2 + 1 <= cnt && h[x * 2 + 1] < h[t])
t = x * 2 + 1;
if (x != t)
{
swap(h[x], h[t]);
down(t);
}
}
void heap_sort(int l, int r)
{
cnt = 0;
for (int i = l; i <= r; i++)
{
h[++cnt] = a[i];
}
for (int i = cnt / 2; i; i--)
{
down(i);
}
int k = l;
while (cnt)
{
a[k++] = h[1];
h[1] = h[cnt--];
down(1);
}
}
int cnt;
int h[N];
void down(int x)
{
int t = x;
if (x * 2 <= cnt && h[x * 2] > h[t])
t = x * 2;
if (x * 2 + 1 <= cnt && h[x * 2 + 1] > h[t])
t = x * 2 + 1;
if (x != t)
{
swap(h[x], h[t]);
down(t);
}
}
void heap_sort(int l, int r)
{
cnt = 0;
for (int i = l; i <= r; i++)
{
h[++cnt] = a[i];
}
for (int i = cnt / 2; i; i--)
{
down(i);
}
int k = r;
while (cnt)
{
a[k --] = h[1];
h[1] = h[cnt--];
down(1);
}
}
计数排序
计算ai的数量,然后算它在数组中是第几小的,然后把第几小赋给b数组作为下标,同时b下标=a中的值,最后整理下
int a[N], h[N+50];
int b[N];
int n;//如果出现负数 (-10000,10000)整体右移 x+10000 (0,20000)
//如果小数 整体*100
void counting_sort()
{
int w = 100050;
memset(h, 0, sizeof h);
for (int i = 0; i < n; i++) h[a[i]]++;
for (int i = 1; i <= w; i++) h[i] += h[i - 1];
for (int i = n-1; i >= 0; i--) b[h[a[i]]--] = a[i];
for(int i=1;i<=n;i++)
a[i-1]=b[i];
}
桶排序
桶排序的核心思想就是将要排序的数据分到几个有序的桶里,每个桶里的数据再单独进行排序。桶排序完之后,再把每个桶里的数据按照顺序依次取出,组成的序列就是有序的了。
int n, w = 100000, a[N];
vector<int> bucket[N];
void insert_sort(vector<int>& A)
{
for (int i = 1; i < A.size(); i++)
{
int key = A[i];
int j = i - 1;
while (j >= 0 && A[j] > key)
{
A[j + 1] = A[j];
j--;
}
A[j + 1] = key;
}
}
void bucket_sort()
{
int bucket_size = w / n + 1;
for (int i = 0; i < n; i++)
{
bucket[i].clear();
}
for (int i = 0; i < n; i++)
{
bucket[a[i] / bucket_size].push_back(a[i]);
}
int p = 0;
for (int i = 0; i < n; i++)
{
insert_sort(bucket[i]);
for (int j = 0; j < bucket[i].size(); j++)
{
a[p++] = bucket[i][j];
}
}
}
基数排序
const int N = 100010;
const int W = 100010;
const int K = 100;
int n, w[K], k, cnt[W];
struct Element {
int key[K];
bool operator<(const Element& y) const {
for (int i = 1; i <= k; ++i) {
if (key[i] == y.key[i]) continue;
return key[i] < y.key[i];
}
return false;
}
} a[N], b[N];
void counting_sort(int p) {
memset(cnt, 0, sizeof(cnt));
for (int i = 1; i <= n; ++i) ++cnt[a[i].key[p]];
for (int i = 1; i <= w[p]; ++i) cnt[i] += cnt[i - 1];
for (int i = n; i >= 1; --i)
b[cnt[a[i].key[p]]--] = a[i];
memcpy(a, b, sizeof(a));
}
void radix_sort() {
for (int i = k; i >= 1; --i) {
counting_sort(i);
}
}