排序1 排序
方法一:插入排序
O(N^2)
#include
using namespace std;
const int N = 100010;
int n;
int a[N];
int main()
{
cin >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
for (int i = 1; i < n; i ++)
{
int tmp = a[i];
int j;
for (j = i; j > 0 && a[j - 1] > tmp; j --)
a[j] = a[j - 1];
a[j] = tmp;
}
for (int i = 0; i < n - 1; i ++)
printf("%d ", a[i]);
cout << a[n - 1];
return 0;
}
方法二:希尔排序
O(N^2)
#include
using namespace std;
const int N = 100010;
int n;
int a[N];
int main()
{
cin >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
for (int d = n / 2; d; d /= 2)
for (int i = d; i < n; i ++)
{
int tmp = a[i];
int j;
for (j = i; j >= d && a[j - d] > tmp; j -= d)
a[j] = a[j - d];
a[j] = tmp;
}
for (int i = 0; i < n - 1; i ++)
printf("%d ", a[i]);
cout << a[n - 1];
return 0;
}
方法三:堆排序
O(NlogN)
#include
using namespace std;
const int N = 100010;
int n;
int a[N];
// 将以root为根节点的堆调整成大根堆
void precdown(int root, int len)
{
int tmp = a[root];
int parent, child;
for (parent = root; (parent * 2 + 1) < len; parent = child)
{
child = parent * 2 + 1; // 左儿子节点
if (child + 1 < len && a[child + 1] > a[child]) child ++;
if (a[child] > tmp)
a[parent] = a[child];
else break;
}
a[parent] = tmp;
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
// 遍历所有根节点,建立大根堆
for (int i = n / 2 - 1; i >= 0; i --)
precdown(i, n);
// 每次将最大值与最后一个节点交换,然后维护一个长度 - 1的新大根堆
for (int i = n - 1; i; i --)
{
swap(a[0], a[i]);
precdown(0, i);
}
for (int i = 0; i < n - 1; i ++)
printf("%d ", a[i]);
cout << a[n - 1];
return 0;
}
方法四:归并排序
递归算法
O(NlogN)
#include
using namespace std;
const int N = 100010;
int n;
int a[N], tmp[N];
void merge_sort(int a[], int l, int r)
{
if (l >= r) return;
int mid = l + r >> 1;
merge_sort(a, l, mid), merge_sort(a, mid + 1, r);
int i = l, j = mid + 1, k = l;
while (i <= mid && j <= r)
{
if (a[i] > a[j]) tmp[k ++] = a[j ++];
else tmp[k ++] = a[i ++];
}
while (i <= mid) tmp[k ++] = a[i ++];
while (j <= r) tmp[k ++] = a[j ++];
i = k = l;
while (k <= r) a[i ++] = tmp[k ++];
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
merge_sort(a, 0, n - 1);
for (int i = 0; i < n - 1; i ++)
printf("%d ", a[i]);
cout << a[n - 1];
return 0;
}
非递归算法
#include
using namespace std;
const int N = 100010;
int n;
int a[N], tmp[N];
void merge(int a[], int tmp[], int l, int r, int r_end)
{
int l_end = r - 1;
int i = l, j = r, k = l;
while (i <= l_end && j <= r_end)
{
if (a[i] <= a[j]) tmp[k ++] = a[i ++];
else tmp[k ++] = a[j ++];
}
while (i <= l_end) tmp[k ++] = a[i ++];
while (j <= r_end) tmp[k ++] = a[j ++];
i = k = l;
while (i <= r_end) a[i ++] = tmp[k ++];
}
void merge_pass(int a[], int tmp[], int len)
{
int i;
for (i = 0; i <= n - 2 * len; i += 2 * len)
merge(a, tmp, i, i + len, i + 2 * len - 1);
if (i + len < n)
merge(a, tmp, i, i + len, n - 1);
else
for (int j = i; j < n; j ++)
tmp[j] = a[j];
}
void merge_sort()
{
int len = 1;
while (len < n)
{
merge_pass(a, tmp, len);
len *= 2;
}
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
merge_sort();
for (int i = 0; i < n - 1; i ++)
printf("%d ", a[i]);
cout << a[n - 1];
return 0;
}
排序2 Insert or Merge
分别用插入排序和归并排序,每一步操作后检查当前排序结果与所给序列是否一致。
#include
#include
using namespace std;
const int N = 110;
int n;
int a[N], tmp[N], target[N];
bool merge_flag;
bool match(int a[], int target[])
{
for (int i = 0; i < n; i ++)
if (a[i] != target[i])
return false;
return true;
}
void print_out(int a[])
{
for (int k = 0; k < n - 1; k ++)
printf("%d ", a[k]);
cout << a[n - 1];
}
bool insert_sort(int a[], int target[])
{
bool flag = false;
for (int i = 1; i < n; i ++)
{
int t = a[i];
int j;
for (j = i; j > 0 && a[j - 1] > t; j --)
a[j] = a[j - 1];
a[j] = t;
if (flag)
{
puts("Insertion Sort");
print_out(a);
return true;
}
flag = match(a, target);
}
return false;
}
void merge(int a[], int tmp[], int l, int r, int r_end)
{
int l_end = r - 1;
int i = l, j = r, k = l;
while (i <= l_end && j <= r_end)
{
if (a[i] <= a[j]) tmp[k ++] = a[i ++];
else tmp[k ++] = a[j ++];
}
while (i <= l_end) tmp[k ++] = a[i ++];
while (j <= r_end) tmp[k ++] = a[j ++];
i = k = l;
while (i <= r_end) a[i ++] = tmp[k ++];
}
void merge_pass(int a[], int tmp[], int len)
{
int i;
for (i = 0; i <= n - 2 * len; i += 2 * len)
merge(a, tmp, i, i + len, i + 2 * len - 1);
if (i + len < n)
merge(a, tmp, i, i + len, n - 1);
else
for (int j = i; j < n; j ++)
tmp[j] = a[j];
}
void merge_sort()
{
int len = 1;
while (len < n)
{
merge_pass(a, tmp, len);
len *= 2;
if (match(a, target))
{
merge_pass(a, tmp, len);
puts("Merge Sort");
print_out(a);
return;
}
}
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
for (int i = 0; i < n; i ++) cin >> target[i];
memcpy(tmp, a, sizeof a);
if (!insert_sort(a, target))
{
memcpy(a, tmp, sizeof a);
memset(tmp, 0, sizeof tmp);
merge_sort();
}
return 0;
}
排序3 Insertion or Heap Sort
#include
#include
using namespace std;
const int N = 110;
int n;
int a[N], target[N], backup[N];
bool insert_flag, heap_flag;
void print_out()
{
for (int i = 0; i < n - 1; i ++)
printf("%d ", a[i]);
cout << a[n - 1];
}
bool match()
{
for (int i = 0; i < n; i ++)
if (a[i] != target[i])
return false;
return true;
}
bool insert_sort()
{
for (int i = 1; i < n; i ++)
{
int tmp = a[i];
int j;
for (j = i; j > 0 && a[j - 1] > tmp; j --)
a[j] = a[j - 1];
a[j] = tmp;
if (insert_flag)
{
puts("Insertion Sort");
print_out();
return true;
}
if (match()) insert_flag = true;
}
return false;
}
void precdown(int root, int len)
{
int tmp = a[root];
int parent, child;
for (parent = root; (parent * 2 + 1) < len; parent = child)
{
child = parent * 2 + 1;
if ((child + 1) < len && a[child + 1] > a[child]) child ++;
if (a[child] > tmp) a[parent] = a[child];
else break;
}
a[parent] = tmp;
}
bool heap_sort()
{
for (int i = n / 2 - 1; i >= 0; i --)
precdown(i, n);
for (int i = n - 1; i; i --)
{
swap(a[0], a[i]);
precdown(0, i);
if (heap_flag)
{
puts("Heap Sort");
print_out();
return true;
}
if (match()) heap_flag = true;
}
return false;
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
for (int i = 0; i < n; i ++) cin >> target[i];
memcpy(backup, a, sizeof a);
if (!insert_sort())
{
memcpy(a, backup, sizeof a);
heap_sort();
}
return 0;
}