堆排序
1.建堆。n个数存放于数组里,下表从1到n。叶子下标则是:n/2+1, n/2+2...n。建堆的时候从最后一个非叶子节点到第一个节点,不断进行调整。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
void MaxHeapify(int maxHeap[], int n, int nowPos) {
int left, right, largest;
left = nowPos << 1;
right = (nowPos<<1|1);
largest = nowPos;
if(left <= n && maxHeap[left] > maxHeap[nowPos])
largest = left;
if(right <= n && maxHeap[right] > maxHeap[largest])
largest = right;
if(largest != nowPos) {
swap(maxHeap[nowPos], maxHeap[largest]);
MaxHeapify(maxHeap, n, largest);
}
}
void buildMaxHeap(int maxHeap[], int n) {
for(int i = n/2; i >= 1; --i)
MaxHeapify(maxHeap, n, i);
}
int main() {
int maxHeap[50] = {0, 4, 1, 3, 2, 16, 9, 10, 14, 8, 7};
buildMaxHeap(maxHeap, 10);
return 0;
}
2.堆排序。先用buildMaxHeap将输入的数组A[1...n]建成大顶堆。因为最大元素在A[1],交换A[1]和A[n]将数放入最终的位置,接着用MaxHeapify()调整A[1...n-1]建成大顶堆,不断重复这个过程。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
void MaxHeapify(int maxHeap[], int n, int nowPos) {
int left, right, largest;
left = nowPos << 1;
right = (nowPos<<1|1);
largest = nowPos;
if(left <= n && maxHeap[left] > maxHeap[nowPos])
largest = left;
if(right <= n && maxHeap[right] > maxHeap[largest])
largest = right;
if(largest != nowPos) {
swap(maxHeap[nowPos], maxHeap[largest]);
MaxHeapify(maxHeap, n, largest);
}
}
void buildMaxHeap(int maxHeap[], int n) {
for(int i = n/2; i >= 1; --i)
MaxHeapify(maxHeap, n, i);
}
void HeapSort(int maxHeap[], int n) {
buildMaxHeap(maxHeap, 10);
for(int i = n; i >= 2; --i) {
swap(maxHeap[1], maxHeap[i]);
MaxHeapify(maxHeap, i-1, 1);
}
}
int main() {
int maxHeap[50] = {0, 4, 1, 3, 2, 16, 9, 10, 14, 8, 7};
HeapSort(maxHeap, 10);
for(int i = 1; i <= 10; ++i) printf("%d ", maxHeap[i]);
return 0;
}
3.建堆效率。很容易会以为建堆的效率是nlogn,因为外层n的循环里还有个沿着树自上而下的调整。实际效率为o(n)。
假设一棵平衡二叉树的高度为h,则第一层的节点数为2^0,最后一层非叶子节点的节点数为2^(n-2)。最后一层非叶子节点要调整的深度为1,向上依次为2,3...n-1。
所以,建堆总的时间:
T=2^(h-2)*1 + 2^(h-3)*2 + ... + 2^1 * (h-2) + 1 * (h-1); (1)式 (1)*2可得
2*T=2^(h-1)*1 + 2^(h-2)*2 + ... + 2^2*(h-2) + 2*(h-1); (2)式 (2)-(1)得
2T-T = T = 2^(h-1) + 2^(h-2) + ...+ 2^1 - h + 1 = 2^h - h - 1;
又h = logn,所以T = n + logn + 1;故效率为o(n)。
浙公网安备 33010602011771号