参考网站 :
https://www.jianshu.com/p/6b526aa481b1

https://blog.csdn.net/alfa_/article/details/53819922

性质: 
     1.堆是一颗完全二叉树,用数组实现。 
     2.堆中存储数据的数据是局部有序的。
最大堆:1.任意一个结点存储的值都大于或等于其任意一个子结点中存储的值。 
     2.根结点存储着该树所有结点中的最大值。
最小堆:1.任意一个结点存储的值都小于或等于其任意一个子结点存储的值。 
     2.根结点存储着该树所有结点中的最小值。
无论最小堆还是最大堆,任何一个结点与其兄弟结点之间都没有必然联系。

建立堆的时间复杂度:

首先这个循环是从i = heap_size/2 -> 1,也就是说这是一个bottom-up的建堆。于是,有1/2的元素向下比较了一次,有1/4的向下比较了两次,1/8的,向下比较了3次,......,1/2^k 的向下比较了k次,其中1/2^k <= 1, k 约等于lg(n)。于是就有总的比较量:
https://www.zhihu.com/question/20729324

堆_第1张图片
从下往上堆建立复杂度计算过程

堆在构建的时候分两种:
1.从下往上构建,时间复杂度O(n)
2.从上往下构建,时间复杂度O(nlog2(n))

堆的每一次插入时间复杂度为O(log2(n))
堆的每一次删除时间复杂度为O(log2(n))

heap.h

//
//  heap.h
//  test
//
//  Created by 王璟 on 2019/6/10.
//  Copyright © 2019年 王璟. All rights reserved.
//

#ifndef HEAP_H
#define HEAP_H

#include 
using namespace std;

// 自定义最大堆的类型
template
class heap
{
private:
    T* data; // 具体类型的数据
    int heap_capacity; // 最大容量
    int heap_size; // 当前大小
    
    // 将该位置的元素与其下面的元素进行比较后,放置到正确的位置
    void sift_down(int pos);
    
    // 判断第一个元素是否大于第二个元素
    bool prior(const int a, const int b) const;
    
    // 交换值
    void swap(int pos1, int pos2);
    
    // 通过pos计算属于哪一层
    static int get_layer(int pos);
    
public:
    
    // 构造函数
    heap(T* _heap, int _size, int _capacity);
    
    // 当前堆的元素个数
    int size() const;
    
    // 当前堆的容量大小
    int capacity() const;
    
    // 判断是否为叶子结点
    bool is_leaf(int pos) const;
    
    // 左子节点的位置
    int left_child(int pos) const;
    
    // 右子节点的位置
    int right_child(int pos) const;
    
    // 父亲节点位置
    int parent(int pos) const;
    
    // 建立堆
    void build_heap();
    
    // 插入一个元素
    void insert(const T& val);
    
    // 移除根节点
    T remove_root();
    
    // 移除任意节点
    T remove(int pos);
    
    // 打印堆元素
    void print() const;
    
};

// 在函数后添加const表示不能修改class的成员
#endif /* heap_h */

heap.cpp

#include "heap.h"
#include 


// 构造函数
template
heap::heap(T* _heap, int _size, int _capacity)
{
    this->data = _heap;
    this->heap_size = _size;
    this->heap_capacity = _capacity;
}

// 将该位置的元素与其下面的元素进行比较后,放置到正确的位置
template
void heap::sift_down(int pos)
{
    while(!this->is_leaf(pos))
    {
        int left_child_pos = this->left_child(pos);
        int right_child_pos = this->right_child(pos);
        if(right_child_pos < this->size() && this->prior(right_child_pos, left_child_pos))
            left_child_pos = right_child_pos;
        if(this->prior(pos, left_child_pos))
            return ;
        this->swap(left_child_pos, pos);
        pos = left_child_pos;
    }
}


// 交换值
template
void heap::swap(int pos1, int pos2)
{
    T temp = this->data[pos1];
    this->data[pos1] = this->data[pos2];
    this->data[pos2] = temp;
}

// 当前堆的元素个数
template
int heap::size() const
{
    return this->heap_size;
}


// 当前堆的容量大小
template
int heap::capacity() const
{
    return this->heap_capacity;
}

// 比较元素大小
template
bool heap::prior(const int a, const int b) const
{
    return (this->data[a] > this->data[b]);
}

// 判断是否为叶子结点
template
bool heap::is_leaf(int pos) const
{
    if(2 * pos + 1 > this->heap_size - 1)
        return true;
    else
        return false;
}

// 左子节点的位置
template
int heap::left_child(int pos) const
{
    return pos * 2 + 1;
}

// 右边子节点的位置
template
int heap::right_child(int pos) const
{
    return pos * 2 + 2;
}

// 父亲节点位置
template
int heap::parent(int pos) const
{
    return (pos - 1) / 2;
}

// 建立堆
template
void heap::build_heap()
{
   // 从最后一个非叶子节点还是
    for(int i = this->size() / 2 - 1; i >= 0; --i)
        this->sift_down(i);
}

// 插入一个元素
template
void heap::insert(const T& val)
{
    if(this->size() + 1 > this->capacity())
    {
        cout<<"超过该最大堆的容量,无法添加新的元素到堆中"<data[this->heap_size++] = val;
    int cur_pos = this->size() - 1;
    while(cur_pos > 0 && this->prior(cur_pos, this->parent(cur_pos)))
    {
        this->swap(cur_pos, this->parent(cur_pos));
        cur_pos = this->parent(cur_pos);
    }
}

// 移除根节点
template
T heap::remove_root()
{
    if(this->heap_size > 0) {
        this->swap(0, --this->heap_size);
        this->sift_down(0);
        return this->data[this->heap_size];
    } else {
        cout << "堆中无任何元素" << endl;
        return NULL;
    }
}

// 移除任意节点
template
T heap::remove(int pos)
{
    if(pos >= this->size())
    {
        cout<<"pos范围超出当前最大堆元素个数,无效操作"<swap(pos, --this->heap_size);
    this->sift_down(pos);
    return this->data[this->heap_size];
}

// 打印堆元素
template
void heap::print() const
{
    for(int i = 0; i < this->size(); ++i)
        cout<data[i]<<"   ";
    cout<
int heap::get_layer(int pos)
{
    return log(pos + 1) / log(2) + 1;
}

int main()
{
    int head_data[8] = {1, 3, 6, 5, 10, 8, 0, 0};
    heap *_heap = new heap(head_data, 6, 8);
    _heap->build_heap();
    _heap->print();
    _heap->insert(9);
    _heap->print();
    _heap->remove(2);
    _heap->print();
    return 0;
}


你可能感兴趣的:(堆)