一.定义
大顶堆:根结点最大的完全二叉树;
小顶堆:根结点最小的完全二叉树;
(以下以大顶堆为例)
用数组的形式定义堆:
const int maxn = 100;
int n;
int heap[maxn];
二.基本操作
1.建堆:
a.向下调整:(将当前结点与它的左右孩子节点比较,按照大小关系交换,若交换则继续与孩子节点比较)
void downAdjust(int low, int high) {
// low 是欲调整节点的数组下标,high 为堆最后一个元素
int i = low, j = i * 2; // i 为欲调整结点,j 为左孩子
while(j <= high) { //如果 i 的孩子结点存在
if(j + 1 <= high && heap[j + 1] > heap[j]) j = j + 1;
if(heap[j] > heap[i]) {
swap(heap[j], heap[i]);
i = j;
j = i * 2;
}
else break;
}
}
b.建堆:(欲调整的结点从数组下标最大的非叶结点开始)
完全二叉树:1 ~ n/2:非叶子节点;n/2+1 及之后是叶子节点(共 n/2 个)
void createHeap() {
for(int i = n / 2; i >= 1; i--) downAdjust(i, n);
}
2.删除堆顶元素:
void deleteTop() {
heap[1] = heap[n--];
downAdjust(1, n);
}
3.添加一个元素:
把想要添加的元素放在数组最后,然后进行向上调整;
a.向上调整:
void uoAdjust(int low, int high) {
// low 一般设置为 1,high 表示欲调整结点的数组下标
int i = high, j = i / 2;
while(j >= low) {
if(heap[j] < heap[i]) {
swap(heap[j], heap[i]);
i = j;
j = i / 2;
}
else break;
}
}
b.添加元素:
void insert(int x) {
heap[++n] = x;
upAdjust(1, n);
}
4.堆排序
将堆顶元素与当前最后一个元素交换,然后进行排序(堆顶元素固定);
void heapSort() {
createHeap();
for(int i = n; i > 1; i--) {
swap(heap[i], heap[1]);
downAdjust(1, i - 1);
}
}
三.题目
1.PAT A1098
思路:
先判断是不是 insertSort ,如果不是则一定是 heapSort;
注意:
1).判断两数组相等不能是 A == B;
2).如何输出下一个数组:先判断是否相等(flag = true),在主函数体又进行一遍后,如果相等(flag = true)则输出数组;
3).第一次排完序后记得把数组还原;
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 110;
int n;
int ori[maxn];
int tempori[maxn];
int changed[maxn];
bool isSame(int A[], int B[]) {
for(int i = 1; i <= n; i++) {
if(A[i] != B[i]) return false;
}
return true;
}
void showArray(int A[]) {
for(int i = 1; i <= n; i++) {
printf("%d", A[i]);
if(i < n) printf(" ");
}
printf("\n");
}
void downAdjust(int low, int high) {
int i = low, j = i * 2;
while(j <= high) {
if(j + 1 <= high && ori[j] < ori[j + 1]) j = j + 1;
if(ori[j] > ori[i]) {
swap(ori[j], ori[i]);
i = j;
j = i * 2;
}
else break;
}
}
void createHeap() {
for(int i = n / 2; i >= 1; i--) downAdjust(i, n);
}
void heapSort() {
createHeap();
bool flag = false;
for(int i = n; i > 1; i--) {
if(i != n && isSame(ori, changed)) flag = true;
swap(ori[1], ori[i]);
downAdjust(1, i - 1);
if(flag) {
showArray(ori);
return;
}
}
}
bool insertSort() {
bool flag = false;
for(int i = 2; i <= n; i ++) {
if(i != 2 && isSame(ori, changed)) flag = true;
sort(ori, ori + i + 1);
if(flag == true) return true;
}
return false;
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &ori[i]);
tempori[i] = ori[i];
}
for(int i = 1; i <= n; i++) scanf("%d", &changed[i]);
if(insertSort()) {
printf("Insertion Sort\n");
showArray(ori);
}
else {
printf("Heap Sort\n");
for(int i = 1; i <= n; i++) ori[i] = tempori[i];
heapSort();
}
return 0;
}