zoukankan      html  css  js  c++  java
  • 数据结构--大小根堆模板类(C++)

    一、大/小根堆成员属性:构造函数第二个参数决定大根堆与小根堆

    可以利用根堆求解大小位置的数组中前i大或者前i小的元素,也可以将其进行按大小排序。

    原理与特点:利用完全二叉树的父子结点在线性表中的索引关系,较为高效的利用空间去实现树形结构,并达到相关要求。这里以索引值 1 为堆顶元素索引作为展开。

      为了更好的去使用大小根堆,采用标志参数:max_heap和min_heap来实现大小根堆的切换,更好的降低了代码量,同时也能尽量保持功能的完整与执行的高效。

      (不完善的地方:应该改进存放容器方式,避免容器的再哈希产生不必要的时间开销,可以在构造对象的时候就确定容器的大小)

     1 #include<iostream>
     2 #include<stdlib.h>
     3 #include<vector>
     4 #include<ctime> 
     5 #define Size long long
     6 using namespace std;
     7 template<typename P>
     8 class heap{
     9     private:
    10         Size heap_size;//容量限制 
    11         Size heap_count;//数据计数 
    12         vector<P> heap_elem;//堆容器 
    13         int maxmin_heap;//选择大小根堆 
    14         
    15         void Up_adjust(int now);//上浮调整 
    16         void Down_adjust(P &top, int now);//下沉调整 
    17     public:
    18         enum{max_heap=1, min_heap=-1};
    19         heap(Size s, int m=max_heap)://构造堆 
    20             heap_size(s){
    21             heap_count=0;
    22             heap_elem.push_back(-999);
    23             maxmin_heap=m;//default max_heap
    24         };
    25         P getTop(){//弹获取堆顶元素 
    26             if(heap_count>0)return heap_elem[1];
    27             return heap_elem[0]*maxmin_heap;
    28         } 
    29         bool empty(){//判断堆空 
    30             if(heap_count==0)return true;
    31             return false;
    32         }
    33         void push(P x);//送元素入堆 
    34         P pop();//堆顶元素弹出 
    35         void Delete(int i);//删除第i个元素 
    36         void data();//打印堆
    37 }; 

    二、大小根堆成员函数:

    1.插入元素:将新元素放入堆底,执行上浮调整,使其合理

    1 template<typename P>
    2 void heap<P>::push(P x){
    3     ++heap_count;
    4     heap_elem.push_back(x*maxmin_heap);
    5     int now=heap_count;
    6     Up_adjust(now);
    7     if(heap_count>heap_size-1)
    8         heap_count--;
    9 }

    2.弹出元素:

    template<typename P>
    P heap<P>::pop(){
        this->Delete(0);
        return getTop()*maxmin_heap;
    }

    3.删除元素:

    用堆底元素替换,并通过下沉调整,使其合理

     1 template<typename P>
     2 void heap<P>::Delete(int i){
     3     if(i>heap_count) return;
     4     cout << "delete heap["<< i <<"]: " << heap_elem[i]*maxmin_heap << endl;
     5     if(i==heap_count){
     6         heap_count--;
     7         return ;}
     8     Down_adjust(heap_elem[heap_count],i);
     9     heap_count--;
    10 }

    4.上浮调整:

    1 template<typename P>
    2 void heap<P>::Up_adjust(int now){
    3     while(now>1 && heap_elem[now]>heap_elem[now/2]){
    4         std::swap(heap_elem[now], heap_elem[now/2]);
    5         now=now/2;
    6     }
    7 }

    5.下沉调整:

     1 template<typename P>
     2 void heap<P>::Down_adjust(P &top, int now){
     3     heap_elem[now]=top;
     4     int next1,next2;
     5     while(now*2<=heap_count){
     6         if(now*2+1>heap_count){
     7             next1=next2=now*2;
     8         }
     9         else{
    10             next1 = heap_elem[now*2]>heap_elem[now*2+1] ? now*2 : now*2+1;
    11             next2 = heap_elem[now*2]<heap_elem[now*2+1] ? now*2 : now*2+1;    
    12         } 
    13         if(heap_elem[next1]>heap_elem[now]){
    14             swap(heap_elem[next1],heap_elem[now]);
    15             now = next1;
    16         }
    17         else if(heap_elem[next2]>heap_elem[now]){
    18             swap(heap_elem[next2],heap_elem[now]);
    19             now = next2;
    20         }
    21         else{
    22             break;
    23         }
    24     }    
    25 }

    6.数据打印:

    1 template<typename P>
    2 void heap<P>::data(){
    3     typename std::vector<P>::iterator itr=heap_elem.begin()+1;
    4     cout << "heap[]: ";
    5     for(int i=0;i<heap_count && i<heap_size;++i){
    6         cout << *(itr+i)*maxmin_heap << ' ';
    7     }
    8     cout << endl;
    9 }

    三、代码测试:以小根堆为例

    可以注释掉标准输出语句,来减少执行操作的时间消耗,能更好测试大量数据插入、删除的实行时间。

     1 int main(){
     2     heap<int> h(20,heap<int>::min_heap);
     3     int x;
     4     srand(time(NULL));
     5     for(int i=0;i < 20;++i){
     6         x = rand()%1000;
     7         h.push(x);
     8         //h.data();
     9     }
    10     h.data();
    11     h.Delete(4);
    12     while(!h.empty()){
    13         h.pop();
    14     }
    15     cout << endl;
    16     return 0;
    17 }

  • 相关阅读:
    jsp mysql 配置线程池
    服务端 模拟 检测 攻击。。乱写
    硕思闪客精灵 7.2 破解版
    unity UnityAwe 插件
    smartfoxserver 2x 解决 Math NAN
    unity 断点下载
    java 监听文件目录修改
    wind7 64 setup appjs
    sfs2x 修改jvm 内存
    unity ngui 解决图层问题
  • 原文地址:https://www.cnblogs.com/lzw265/p/12194703.html
Copyright © 2011-2022 走看看