大顶堆的前提是一颗完全二叉树,随后其根节点都大于左右子树 则称为大顶堆 否则为小顶堆
首先介绍下堆调整,堆是一种数据结构,是一种完全二叉树(不一定是满二叉树),所以根节点与叶子节点满足关系如下:根节点下标为i,左叶子为下标2*i,右叶子下标为2*i+1,当然这里我们用数组来对堆进行存储。堆的子树必须满足如下关系,根节点大于左子树且大于右子树。
堆调整的方法如下,检测根节点是否为叶子节点,是退出,否调出子树中最大的值作为根节点,并对受影响的叶子节点进行递归调整。
主要的博客是这两个 个人感觉写的挺好的
http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html
http://www.cnblogs.com/mengdd/archive/2012/11/30/2796845.html 这里面的图可以作为参考
http://www.cnblogs.com/Jason-Damon/archive/2012/04/18/2454649.html
随后主要是堆排序的实现 实质上就是先根部的三个进行排序 把最大的或最小的先找出来,随后与最后一个,或者最后第二个进行调换位置,最后便成为了一个大顶堆 实质上的复杂度为nlogn 并不高
下面附上自己的代码
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
int a[10001];
//调整堆 现在最上面的根和他的左孩子还有右孩子进行比较
//把最大的找出来放在栈顶
void heapAdjust(int a[], int i, int size) {
//左右孩子的节点先确定
int lchild = 2 * i;
int rchild = 2 * i + 1;
//临时变量
int max = i;
//不是叶节点才进行调整
if (i <= size / 2) {
if (lchild <= size&&a[lchild] < a[max]) {
max = lchild;
}
if (rchild <= size&&a[rchild] < a[max]) {
max = rchild;
}
if (max != i) {
int temp = a[i];
a[i] = a[max];
a[max] = temp;
//这一步必须要加 避免max为父节点的子树不是堆
heapAdjust(a, max, size);
}
}
}
//建立最大堆
void BuildHeap(int a[], int size) {
int i;
//从第一个不是叶节点的size/2开始建立堆
for (i = size/2; i >= 1; i--) {
heapAdjust(a, i, size);
}
}
//堆排序
void heapSort(int a[], int size) {
int i;
BuildHeap(a, size);
for (i = size; i >= 1; i--) {
//都将第一个元素和倒数第i元素进行替换,随后进行一次堆的调整
int temp = a[i];
a[i] = a[1];
a[1] = temp;
heapAdjust(a, 1, i - 1);
}
}
int main() {
int n, k;
while (cin >> n&&n) {
cin >> k;
for (int i = 1; i <= n; i++)
cin >> a[i];
heapSort(a, n);
cout << a[k] << endl;
}
return 0;
}
要注意一直是逆序的进行排序,也就是size/2 否则会出错
题意是输进n个数 求第k大的数