排序
输⼊: 待排序的数组a[]
, 元素个数n
输出: 已排序的数组a[]
1. 插入排序
n-1
趟排序
0<i<n
第i趟排序处理a[i]
, 前i
个元素有序, 将a[i]
插⼊合适的位置
void insertsort(int n) {
int i, j;
int t;
for (i = 1; i < n; ++i) {
t = a[i];
for (j = i; j > 0 && a[j - 1] > t; --j) //查找插入位置并移动元素
a[j] = a[j - 1];
a[j] = t; //插入
}
}
1.5. *折半插入排序
todo
2. 冒泡排序
n-1
次处理
0<i<n
每次处理使最⼤元素沉底
void bubblesort(int n) {
int i, j;
for (i = 1; i < n; ++i)
for (j = 0; j < n - i; ++j)
if (a[j] > a[j + 1]){
int t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
}
}
3. 选择排序
n-1
次处理
0<i<n
每次处理使最⼤元素沉底
void choosesort(int n) {
int i, j;
for (i = 1; i < n; ++i) {
int max = INT32_MIN;
int maxj = 0;
for (j = 0; j <= n - i; ++j)
if (a[j] > max) {
maxj = j;
max = a[j];
}
a[maxj] = a[n - i];
a[n - i] = max;
}
}
4. 希尔排序
步⻓为k
的插⼊排序称为k-排序
k-排序考察a[k]~a[n-1]
, 使k个子序列有序
k值的序列称为增量序列,增量序列的选择影响希尔排序的效率,⼀个较简单的增量序列如下所示,但效率不⾼
希尔排序通过⼀系列的k-排序最终使序列有序
void shellsort(int n) {
int i, j, k;
int t;
for(k = n / 2; k > 0; k /= 2)
for (i = k; i < n; ++i) {
t = a[i];
for (j = i; j >= k && a[j - k] > t; j -= k)
a[j] = a[j - k];
a[j] = t;
}
}
5. 堆排序
将所有元素加⼊堆,再⼀个⼀个弹出
//堆的数据结构及操作略
void heapsort(int n) {
int i;
for (i = 0; i < n; ++i)
insert(a[i]);
for (i = 0; i < n; ++i) {
a[i] = heapmin();
ddelete();
}
}
6. 归并排序
void gbsort(int left, int right) {
if (left >= right) return;
int mid = (left + right) / 2;
gbsort(left, mid);
gbsort(mid + 1, right);
int i, j, k, l;
for (i = left, j = mid + 1, k = 0; i <= mid && j <= right; ) { //合并
if (a[i] <= a[j])
b[k++] = a[i++];
else
b[k++] = a[j++];
}
if (i > mid)
for (; j <= right; ++j)
b[k++] = a[j];
else
for (; i <= mid; ++i)
b[k++] = a[i];
for (i = left, l = 0; l < k; ++i, ++l) { //复制数组
a[i] = b[l];
}
}
7. 快速排序
快速排序很令⼈头疼
选取枢纽元:
三数取中法
选取a[left]
,a[mid]
,a[right]
的中位数作为枢纽元
避免数组基本有序时时间复杂度退化成⼆次
同时保证a[left] ≤ a[mid] ≤ a[right]
⽅便下⼀步处理
分割策略:
- 将枢纽元(a[mid])与最后⼀个元素(a[right - 1])交换
- l从第⼀个元素(left + 1)开始,r从倒数第⼆个元素(right - 2)开始
- 当l在r的左边时,将l右移,移过小于枢纽元的元素,将r左移,移过大于枢纽元
的元素
当l和r停止时,如果l仍在r的左边,则交换这两个元素 - 当l和r交错后,将枢纽元与l位置元素互换
避免数组元素大小相同时时间复杂度退化成⼆次
小数组优化:
对于小数组使用插入排序
#define CUTOFF 10
int mid3(int left, int right) { //三数取中
int mid = (left + right) / 2;
if (a[left] > a[mid]) {
int t = a[left];
a[left] = a[mid];
a[mid] = t;
}
if (a[left] > a[right]) {
int t = a[left];
a[left] = a[right];
a[right] = t;
}
if (a[mid] > a[right]) {
int t = a[mid];
a[mid] = a[right];
a[right] = t;
}
int t = a[mid];
a[mid] = a[right - 1];
a[right - 1] = t;
return a[right - 1];
}
//insertsort()见插入排序
void quicksort(int left, int right) {
if (left + CUTOFF <= right) {
int x = mid3(left, right);
int l = left, r = right - 1;
for ( ; ; ) {
while (a[++l] < x);
while (a[--r] > x);
if (l < r) {
int t = a[l];
a[l] = a[r];
a[r] = t;
}
else break;
}
int t = a[l];
a[l] = a[right - 1];
a[right - 1] = t;
quicksort(left, l - 1);
quicksort(l + 1, right);
}
else
insertsort(left, right - left + 1);
}
8. 桶排序
线性时间排序算法
*代码略