堆
< 参考 >
参见【算法导论】第3版第6章【堆】
参见【具体数学】第2版第3章【整值函数】
参见 算法导论习题
参见【编程之美】第2章【2.5.寻找最大的K个数】
参见【stl源码剖析】第4章【4.7.heap】
< 准备 >
![]()
图1: 一棵完全二叉树
1. 一棵完全二叉树深度为h的结点个数为 2h 。
2. 一棵高度为h的完全二叉树的结点个数 2h+1−1
注意:
a. 一棵完全二叉树保留前h深度的结点,去掉大于h深度的结点,剩下的仍然是一棵完全二叉树,其高度为h。
b. 深度为h的结点的个数比前h-1深度的结点个数大1。
3. floor函数和ceil函数定义:
⌊x⌋= 小于或等于x的最大整数
⌈x⌉= 大于或等于x的最小整数![]()
图2:floor函数和ceil函数
< 练习 >
6.1-1:
一棵高度为h的堆的元素个数最多为 2h+1−1 ,最少为 2h
6.1-2:
证明:含n个元素的堆的高度为 ⌊lgn⌋ 。
设树的高度为h,则 2h≤n<2h+1⇒h≤lgn<h+1⇒h=⌊lgn⌋
6.1-3:
证明:对于任一包含n个元素的堆中,至多有 ⌈n2h+1⌉ 个高度为h的结点。
P(h):对任意大小为n的堆,高度为h的结点 ≤⌈n2h+1⌉ 。
a. 当h=0时,高度为h(0)的结点就是叶结点,个数为 n−⌊n/2⌋=n+⌈−n/2⌉=⌈n−n/2⌉=⌈n/2⌉=⌈n20+1⌉ , P(0)成立。
b. 假设P(k)成立。
证明P(k+1)成立:
将任意一个大小为n的堆A,去掉A的叶结点后,剩下的树仍然满足堆的性质,构成堆B,在A中高度为k+1的结点在B中的高度为k,B的结点的个数为 ⌊n/2⌋ ,P(k)成立,所以B中高度为k的结点个数 ≤⌈⌊n/2⌋2k+1⌉≤⌈n/22k+1⌉≤⌈n2k+1+1⌉ 。所以P(k+1)成立。
c. 综上,P(h)成立。
< code >
< MyHeap.h >
#include<vector>
#include<iterator>
using namespace std;
//
class Myheap{
public:
vector<int> Heaptree;
int size;
public://堆的外部接口
Myheap(vector<int> &data);
void insert_element(int element);
int delete_element(int index);
void heap_sort();
int heap_maximum(){ return Heaptree[0]; }
private://堆的内部接口
void max_heapify(int index);
void max_heapup(int index);
void build_max_heap();
inline int parent(int i){
if (i>0)
return (i - 1) / 2;
return -1;
}
inline int left(int i){
if (2*i+1<size)
return 2 * i + 1;
return -1;
}
inline int right(int i){
if (2*i+2<size)
return 2 * i + 2;
return -1;
}
};
< MyHeap.cpp >
#ifndef MYHEAP_
#define MYHEAP_
#include "MyHeap.h"
Myheap::Myheap(vector<int>&data){
copy(data.begin(), data.end(), back_inserter(Heaptree));
this->size = Heaptree.size();
build_max_heap();
}
void Myheap::max_heapify(int index){
int left = this->left(index);
int right = this->right(index);
if (left == -1) return;
int bigger = left;
if (right!=-1&&Heaptree[left] < Heaptree[right]){
bigger = right;
}
if (Heaptree[bigger]>Heaptree[index]){
int temp = Heaptree[bigger];
Heaptree[bigger] = Heaptree[index];
Heaptree[index] = temp;
max_heapify(bigger);
}
}
void Myheap::max_heapup(int index){
int parent =this->parent(index);
if (parent == -1) return;
if (Heaptree[index] > Heaptree[parent]){
int key = Heaptree[index];
Heaptree[index] = Heaptree[parent];
Heaptree[parent] = key;
max_heapup(parent);
}
}
void Myheap::build_max_heap(){
for (int i = parent(size - 1); i >= 0; i--)
max_heapify(i);
}
void Myheap::insert_element(int element){
Heaptree.push_back(element);
max_heapup(size);
size++;
}
int Myheap::delete_element(int index){
Heaptree[index] = Heaptree[--size];
max_heapify(index);
return Heaptree[size];
}
void Myheap::heap_sort(){
int temp;
int memosize = size;
while(size>1){
temp = Heaptree[--size];
Heaptree[size] = Heaptree[0];
Heaptree[0] = temp;
max_heapify(0);
}
size = memosize;
}
#endif
< Main >
#include<iostream>
#include"MyHeap.h"
int main(){
vector<int>data;
cout <<"输入数据:"<< endl;
copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(data));
cin.clear(), cin.sync();
Myheap heap(data);
cout << "before heap sort" << endl;
for (int i(0); i < heap.size;i++)
cout << heap.Heaptree[i] << " ";
cout <<"堆的最大值:"<< heap.heap_maximum() << endl;
heap.heap_sort();
cout << "after heap sort" << endl;
for (int i(0); i < heap.size; i++)
cout << heap.Heaptree[i] << " ";
cout << endl;
system("pause");
return 0;
}
< heap的应用 >
- 优先队列
- 在大量的数据中寻找最小(大)的前k个数据。
- 将多个排序链表整合在一起,形成一个大的排序链表。