关闭

大顶堆以及堆排序

390人阅读 评论(1) 收藏 举报
分类:

大顶堆的前提是一颗完全二叉树,随后其根节点都大于左右子树 则称为大顶堆 否则为小顶堆 

首先介绍下堆调整,堆是一种数据结构,是一种完全二叉树(不一定是满二叉树),所以根节点与叶子节点满足关系如下:根节点下标为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大的数


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:72707次
    • 积分:2603
    • 等级:
    • 排名:第14577名
    • 原创:197篇
    • 转载:0篇
    • 译文:0篇
    • 评论:5条
    最新评论