1.最小堆实现

来源:互联网 发布:openwrt安装mysql 编辑:程序博客网 时间:2024/05/22 06:53

1.说明
现在开始注重编写一些公共的库,方便自己以后复用,为了提高复用性,采用了模板的方式,同时将这些库发布出来,供大家参考,如有问题或意见请发邮件zhang_int@sina.cn

2.最小堆
至于最小堆的思想,原理等再此就略过吧,结构很简单就不画UML了,简单说明下:
MinHeap.h:最小堆基类,对外部提供接口,方便以后扩展,如采用二叉树形式等
MinHeapArray.h:最小堆的具体实现,采用了数组的形式
Lock.h:线程锁的封装,封装库为ptherad,所以使用线程安全模式时,不支持跨平台
client.cpp:测试用例
现在就直接用代码说话

3.代码实现

//抽象的外部接口和基类 MinHeap.h #ifndef __MINHEAP_H#define __MINHEAP_H#include <string>#include <pthread.h>#include "Lock.h"/**@brief:外部对外抽象的接口,通过接口操作即可*@author:zp*/template <class TYPE>class CMinHeap{public:     CMinHeap(){}    virtual ~CMinHeap(){}    ///@brief:添加元素,采用从上往下移动方式       virtual bool add(const TYPE p) = 0;    ///@brief:获取小根堆头结点     ///@ret:0 成功 -1 失败    virtual int front(TYPE& val) = 0;    ///@brief:移除头结点元素    ///@ret:0 成功 -1 失败    virtual int pop() = 0;      ///@brief:返回堆中元素个数    virtual int size() = 0;    ///@brief:获取最后状态错误信息    virtual const std::string& get_lasterror() = 0; private:};#endif//派生类,具体实现MinHeapArray.h#ifndef __MINHEAPARRAY_H#define __MINHEAPARRAY_H#include "MinHeap.h" /************************************************************* @brief: 数组形式的最小堆,通过自动化测试,时间复杂度log(N) @author:zp  @atention: 1.如果是自定义复合类型,需要重载 < > = 三个重载运算符,以确定比较方式            2.支持线程安全和非安全模式,所以编译时需链接 lpthread            //尚待测试点 函数指针,仿函数,模板函数传进来            //二叉树形式实现没有成功,以后再来把二叉树形式的写了吧**************************************************************/ template <class TYPE>class CMinHeapArray:public CMinHeap<TYPE>{public:     CMinHeapArray(const int size, const bool thrdsafe=false);    ~CMinHeapArray();     ///@brief:添加元素,采用从上往下移动方式       virtual bool add(const TYPE p);    ///@brief:获取小根堆头结点     ///@ret:0 成功 -1 失败    virtual int front(TYPE& val);    ///@brief:移除头结点元素    ///@ret:0 成功 -1 失败    virtual int pop();      ///@brief:返回堆中元素个数    virtual int size();    ///@brief:获取最后状态错误信息    virtual const std::string& get_lasterror();private:    ///小根堆元素保存的缓冲区    TYPE* m_heap;       ///最小堆元素个数限制    int m_size;    ///当前元素个数    int m_cur;    ///最后状态错误原因    std::string m_lasterror;     ///是否支持线程安全 true 支持  fales不支持    bool m_thrdsafe;    ///线程安全锁    CLock m_lock; }; template<class TYPE>CMinHeapArray<TYPE>::CMinHeapArray(const int size, const bool thrdsafe){       if (size <= 0)    {        m_lasterror = "min-heap size illegal";    }    else    {        m_heap = new(std::nothrow) TYPE[size];        if (NULL == m_heap)        {            m_lasterror = "min-heap init error";        }                    m_size = size;        m_cur = 0;    }        m_thrdsafe = thrdsafe;}template<class TYPE>CMinHeapArray<TYPE>::~CMinHeapArray(){    delete m_heap;    m_heap = NULL;}template <class TYPE> inline const std::string& CMinHeapArray<TYPE>::get_lasterror(){    if (m_thrdsafe)        m_lock.lock();    std::string& lasterror = m_lasterror;    if (m_thrdsafe)        m_lock.unlock();    return m_lasterror;}//bool add(const TYPE p, bool (*compare)(const TYPE a, const TYPE b)=NULL)template <class TYPE> bool CMinHeapArray<TYPE>::add(const TYPE p){       if (m_thrdsafe)        m_lock.lock();    int s;     s = m_cur;    int parent;    bool bflag = false;     if (m_cur < m_size)      {        while (s > 0)        {            parent = (s - 1) / 2;                        if (m_heap[parent] < p)                break;                       m_heap[s] = m_heap[parent];            s = parent;                         }        m_heap[s] = p;          m_cur++;        bflag = true;     }    if (m_thrdsafe)        m_lock.unlock();    return bflag;} template <class TYPE>int CMinHeapArray<TYPE>::front(TYPE& val){    if (m_thrdsafe)        m_lock.lock();    int flag = -1;    if (m_cur > 0)    {        flag = 0;        val = m_heap[0];    }    if (m_thrdsafe)        m_lock.unlock();    return flag;}///note:在弹出元素时,会将最后元素移动到被移走的空位处template <class TYPE>int CMinHeapArray<TYPE>::pop(){    if (m_thrdsafe)        m_lock.lock();    int nret = -1;    int s = 0;      int half = 0;        int smallerpos = 0;     if (m_cur > 0)    {        nret = 0;        m_cur--;        half = m_cur / 2;        while (s < half)        {            int childl = s*2+1;            int childr = s*2+2;            smallerpos = childl;            if (childr < m_cur && m_heap[childl]>m_heap[childr])                smallerpos = childr;            if (m_heap[m_cur]<m_heap[smallerpos])                break;            m_heap[s] = m_heap[smallerpos];            s = smallerpos;        }        m_heap[s] = m_heap[m_cur];    }    if (m_thrdsafe)        m_lock.unlock();    return nret;} template<class TYPE>inline int CMinHeapArray<TYPE>::size(){    int size = 0;    if (m_thrdsafe)        m_lock.lock();        m_size = m_cur;    if (m_thrdsafe)        m_lock.unlock();    return m_cur;}  #endif//线程锁封装#ifndef __LOCK_H#define __LOCK_H #include <pthread.h>/****************************************************************@brief:linux平台线程锁*@author:zp*/class CLock{public:    CLock()    {        _lock = new pthread_mutex_t;        pthread_mutex_init(_lock, NULL);    }    ~CLock()    {        pthread_mutex_destroy(_lock);        delete _lock;    }    void lock()    {        pthread_mutex_lock(_lock);    }    void unlock()    {        pthread_mutex_unlock(_lock);    }    int trylock_mutex()    {        return pthread_mutex_trylock(_lock);    }       private:    pthread_mutex_t* _lock;} ;#endif//测试用例#include <iostream>#include <stdlib.h>#include <time.h>/**@brief:最小堆测试和使用用例*@attention:1.自定义复合结构需要重写 < > = 运算符 ,如有必要可以改成回调函数形式*            2.在使用过程中如有逻辑问题或性能问题,请邮件zhang_int@sina.cn**/#include "MinHeap.h"#include "MinHeapArray.h"#define VAL_RANGE 20000#define ARR_SIZE  9999//自定义复合结构测试用例typedef struct SMyStruct{    std::string t1;    std::string t2;    int a;    int b;    bool operator < (SMyStruct val)    {        bool bret = false;        if (t1<val.t1)            bret = true;        return bret;    }    bool operator > (SMyStruct val)    {        bool bret = false;        if (t1>val.t1)            bret = true;        return bret;    }    bool operator = (SMyStruct val)    {        t1 = val.t1;        t2 = val.t2;        a = val.a;        b = val.b;    }} TMyStruct;bool judge(int front, int next){    bool bflag = true;    if (front > next)    {        bflag = false;    }    return bflag;} //批量自动化测试,随机构造数组大小,随机构造数组内的元素,然后放入到最小堆里面//然后将数据弹出,查看是否是 升序//保证最小堆能够可靠完整的运行 int batch_test(){    //构建自动化测试,保证代码可靠运行    int arrsize;    while (1)    {               int* val;        arrsize  = random() % ARR_SIZE;        if (arrsize == 0)            continue;        CMinHeap<int>* heap = new CMinHeapArray<int>(arrsize);        val = new int[arrsize];        for (int j=0; j<arrsize; j++)        {            int rand = random() % VAL_RANGE;            heap->add(rand);            val[j] = rand;        }        int size = heap->size();        int last;        int next;        bool bflag = true;        for (int i=0; i<size; i++)        {                   if (i==0)            {                if (heap->front(last) == -1)                    std::cout<<"front error last."<<std::endl;                          }            else             {                if (heap->front(next) == -1)                    std::cout<<"front error next."<<std::endl;                if (!judge(last, next))                {                    bflag = false;                                  }                last = next;                            }               //std::cout<<last<<"  ";                        heap->pop();        }        if (bflag == false)        {            std::cout<<"judge error."<<std::endl;            for (int i=0; i<arrsize; i++)            {                std::cout<<val[i]<<"  ";            }            std::cout<<std::endl;            std::cin.get();        }        std::cout<<"test over "<<arrsize<< "!!!"<<std::endl;        usleep(1000);        delete heap;        heap = NULL;        delete val;        val = NULL;    }           return 0;}  /*bool compare_min(TMyStruct a, TMyStruct b){    bool bret = false;    if (a.t1 < b.t1)        bret = true;    if (a.t1 == b.t1)        std::cout<<"equal."<<std::endl;    return bret;}*/void type_test(void){    TMyStruct b[10];    b[0].t1 = "nihao";    b[1].t1 = "test";    b[2].t1 = "1";    b[3].t1 = "god";    b[4].t1 = "msg";    b[5].t1 = "hehe";    b[6].t1 = "yumy";    b[7].t1 = "info";    b[8].t1 = "book";    b[9].t1 = "tea";    CMinHeap<TMyStruct>* heap = new CMinHeapArray<TMyStruct>(10, false);    for (int i=0; i<10; i++)    {        heap->add(b[i]);    }    int size = heap->size();    TMyStruct t;    for (int i=0; i<size; i++)    {        heap->front(t);        std::cout<<t.t1.c_str()<<" "<<std::endl;        heap->pop();    }     std::cin.get();  } int main(void){    type_test();         batch_test();    return 0;}
0 0
原创粉丝点击