[灌水]d堆的實現與測試文件

#ifndef DHEAP_H_INCLUDED

#define DHEAP_H_INCLUDED

 

#include<vector>

#include<limits>

//#include<functional>

 

//#define DEBUG

 

// 一些輔助工具

namespace heap_aux{

    const int MAX_SIZE = std::numeric_limits<int>::max()-1;

 

    template<typename T> inline void swap(T& a, T& b){

       T tmp = a;

       a = b;

       b = tmp;

    }

 

    template<typename T>struct equal_to{

        bool operator()(const T& a, const T& b) const { return a == b ? true : false; }

    };

    template<typename T>struct not_equal_to{

        bool operator()(const T& a, const T& b) const { return a != b ? true : false; }

    };

    template<typename T>struct less{

        bool operator()(const T& a, const T& b) const { return a < b ? true : false; }

    };

    template<typename T>struct greater{

        bool operator()(const T& a, const T& b) const { return a > b ? true : false; }

    };

    template<typename T>struct less_equal{

        bool operator()(const T& a, const T& b) const { return a <= b ? true : false; }

    };

    template<typename T>struct greater_equal{

        bool operator()(const T& a, const T& b) const { return a >= b ? true : false; }

    };

 

    // 異常處理信息類

    struct heap_error{

       std::string error_info;

       heap_error(std::string _error_info) :error_info(_error_info) {}

    };

}

 

template<typename T, typename Compare = heap_aux::greater_equal<T> >

class dheap{

public: // contructors

    dheap(int _d = 2, const Compare& _comp = Compare()) : coll(0), d(_d), heapsize(0), comp(_comp){}

    dheap(size_t size, int _d = 2, const Compare& _comp = Compare()) : coll(size, 0), d(_d), heapsize(0), comp(_comp) {}

    dheap(std::vector<T> _coll, int _d = 2, const Compare& _comp = Compare()) : coll(_coll), d(_d), heapsize(_coll.size()), comp(_comp) {

       make_heap();

    }

    ~dheap(){}

 

public: // access functions

    inline const int get_heapsize() const { return heapsize;}

    inline const T& getTop() const{

       if(!heapsize){ //能在函數內解決,就不使用異常了

           std::cerr<<"heap is empty/n";

           return T();//這個處理其實不很優雅,我也不知道該怎麼處理更好

       }

       return *coll.begin();

    }

    inline const T& get_elem(int index) const{ return coll[index];}

 

public: // operations

    void insert(T item){

       int index = heapsize; // 初始時當然就是插入到數組尾部了

       if(index == heap_aux::MAX_SIZE){

           std::cerr<<"heap is full./n";

           return;

       }

 

       coll.push_back(item);

       ++heapsize;

       try{

           heapify(index, heapsize-1);

       }

       catch(heap_aux::heap_error& he){

           std::cerr<<he.error_info;

           return;

       }

    }

 

    void delete_heap(int index = 0){ // 默認刪除堆頂元素

       if(index == 0) heap_aux::swap(*coll.begin(), *(coll.end()-1));

       else{

           if(index > heapsize - 1){

              std::cerr<<"index exceeded/n";

              return;

           }

           heap_aux::swap(coll[index], *(coll.end()-1));

       }

 

       --heapsize;

 

       try{

           heapify(index, heapsize-1);

       }

       catch(heap_aux::heap_error& he){

           std::cerr<<he.error_info;

           return;

       }

    }

 

    void modify_top(T dest){ //默認修改堆頂元素

       if(coll.empty()){

           std::cerr<<"heap is empty./n";

           return;

       }

 

       T tmp = *coll.begin();

       *coll.begin() = dest;

       if(!comp(dest, tmp)){

           try{

              heapify(0, heapsize-1);

           }

           catch(heap_aux::heap_error& he){

              std::cerr<<he.error_info;

              return;

           }

       }

    }

 

    void merge(const dheap& other){

       for(int i = 0; i < other.get_heapsize(); ++i)

           coll.push_back(other.get_elem(i));

       heapsize += other.get_heapsize();

       make_heap();

    }

 

private: // inner auxiliaies

