【排序】堆排序

MyHeap.h

#ifndef MY_HEAP_H  
#define MY_HEAP_H  

#include<iostream>  
#include<vector>  

#define max_value -99999999  
//仿函数  
template<typename T>
struct MyLess{
    bool operator()(const T& x, const T& y) const { return x < y; }
};
template<typename T>
struct MyGreater{
    bool operator()(const T& x, const T& y) const { return x > y; }
};

template<typename T, typename Compare = MyLess<T>>
class MyHeap{
private:
    std::vector<T> vec; //堆的底层容器  
    int num_of_element; //堆中元素个数  
    const int start_index = 1; //堆在底层容器中从位置1开始  
    Compare comp;
public:
    //用了一个小技巧,将vector的#0元素保留,可知某节点位于vector的i处时,其左子节点位于2*i处,右子节点位于2*i+1处,父节点位于i/2处  
    MyHeap() :num_of_element(0){ vec.push_back(max_value); }
    template<typename RandomAccessIterator>
    void initial_heap(RandomAccessIterator begin, RandomAccessIterator end);
    void push_heap(T element);
    void pop_heap();
    void sort_heap();
    void make_heap();
    void percolate_up(int hole_index, T value); //上溯程序  
    void adjust_heap(int hole_index, T value); //调整程序,包括下溯操作和上溯操作  
    void print_heap();
    std::vector<T>& get_vector(){ return vec; }
};
//initial_heap(RandomAccessIterator begin, RandomAccessIterator end)  
template<typename T, typename Compare>
template<typename RandomAccessIterator>
void MyHeap<T, Compare>::initial_heap(RandomAccessIterator begin, RandomAccessIterator end){
    for (RandomAccessIterator it = begin; it != end; ++it){
        vec.push_back(*it);
        ++num_of_element;
    }
}
//push_heap(T element)  
template<typename T, typename Compare>
void MyHeap<T, Compare>::push_heap(T element){
    vec.push_back(element);
    ++num_of_element;
    percolate_up(num_of_element, element);
}
//percolate_up(int hole_index, T value)  
template<typename T, typename Compare>
void MyHeap<T, Compare>::percolate_up(int hole_index, T value){
    int parent = hole_index / 2; //找出洞节点的父节点  
    while (hole_index > start_index&&comp(vec[parent], value)){//没到顶点且父值小于插入值  
        vec[hole_index] = vec[parent];//洞值为父值  
        hole_index = parent; //调整洞号  
        parent = hole_index / 2; //新洞的父节点  
    }
    vec[hole_index] = value; //洞值为插入值  
}
//pop_heap()  
template<typename T, typename Compare>
void MyHeap<T, Compare>::pop_heap(){
    T adjust_value = vec[num_of_element];//堆的最后一个节点需要调整  
    vec[num_of_element] = vec[start_index];//vec中最后一个元素为最大值  
    --num_of_element; //堆中元素减1  
    adjust_heap(start_index, adjust_value);
}
//adjust_heap(int hole_index, T value)  
template<typename T, typename Compare>
void MyHeap<T, Compare>::adjust_heap(int hole_index, T value){
    int right_child = 2 * hole_index + 1; //洞节点的右子节点  
    while (right_child <= num_of_element){
        if (comp(vec[right_child], vec[right_child - 1])) //比较左右两个子节点的值  
            --right_child;
        vec[hole_index] = vec[right_child];//洞值为左右两个子节点中较大的值  
        hole_index = right_child; //调整洞号  
        right_child = 2 * hole_index + 1; //新洞节点的右子节点  
    }
    if (right_child == num_of_element + 1){ //没有右子节点,只有左子节点  
        vec[hole_index] = vec[right_child - 1]; //左子值为洞值  
        hole_index = right_child - 1;//洞节点为左子节点  
    }
    vec[hole_index] = value; //洞值为插入值  
    //percolate_up(hole_index, value); //此时可能尚未满足次序特性,执行上溯操作,可能有问题  
    //注意,跟STL源码剖析说执行一次percolate up操作有区别,执行一次可能会出错  
    int yejiedian = num_of_element;
    while (yejiedian >= hole_index){
        percolate_up(yejiedian, vec[yejiedian]); //此时可能尚未满足次序特性,执行上溯操作  
        --yejiedian;
    }
}
//sort_heap()  
template<typename T, typename Compare>
void MyHeap<T, Compare>::sort_heap(){
    while (num_of_element > 0)
        pop_heap();
}
//make_heap()  
template<typename T, typename Compare>
void MyHeap<T, Compare>::make_heap(){
    cout << "make heap过程:" << endl;
    if (num_of_element < 2) //长度为0或1,不必重新排列  
        return;
    int parent = num_of_element / 2; //第一个需要重排的子树头部  
    while (true){
        adjust_heap(parent, vec[parent]);
        print_heap();
        if (parent == 1) //走完根节点就结束  
            return;
        --parent;
    }
}
//print_heap()  
template<typename T, typename Compare>
void MyHeap<T, Compare>::print_heap(){
    for (int i = 1; i <= num_of_element; ++i)
        std::cout << vec[i] << " ";
    std::cout << std::endl;
}
#endif  
MyHeap.cpp

#include"MyHeap.h"  
using namespace std;

int main(){
    int ia[] = { 24, 26, 31, 13, 19, 21, 65, 68, 16 };  
    //int ia[] = { 24, 26, 31, 68, 19, 21, 13, 16, 65 };
    MyHeap<int> heap;
    cout << "大顶堆" << endl;
    heap.initial_heap(begin(ia), end(ia));
    cout << "initial heap:";
    heap.print_heap();

    heap.make_heap();
    cout << "make heap:";
    heap.print_heap();

    heap.push_heap(50);
    cout << "push heap:";
    heap.print_heap();

    heap.pop_heap();
    heap.get_vector().pop_back();
    cout << "pop heap:";
    heap.print_heap();

    heap.sort_heap();
    cout << "sort heap:";
    for (int i = 1; i <= 9; ++i)
        cout << heap.get_vector()[i] << " ";
    cout << endl;

    MyHeap<int, MyGreater<int>> heap2;
    cout << endl << "小顶堆" << endl;
    heap2.initial_heap(begin(ia), end(ia));
    cout << "initial heap:";
    heap2.print_heap();

    heap2.make_heap();
    cout << "make heap:";
    heap2.print_heap();

    heap2.push_heap(50);
    cout << "push heap:";
    heap2.print_heap();

    heap2.pop_heap();
    heap2.get_vector().pop_back();
    cout << "pop heap:";
    heap2.print_heap();

    heap2.sort_heap();
    cout << "sort heap:";
    for (int i = 1; i <= 9; ++i)
        cout << heap2.get_vector()[i] << " ";
    cout << endl;

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值