堆排序:先通过对每个结点进行下滤操作,自底向上建堆。每次从堆顶拿出一个最大的元素,和堆末尾的元素交换,然后缩小堆的大小(-1),然后将从堆末尾交换上来的元素下滤,以恢复堆的根结点值总比子结点大的特性。
为了让下滤操作不越界,将数组开得较大,并且初值设为int最小值。
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int MIN = 0x80000000;
int n;
vector<int> initial(200), partial(200);
//比较当前数组v和部分排序的数组
bool check(vector<int> v) {
for (int i = 0;i < n;i++) {
if (v[i] != partial[i])
return false;
}
return true;
}
bool isInsertionSort = false;
void insertionSort(vector<int> v) {
for (int i = 1;i < n;i++) {
int temp = v[i],
pos = i; //v[i]插入位置
while (pos > 0 && v[pos - 1] > temp) {
v[pos] = v[pos - 1];
pos--;
}
v[pos] = temp;
if (isInsertionSort == true) {
printf("Insertion Sort\n");
for (int j = 0;j < n;j++) {
if (j != 0)
printf(" ");
printf("%d", v[j]);
}
return;
}
isInsertionSort = check(v);
}
}
void percolateDown(int index, int rear) {
int left = index * 2 + 1, right = index * 2 + 2;
while (left < rear) {
int pos = initial[left] > initial[right] ? left : right;
if (initial[pos] <= initial[index]) {
break;
}
int temp = initial[index];
initial[index] = initial[pos];
initial[pos] = temp;
index = pos;
left = index * 2 + 1, right = index * 2 + 2;
}
}
bool isHeapSort = false;
void heapSort() {
for (int i = n - 1;i >= 0;i--) {
percolateDown(i, n);
}
int rear = n;
while (rear > 0) {
int temp = initial[0];
initial[0] = initial[rear - 1];
percolateDown(0, rear - 1);
initial[rear - 1] = temp;
rear--;
if (isHeapSort) {
printf("Heap Sort\n");
for (int j = 0;j < n;j++) {
if (j != 0)
printf(" ");
printf("%d", initial[j]);
}
return;
}
if (check(initial))
isHeapSort = true;
}
}
int main() {
fill(initial.begin(), initial.end(), MIN);
scanf("%d", &n);
for (int i = 0;i < n;i++) {
scanf("%d", &initial[i]);
}
for (int i = 0;i < n;i++) {
scanf("%d", &partial[i]);
}
insertionSort(initial);
if (!isInsertionSort) {
heapSort();
}
}
二刷:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int MIN = 0xffffffff;
int n;
vector<int> initial, partial; //最初的数组和部分排序的数组
//比较两数组各元素是否完全吻合
bool match(vector<int> &a, vector<int> &b) {
for (int i = 0; i < n; i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
}
bool isInsertionSort = false;
vector<int> insertion;
void tryInsertionSort() {
insertion = initial;
for (int i = 1; i < n; i++) {
//将未排序子列最前面的一个元素加入到已排序的子列中
int j = i;
while (j >= 1 && insertion[j] < insertion[j - 1]) {
swap(insertion[j], insertion[j - 1]);
--j;
}
if (isInsertionSort) {
return;
}
if (match(insertion, partial)) {
isInsertionSort = true;
}
}
}
//对下标为index的结点进行下滤,range为下滤的范围
void percolateDown(int index, int range) {
//choose a larger number among its childen
while (index <= range) {
int left = 2 * index + 1, right = 2 * index + 2;
int leftVal = MIN, rightVal = MIN;
if (left <= range) {
leftVal = initial[left];
}
if (right <= range) {
rightVal = initial[right];
}
if (initial[index] > max(leftVal, rightVal)) {
return;
}
int next = leftVal > rightVal ? left : right;
swap(initial[index], initial[next]);
index = next;
}
}
void print(vector<int> &v) {
for (int i = 0; i < n; i++) {
if (i != 0) {
cout << " ";
}
cout << v[i];
}
}
bool isMatch = false;
void heapSort() {
int last = n - 1;
//build heap
//建堆:对每个结点自底向上下滤一遍
for (int i = n - 1; i >= 0; i--) {
percolateDown(i, last);
}
for (int i = 0; i < n; i++) {
swap(initial[last], initial[0]); //每次从堆顶拿最大的元素和数组末尾的元素交换
percolateDown(0, --last); //缩小堆的范围(last—-),然后将从末尾换上来的元素下滤,以恢复堆的结构
if (isMatch) {
cout << "Heap Sort" << endl;
print(initial);
return;
}
if (match(initial, partial)) {
isMatch = true;
}
}
}
int main() {
cin >> n;
initial.resize(n);
partial.resize(n);
for (int i = 0; i < n; i++) {
cin >> initial[i];
}
for (int i = 0; i < n; i++) {
cin >> partial[i];
}
tryInsertionSort();
if (isInsertionSort) {
cout << "Insertion Sort" << endl;
print(insertion);
}
else {
heapSort();
}
}