priority优先级队列
头文件queue
利用vector做适配器
出栈(默认底层是大堆)
跟栈,堆很像 出数据取一个出一个默认底层是大堆)
堆顶 位置数据跟 堆底 交换然后(向下调整)
插入删除效率是logN
变成小堆(升序)
支持迭代器区间构造
优先级队列最适合的适配器是vector
构造优先队列
首先构造一个大堆,默认插入数据是 尾插 假如插入 80 就要向上调整保持是堆
插入数据
插入数据只会影响父辈(比较调整,比较调整)
插入数据后最新插入的数据下标为size-1
知道孩子算父亲(child-1)/2 while循环条件不能是parent<0,应为循环条件如果是 (0-1)/2结果也不会<0会进入死循环,所以条件为child>0,当child=0时候循环结束(child下标不会<0会等)
由此完成一个数据插入
删除数据
删除堆顶数据,现将堆顶与最后一个交换,然后删除最后一个,再向下调整(首位交换)
不能头删,vector勉强支持头删但是不推荐
从堆顶元素向下调整,向下调整函数参数不用给大小应为_con是一个适配器类型可以调用size
1.父亲算孩子 child=parent*2+1,先选出左右孩子大的那一个,一直调到叶子结点
2.如果算出的(孩子)下标超出数组的范围,就结束了.
3.找较大的孩子过程中,可能会出现没有右孩子的过程,所以可能计算右孩子越界
4.所以用假设左孩子大(因为左孩子一定存在),如果右孩子(存在)且大于 左孩子 就更新
5.当孩子大于_con[child]>_con[parent]父亲时跟父亲交换
构造和析构
我们没写构造和析构函数,container(容器)是自定义类型,会调用自定义类型的构造函数
拷贝构造也不需要自己写,当我们拷贝构造时候会发现没有拷贝成功,因为数据已经出队了
优先级队列的迭代器
【从堆的定义到优先队列、堆排序】 10分钟看懂必考的数据结构——堆_哔哩哔哩_bilibili
利用迭代器,插入建堆(nlogn)向下调整建堆(On)
先形成一个堆再对每个父节点下滤
向下调整建堆(On) (n-2)/2 也就是((n-1)-1)/2 找最后一个元素的父亲
仿函数
非类型模板参数参数
不用像defi n一样写死,而且必须是常量(因为编译时候要开数组不知道n多大就不知道开多大的数组)且参数只支持整形(char可以因为也是整形(int,char,short))
模版特化
针对某些类型进行特殊化处理
如果是int double走下面的类,如果不是就走上面的类(下面的类模板不写参数)
函数模版可以不用特化
反向迭代器
偏特化
特化部分参数
指针类型
反向迭代器适配器
T*是内置类型,返回值是返回它的临时拷贝(finish的拷贝,同理自定义类型_list_iterator返回的是iterator的拷贝),拷贝的是临时对象(右值)具有常性,所以常量(常性)对象不能- -,- -对象需要左值
但是第二个(list没报错)在自定义类型中的_head->_next(右值)特殊处理了,就当做--调用了非const成员函数end(),内置类型不能直接--
所以改成end()-1因为他是常量(右值)
特殊处理了
同样是--end
匿名对象和临时对象不能取别名+const就行了,但是他却可以调用类中的非const函数
坑!
A()是一个临时对象(临时对象具有常性)不能取别名 +const就行了,但是加了const确可以调用
非const函数.printf(),但是 内置类型T不可以调用(--end())改成(end()-1)右值可以-1
模版不支持分离编译
普通函数和函数模版 调用函数模版会出错(最少要有声明)
解决方法:
1.显示实例化(缺点就是不灵活了,假如传double就不行了)不好用,分离编译显示实例化不是长久之计
stack.cpp会形成汇编func可以 但是T找不到实例化类型,有声明也行,(有定义直接买房,有声明也行)func有声明地址.s生成.o(有声明和定义),但是add没有被实例化
func可以调用但是Add不可以调用,因为Add是函数模版
2. 声明和定义都放在一个文件里