< 参考 >

参见【算法导论】第3版第6章【堆】
参见【具体数学】第2版第3章【整值函数】
参见 算法导论习题
参见【编程之美】第2章【2.5.寻找最大的K个数】
参见【stl源码剖析】第4章【4.7.heap】

< 准备 >

堆_第1张图片
图1: 一棵完全二叉树

1. 一棵完全二叉树深度为h的结点个数为 2h
2. 一棵高度为h的完全二叉树的结点个数 2h+11
注意:
a. 一棵完全二叉树保留前h深度的结点,去掉大于h深度的结点,剩下的仍然是一棵完全二叉树,其高度为h。
b. 深度为h的结点的个数比前h-1深度的结点个数大1。
3. floor函数和ceil函数定义:
x= 小于或等于x的最大整数
x= 大于或等于x的最小整数

堆_第2张图片
图2:floor函数和ceil函数

< 练习 >

6.1-1:
一棵高度为h的堆的元素个数最多为 2h+11 ,最少为 2h
6.1-2:
证明:含n个元素的堆的高度为 lgn
设树的高度为h,则 2hn<2h+1hlgn<h+1h=lgn
6.1-3:
证明:对于任一包含n个元素的堆中,至多有 n2h+1 个高度为h的结点。
P(h):对任意大小为n的堆,高度为h的结点 n2h+1
a. 当h=0时,高度为h(0)的结点就是叶结点,个数为 nn/2=n+n/2=nn/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/22k+1n/22k+1n2k+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的应用 >

  1. 优先队列
  2. 在大量的数据中寻找最小(大)的前k个数据。
  3. 将多个排序链表整合在一起,形成一个大的排序链表。

你可能感兴趣的:(堆)