1.最小堆实现

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值