    inline void make_heap(){

       for(int i = (heapsize-2)/d; i>=0; --i){ //注意heapsize要減2

           try{

              heapify(i, heapsize-1);

           }

           catch(heap_aux::heap_error& he){

              std::cerr<<he.error_info;

              return;

           }

       }

    }

 

    inline void heapify(int start, int len){

       if(start > heapsize -1)

           throw heap_aux::heap_error("index exceed./n");

 

       int son = start*d+1; // 左子節點索引,因爲下標從0開始

       T item = coll[start];

       while(son <= len){

           if(son < len && (!comp(coll[son], coll[son+1])) )

                ++son;

           if(comp(item, coll[son]) ) break; // (*)

           coll[(son-1)/d] = coll[son]; //coll[son>>1]就是父節點,(*)行沒有break出去,說明違反堆性質

           son=son*d+1; //孫子節點

       }

       #ifdef DEBUG

            std::cout<<"DEBUG:/t";

            for(size_t i = 0; i < heapsize; ++i)

                std::cout<<coll[i]<<' ';

            std::cout<<"/n";

        #endif

       coll[(son-1)/d] = item;

    }

private:

    std::vector<T> coll;

    int d;

    int heapsize;

    Compare comp;

};

 

#endif // DHEAP_H_INCLUDED

 

 

 

// 以下爲Windows下測試文件,我實測的時候也對insert delete等操作做了測試,下面僅僅是建堆的測試,實際上要改爲insert那也很簡單

 

 

#include<iostream>

//#include<vector>

#include <windows.h>

#include"binaryheap.h"

 

#include"random.h" // 這個是個人寫的隨機數發生器,因爲我覺得系統默認的隨機數既慢且隨機性能不好,您用系統提供的也是可以的啦~

 

 

#define CORRECTNESS_MODE

//#define TIME_MODE

 

#ifdef CORRECTNESS_MODE

    #define E 4

    #define SZ (1<<E)

    #define C 5

#else // TIME_MODE

    #define E 20

    #define SZ (1<<E)

    #define C 20

#endif

 

template<typename T> inline void print_vector(const std::vector<T>& vec){

    std::cout<<"elements in vector:/n";

    for(size_t i = 0; i<vec.size(); ++i)

        std::cout<<vec[i]<<' ';

    std::cout<<"/n";

}

 

template<typename T>inline void print_heap(const binaryheap<T>& bh){

    std::cout<<"elements in binaryheap:/n";

    for(int i = 0; i < bh.get_heapsize(); ++i)

        std::cout<<bh.get_elem(i)<<' ';

    std::cout<<"/n";

}

 

// 嚴格說這個正確性測試方法是錯的,應該遞歸檢查是否滿足堆性質,由於我們的堆和STL的堆使用的算法一致,就偷懶了

template<typename T>inline void correntness_check(const binaryheap<T>& bh, const std::vector<T>& vec){

    for(int i = 0; i < bh.get_heapsize(); ++i){

        if( vec[i] != bh.get_elem(i) )

            std::cout<<"binaryheap works ERROR!!/n";

    }

    std::cout<<"binaryheap works fine!";

}

 

int main()

{

    std::vector<size_t> vnth(C), v1(SZ), v2; // v1STL測試數據, v2binaryheap測試數據       std::cout << "testing is in progress ..." << '/n';

    Sleep(1000);

 

    for(size_t i = 0; i < C; ++i)

    {

        for(size_t j = 0; j<SZ; ++j) v1[j] = irand();

        v2 = v1;

 

        std::cout<<"/n/nTest  "<<i<<"/n";

#ifdef TIME_MODE

        DWORD t1 = GetTickCount();

#endif

        make_heap(v1.begin(), v1.end());

 

#ifdef CORRECTNESS_MODE

        print_vector(v1);

#else //TIME_MODE

        std::cout<<"STL make_heap() used "<<GetTickCount() - t1<<"ms/n";

#endif

 

#ifdef TIME_MODE

        DWORD t2 = GetTickCount();

#endif

        binaryheap<size_t> bh(v2);

 

#ifdef CORRECTNESS_MODE

        print_heap(bh);

        correntness_check(bh, v1);

#else //TIME_MODE

        std::cout<<"binaryheap make heap used "<<GetTickCount() - t2<<"ms/n";

#endif

    }

        return 0;

}

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章