转载:https://www.cnblogs.com/muzicangcang/p/10579250.html

今天将继续将强C++模板类的学习,同时为了巩固已经学习过的数据结构中有关优先队列的知识,我将会使用模板类来实现自己的优先队列。在给出具体实现之前,我要先介绍一下什么是优先队列,聊以为复习吧。

在某些情况下,我们会收集一些元素,处理当前元素的最大值,然后再收集更多数据,再处理此时的最大值。这就要求我们设计的数据结构能够随时访问元素集合中的最大值和能够随时插入数据。优先队列即可以实现这种功能。

优先队列

优先队列的实现有两种思路,第一是在数据插入时保存数据元素的有序性,这意味着我们能够以O(1)的时间复杂度来访问元素中的最大值。但是我们在数据进行插入的时候,对寻找数据的合适位置的访问操作的最坏时间复杂度为O(N)。第二种思路是构建一个堆,他能够让我们以N(1)的时间复杂度来访问元素中的最大值,而以O(logN)的时间复杂度来调整堆,以便将元素插入到合适的位置。综上所述,在具体实现优先队列的时候需要根据待处理的元素量级来确定到底使用哪种思路。很明显,当数量级较小的时候,适合使用第一种思路;当数量级较大的时候,第二种思路将比较好。

首先简单介绍一下什么是堆。

1、堆是一种数据结构,他是一棵完全二叉树

2、在堆中,每个父节点都大于等于它的两个孩子结点,被称为堆有序

3、如果将堆由上到下,由左到右从0开始编号(即根节点编号为0),则某个节点,它的左孩子编号=(该结点的编号*2+1);右孩子结点的编号=(该结点编号*2+2)。他的第一个存在孩子结点的结点编号为(堆长度/2-1)

优先队列堆实现

//
// Created by yz on 19-8-31.
//
#include <iostream>
#include <algorithm>
#include <vector> using namespace std; /*****************优先队列实现**************************/
//默认仿函数,最大堆
template <class T>
class _compare
{
public:
bool operator()(T a,T b)
{
return a<b;
}
}; template <class T,class compareType=_compare<T>>
class MyPriorityQueue
{
private:
T* m_data;//数据
size_t m_size;//元素个数
size_t m_capacity;//队容量
compareType m_compare;
private:
void heapInsert();//向上调整堆
void heapify();//向下调整堆
void obj_cpy(T*,const T*,size_t);//元素复制
inline void swap(size_t i,size_t j);//交换元素
public:
MyPriorityQueue();//构造函数
~MyPriorityQueue(); bool push(const T& obj);//入队操作
bool pop();//删除队头元素
T top();//获取队头元素 bool empty()const//返回是否为空
{
return 0==m_size;
}
size_t size()const//返回队列大小
{
return m_size;
}
size_t capacity()const //返回队列容量
{
return m_capacity;
}
void show()
{
cout<<"队列元素数量为:"<<m_size<<endl;
cout<<"将队列从大到小打印"<<endl;
size_t len=m_size;
for (int i = 0; i <len; ++i) {
cout<<top()<<" ";
pop();
}
cout<<endl;
}
};
//无参构造函数
template <class T,class compareType>
MyPriorityQueue<T,compareType>::MyPriorityQueue() :m_size(0),m_capacity(10)
{
m_data=new T[m_capacity];
if(nullptr==m_data)
{
throw "申请空间失败";
}
}
//析构函数
template <class T,class T2>
MyPriorityQueue<T,T2>::~MyPriorityQueue()
{
if(m_data!= nullptr)
{
delete [] m_data;//释放空间
m_data= nullptr;//置空
}
}
//交换元素
template <class T,class T2>
void MyPriorityQueue<T,T2>::swap(size_t i, size_t j)
{
T temp=m_data[i];
m_data[i]=m_data[j];
m_data[j]=temp;
}
//插入队尾后,需要向上重新调整堆结构
template <class T,class T2>
void MyPriorityQueue<T,T2>::heapInsert()
{
size_t index=m_size-1;//index指向最后一个元素
//同父节点进行比较,如果满足,交换,上浮
while(index>0&&m_compare(m_data[(index-1)/2],m_data[index]))
{
swap((index-1)/2,index);
index=(index-1)/2;//index指向他的父节点;
}
}
//当队头出队,需要将队尾移动到队头,向下重新调整堆
template <class T,class T2>
void MyPriorityQueue<T,T2>::heapify()
{
size_t index=0;
size_t left=index*2+1;
while(left<m_size)//该节点有左孩子
{
//有右孩子的话选择左右孩子较大的那一个
size_t largest=left+1<m_size&&m_compare(m_data[left],m_data[left+1])?left+1:left;
//比较孩子节点与父节点
largest=m_compare(m_data[largest],m_data[index])?index:largest;
if(largest==index)//父节点已经是最大节点跳出循环
{
break;
}
swap(largest,index);
index=largest;
left=2*index+1;
} }
//元素复制
template <class T,class T2>
void MyPriorityQueue<T,T2>::obj_cpy(T * dest, const T * sour, size_t n)
{
for (size_t i = 0; i <n; ++i) {
dest[i]=sour[i];
}
} //入队操作
template <class T,class T2>
bool MyPriorityQueue<T,T2>::push(const T& obj)
{
T* tempPtr=m_data;
if(m_size==m_capacity)//空间不足,则需要重新申请空间
{
m_capacity*=2;//重新申请的空间的大小
m_data=new T[m_capacity];
if(m_data== nullptr)
{
m_data=tempPtr;//恢复原来的空间
m_capacity/=2;//恢复原来的容量
return false;//返回失败
}//申请空间成功
obj_cpy(m_data,tempPtr,m_size);//复制数据到新空间中
delete [] tempPtr;//删除旧空间
}
m_data[m_size++]=obj;//加入队列
heapInsert();//向上重新调整堆
return true;
}
//出队操作
template <class T,class T2>
bool MyPriorityQueue<T,T2>::pop()
{
if(m_size==0)
return false;
if (m_size==1)
{
m_size=0;
return true;
}
m_data[0]=m_data[m_size-1];//将队尾数据复制到队头
m_size--;//队尾元素个数减一
heapify();//重新向下调整堆
return true;
}
//取队头元素
template <class T,class T2>
T MyPriorityQueue<T,T2>::top()
{
if(m_size<=0)
throw "空队列";
return m_data[0];//返回队头元素
}
/******************************************************/
//仿函数,最小堆
template <class T>
class MyCompare
{
public:
bool operator()(T a,T b)
{
return a>b;
}
};
void test01()
{
MyPriorityQueue<int> maxQueue;
maxQueue.push(4);
maxQueue.push(2);
maxQueue.push(3);
cout<<"利用默认比较函数建最大堆"<<endl;
maxQueue.show(); cout<<"利用自己定义的比较仿函数,建最小堆"<<endl;
MyPriorityQueue<int,MyCompare<int>>minQueue;
minQueue.push(3);
minQueue.push(1);
minQueue.push(2);
minQueue.show();
}
int main()
{
test01();
return 0;
}

  

