【数据结构】用模版实现大小堆、实现优先级队列,以及堆排序

一、用模版实现大小堆

如果不用模版的话,写大小堆,就需要分别实现两次,但是应用模版的话问题就简单多了,我们只需要实现两个仿函数,Greater和Less就行了,仿函数就是用类实现一个()的重载就实现了仿函数。这个看下代码就能理解了。再设计参数的时候,需要把模版设计成模版的模版参数,因为要实现大小堆嘛!当我们实现好一个大堆或者小队的逻辑后只需要用模版接收的Greater或Less类定义一个变量,就能实现通用功能了。

template<typename T>
struct Less
{
    bool operator()(const T& l, const T& r)
    {
        return l < r;
    }
};

template<class T>
struct Greater
{
    bool operator()(const T& l, const T& r)
    {
        return l>r;
    }
};

template <class T,template<class> class compare = less>
class Heap
{
public:
    Heap()
    {}

    Heap(T* a,size_t size)
    {
        size_t index = 0;
        while (index < size)
        {
            _a.push_back(a[index]);
            index++;
        }

        for (int i = (_a.size() - 2) / 2; i >= 0; i--)
            _AdjustDown(i);
    }

    void push(const T& x)
    {
        _a.push_back(x);
        _AdjustUp(_a.size() -1);
    }

    void pop()
    {
        size_t size = _a.size();
        assert(size > 0);
        swap(_a[0], _a[size - 1]);
        _a.pop_back();
        size = _a.size();
        _AdjustDown(0);
    }

    size_t top()
    {
        assert(!_a.empty());

        return _a[0];
    }

    bool empty()
    {
        return _a.size() == 0;
    }

    size_t Size()
    {
        return _a.size();
    }

    void Print()
    {
        for (int i = 0; i < _a.size(); i++)
        {
            cout << _a[i] << " ";
        }
        cout << endl;
    }

protected:
    void _AdjustUp(int child)
    {
        int parent = (child - 1) / 2;
        compare<T> com;  //如果是大堆传过来就是用大堆的逻辑,小堆就实现小堆的逻辑
        while (child > 0)
        {
            //找出孩子中的最大孩子
            if (com(_a[child] , _a[parent]))
            {
                swap(_a[child], _a[parent]);
                child = parent;
                parent = (child - 1) / 2;
            }
            else
            {
                break;
            }
        }

    }

    void _AdjustDown(size_t parent)
    {
        size_t child = 2 * parent + 1;
        compare<T> com; //如果是大堆传过来就是用大堆的逻辑,小堆就实现小堆的逻辑
        while (child < _a.size())
        {
            //找出孩子中的最大孩子
            if (child + 1 < _a.size() && com(_a[child+1] ,_a[child]))
            {
                ++child;
            }
            //把
            if (com(_a[child] , _a[parent]))
            {
                swap(_a[parent], _a[child]);
                parent = child;
                child = child * 2 + 1;
            }
            else
            {
                break;
            }
        }

    }
protected:
    vector<T> _a;
};

二、用模版实现优先级队列

前面实现了大小堆,这里我们可以使用适配器,直接调用大小堆,来实现优先级队列。

template<class T, template<class> class compare = Less>
class priorityQueue
{
private:
    Heap<T, compare> _hp; 
public:
    void push(const T& x)
    {
        _hp.push(x);
    }

    void pop()
    {
        _hp.pop();
    }

    T& Top()
    {
        return _hp.top();
    }

    void Print()
    {
        _hp.Print();
    }

};

三、堆排序的实现

堆排序的实现简单思路,(升序)先构造出来一个大堆,调整堆后,将堆头和最后一个数据交换,最大值就换到了数组的最后,然后在调整堆,但是size需要减少1,因为最大的已经调整到最后,如果再加上它调整又会回到堆头。

int*& HeapSort(int* a, size_t size)
{
    for (int i = (size - 2) / 2; i >= 0; i--)
    {
        _AdjustDown(a, size, i);
    }

    for (int i = 0; i < size; i++)
    {
        swap(a[0], a[size - i - 1]);
        _AdjustDown(a, size - i - 1, 0);
    }

    return a;
}
时间: 2024-08-28 19:04:09

【数据结构】用模版实现大小堆、实现优先级队列,以及堆排序的相关文章

