C++模板学习之优先队列实现
转载: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++模板学习之优先队列实现的更多相关文章
- XTemplate模板学习和使用总结
XTemplate模板学习和使用总结 前言 XTemplate是我接触的第一个模板语言,用在公司的一个NodeJS项目中,跟它打交道经常是因为需要使用它的语法向模板中注入数据.因为是刚入门前端不久 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- C++模板学习
一.定义函数模板 template<class T> 函数定义 举个例子比较两个数大小: template<class T> int Compare(T a,T b) { ; ...
- C++模板学习随笔
本文学习内容参考:http://www.cnblogs.com/gw811/archive/2012/10/25/2738929.html C++模板 1.模板分为函数模板和类模板两种类型 函数模板针 ...
- 模板学习实践二 pointer
c++ template学习记录 使用模板将实际类型的指针进行封装 当变量退出作用域 自动delete // 1111.cpp : 定义控制台应用程序的入口点. // #include "s ...
- 算法模板学习专栏之总览(会慢慢陆续更新ing)
博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/7495310.html特别不喜欢那些随便转载别人的原创文章又不给 ...
- wordpress学习三:wordpress自带的模板学习
在<学习二>里,大概说了下怎么去查找模板,本节我们以一个简单的模板为例子,继续说说wordpress的模板机制,看看做一个自己的模板需要哪些知识点. 页面模板渲染 wordpress的模板 ...
- C++模板学习笔记
一个有趣的东西:实现一个函数print, 输入一个数组, 输出数组的各个维度长度. eg. ], b[][], c[][][]; print(a); //(2, 4) print(b); //(3, ...
- 转:C++模板学习
C++ 模板 转:http://www.runoob.com/cplusplus/cpp-templates.html 2018-01-05 模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的 ...
随机推荐
- [VIP] openstack环境配置VIP
描述 当你在openstack平台创建一个network,在这个network上创建两台虚拟机,当这两台虚拟机还需要VIP时,你从这个network分配一个地址做为VIP,配置到虚拟机上,你会发现这个 ...
- 单网口RFC2544测试——信而泰网络测试仪实操
一.测试拓扑 拓扑说明 测试仪一个端口和DUT一个端口相连 DUT假设是一台交换设备,它能够把测试仪发送的流量直接转发回来 注意:要求DUT必须能够把收到的流量环回出来,否则没有办法测试 二.测试思路 ...
- 在windev中实现BS架构级的灵活排版
windev是CS架构,但却能够实现BS架构级的灵活排版.玩过CS架构的老铁们,感受应会都如我,如获新生!因为苦于没有一张好画皮久矣!在windev中,要实现灵活,专业,自适应和非常丰富的排版,可以关 ...
- 使用Helm安装harbor
使用nfs共享存储搭建的pvc(此次都放在一个vpc下): harbor使用nodePort方式部署,不使用ssl: 准备工作: 准备好harbor用的pvc: 安装好helm,添加好可用源: 因为使 ...
- 【C#DLR 动态编程】CallSite<T>
CallSite<T>译为"动态(调用)站点",它是DLR中的核心组件之一
- shell脚本编写自动启动服务方法
shell脚本编写自动启动服务方法 前言 ln :创建连接文件 默认创建的是硬连接,好比复制 ,但是两个文件会同步命令:ln ./java/android/aa.txt aaa s :创建的是软连接变 ...
- Java课程设计---创建数据库工具类
1.传统的数据库操作 package com.java.mysql; import java.sql.Connection; import java.sql.DriverManager; import ...
- Excel:如何在间断的序号间插入空行
https://jingyan.baidu.com/article/e6c8503cb7ad7de54e1a1851.html
- ROS入门介绍
1.ROS版本介绍 ROS版本:(已经推出数十个版本) 2013 ------> Hydro 2014 ------> Indigo (对应Ubuntu14.04) (现在已经基本废弃) ...
- Go基础知识梳理(三)
Go基础知识梳理(三) 结构 type Person struct { name string sex int } func main() { //推荐写法 person := Person{ nam ...