C++模板学习之优先队列实现的更多相关文章

  1. XTemplate模板学习和使用总结

    XTemplate模板学习和使用总结 前言   XTemplate是我接触的第一个模板语言,用在公司的一个NodeJS项目中,跟它打交道经常是因为需要使用它的语法向模板中注入数据.因为是刚入门前端不久 ...

  2. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  3. C++模板学习

    一.定义函数模板 template<class T> 函数定义 举个例子比较两个数大小: template<class T> int Compare(T a,T b) { ; ...

  4. C++模板学习随笔

    本文学习内容参考:http://www.cnblogs.com/gw811/archive/2012/10/25/2738929.html C++模板 1.模板分为函数模板和类模板两种类型 函数模板针 ...

  5. 模板学习实践二 pointer

    c++ template学习记录 使用模板将实际类型的指针进行封装 当变量退出作用域 自动delete // 1111.cpp : 定义控制台应用程序的入口点. // #include "s ...

  6. 算法模板学习专栏之总览(会慢慢陆续更新ing)

    博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/7495310.html特别不喜欢那些随便转载别人的原创文章又不给 ...

  7. wordpress学习三:wordpress自带的模板学习

    在<学习二>里,大概说了下怎么去查找模板,本节我们以一个简单的模板为例子,继续说说wordpress的模板机制,看看做一个自己的模板需要哪些知识点. 页面模板渲染 wordpress的模板 ...

  8. C++模板学习笔记

    一个有趣的东西:实现一个函数print, 输入一个数组, 输出数组的各个维度长度. eg. ], b[][], c[][][]; print(a); //(2, 4) print(b); //(3, ...

  9. 转:C++模板学习

    C++ 模板 转:http://www.runoob.com/cplusplus/cpp-templates.html 2018-01-05 模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的 ...

随机推荐

  1. oracle11g在windows下安装

    oracle下载 https://www.oracle.com/database/technologies/oracle-database-software-downloads.html 下载11g ...

  2. 攻防世界-Crypto高手进阶区部分Writeup

    1.flag_in_your_hand && flag_in_your_hand1 下载,解压后 打开index文件,直接点击get flag错误,输入其他点击也同样 打开js文件,在 ...

  3. 推荐一款好用的国产web报表软件,轻松搞定复杂报表

    随着经济全球化程度的逐步加深以及全球市场的加速整合以便最大程度地对企业资源进行整合,从而达到降低成本和提高效率的目的.Web报表由于借助于web平台,即运用了B/S模式,即"浏览器/服务器& ...

  4. Keepalived非抢占模式配置

    一.前言 HA的实际运行过程中,当主机发生异常,且后期恢复正常后,存在抢占或非抢占两种情况. 结合实际需求,可能有很多用户需要非抢占的HA工作模式.keepalived能够很好的支持这一需求. 二.k ...

  5. Ubuntu 18.04 安装配置LAMP

    --作者:飞翔的小胖猪 --创建时间:2021年5月29日 --修改时间:2021年5月29日 一.准备 1.1 环境 操作系统:Ubuntu 18.04 网页引擎:Apache php版本:7.4 ...

  6. input框限制输入金额

    HTML: <input type="tel" class="capital mui-input-clear" value="0.00" ...

  7. python3中collections模块(转)

    https://www.cnblogs.com/zhangxinqi/p/7921941.html

  8. 含变量的字符串拼接(string.Format()或$"")

    含变量的字符串拼接,一般不要用 + 来连接字符串,可用以下两种方式: 一.string.Format() 二.$""  (在C#6以上的版本中可用,推荐这种写法) 1 public ...

  9. Spring入门笔记简要

    总览:https://www.processon.com/view/link/605b14ab5653bb2225e6b0c5 一.Spring 1.概述 1.spring框架简介 ​ 为简化企业级开 ...

  10. 怎么在自己的windows上创建虚拟机(linux centos7)

    怎么在自己的windows上创建虚拟机(linux centos7) 作为一个非科班出身自学的小白,踩过很多的坑,特此留下记录 宿主机:windows10系统 8G 64位操作系统 虚拟机:linux ...