浅谈算法和数据结构: 五 优先级队列与堆排序

转载自:http://www.cnblogs.com/yangecnu/p/Introduce-Priority-Queue-And-Heap-Sort.html 浅谈算法和数据结构: 五 优先级队列与堆排序 在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理次高的对象.最简单的一个例子就是,在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话. 在这种情况下,我们的数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是

STL源码笔记(15)—堆和优先级队列(二)

STL源码笔记(15)-堆和优先级队列 优先级队列的源码实现基于heap的操作,底层容器默认是vector. 优先级队列简介 优先级队列跟队列类似,一端插入一端删除,不同的是,优先级队列的元素入队后会根据其优先级进行调整,默认情况下优先级高的将优先出队,在SGI STL中,优先级队列的功能保证由heap实现:stl_heap.h中,heap的分析见:STL堆源码分析 优先级队列构造函数 默认情况下,优先级队列使用vector作为底层容器,使用less作为比较函数,其在源码中的定义声明如下: te

STL源码笔记(14)—堆和优先级队列(一)

STL源码笔记(14)-堆和优先级队列 priority_queue是拥有权值观念的queue,跟queue类似,其只能在一端push,一端pop,不同的是,每次push元素之后再容器内部元素将按照一定次序排列,使得pop得到的元素始终是当前权值的极大值. 很显然,满足这个条件就需要某些机制了,缺省情况下使用max-heap大顶堆来实现,联想堆排序的实现,使用大顶完成序列从小到大的排序,过程大概是: 把堆的根元素(堆中极大值)交换到最后 堆的长度减1 这样每次取出堆中的极大值完成排序,刚好与优先

优先级队列与堆排序

转自:http://www.cnblogs.com/yangecnu/p/Introduce-Priority-Queue-And-Heap-Sort.html 在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理次高的对象.最简单的一个例子就是,在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话. 在这种情况下,我们的数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象.这种数据结构就是优先级队列(Pri

初学算法-基于最小堆的优先级队列C++实现

笔者近日实现了最小堆类及其派生的优先级队列,特将代码奉上,不足之处还请指出! 在实现优先级队列时,笔者表示萌萌哒没有用过template写派生类,结果写完了出现error: *** was not decleared in this scope..后来各种补上this->才完事,在CSDN(笔者的帖子地址? http://bbs.csdn.net/topics/391806995)上提问后才知道是模板参数依赖,笔者表示涨姿势了.. /**  * The Minimum Heap Class an

python[数据]--队列,堆,优先级队列

队列:from collections import deque:实现保存最后几条历史记录,list = deque(maxlen=6),那么超过六条记录会删除之前的记录. 堆:import heapq;最大特点是第一弹出的元素总是堆中最小的元素:list=[1,2,3] heap=heapq.heapify(list) ,nlargest(3,数据,key=lambda) nsmallest() 优先级队列:堆中的元素(-优先级,序号,item)这样即可实现优先级,优先级越高最先pop出堆,优

数据结构与算法之美-堆的应用

堆的应用一:优先级队列 优先级队列首先应该是一个队列.队列最大的特性就是先进先出.但是在优先级队列中,出队顺序不是先进先出,而是按照优先级来,优先级最高的,最先出队. 用堆来实现优先级队列是最直接.最高效的.这是因为,堆和优先级队列非常相似.一个堆就可以看作一个优先级队列.很多时候,它们只是概念上的区分而已. 往优先级队列中插入一个元素,就相当于往堆中插入一个元素.从优先级队列中取出优先级最高的元素,就相当于取出堆顶元素. 很多数据结构和算法都要依赖它.比如,赫夫曼编码.图的最短路径.最小生成树

数据结构与算法:二叉树+堆

[二叉树] 1. 实现一个二叉查找树,并且支持插入.删除.查找操作 class Node: def __init__(self, data): self.data = data self.lchild = None self.rchild = None class BST: def __init__(self, node_list): self.root = Node(node_list[0]) for data in node_list[1:]: self.insert(data) # 查找

优先级队列及小顶堆排序

优先级队列及小顶堆排序实现 /** @file          HeapSort.h *  @copyright     personal *  @brief         优先级队列及堆排序 *  @version       V1.0.0 *  @author        fangyuan *  @date          2015/12/31 *  @note          测试版本 */ #include "iostream" using namespace std