algorithm算法里有堆排序
默认sort是快排,
了解下:

报错。得是堆才能排

这个判断是不是堆。
也有建堆算法


优先级队列不想自己写,是可以调用这块的算法。这也是走一个向上调整算法
这个本质也是个向下调整算法。优先级队列是将这个堆算法结合起来形成一个适配器。
看一个奇怪的东西:

所说的不仅仅是这一个算法,要求穿一个迭代器,可以穿vector迭代器,也可以传数组的指针,物理空间连续情况下,原生指针就是天然的迭代器,sort也可以排序数组。vector string,可以用原生指针替代iterator,看起来是iterator实际就是原生指针,前提是底层是个连续的物理空间,
看一下仿函数,实践当中不需要写less和greater,直接用就行。
在function的一个头文件,有时候也不需要包,被间接包了,
仿函数一般不需要我们自己写,但是有一些场景必须自己写
cpp
class Date
{
friend ostream& operator<<(ostream& _cout, const Date& d);
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
bool operator<(const Date& d)const
{
return (_year < d._year) ||
(_year == d._year && _month < d._month) ||
(_year == d._year && _month == d._month && _day < d._day);
}
bool operator>(const Date& d)const
{
return (_year > d._year) ||
(_year == d._year && _month > d._month) ||
(_year == d._year && _month == d._month && _day > d._day);
}
private:
int _year;
int _month;
int _day;
};

我们直接用日期类对象做这个,插入日期类支持,因为priority queue默认仿函数是less,less内调用的是比较大于和小于,日期类对象支持大于和小于,也就是说,类类型也没关系,自己支持一下就OK。
这种可以控制住,

第一次是30 28 29
每次生成都不一样,底层依靠指针,也就是地址比,而且地址是随机的,先new不一定大,


缺省值不传按date*比,传了按指向去比。,降序operator反过来就行
模版进阶
之前叫类型模版参数
现在学
我们定义一个静态的栈,可以不要参数,直接用常量,定义的是常量,可以直接用来做数组的大小,编译时候就确定了,模版在编译时候就实例化了,比起宏的好处是什么,宏是写死的

非类型模版参数就可以帮忙解决这个问题,本质底层生成两个类,一个类N是5,一个N是10,,非类型模版定义的常量。
非类型模版参数只能用于整形,其他类型不可以,C++20才能用double
非类型模版参数主要就是为了定义一些大小,固定值,这种。解决这个问题。非类型模版参数可以给缺省值。

推荐这样写。都支持,向前兼容。可以写两个模版参数
、
布尔也算整形,整形家族,char int lnog 有符号 无符号 布尔
array是个静态数组, 迭代器是随机迭代器,原生指针实现的,用非类型模版参数。(非常适合)
也没初始化
底层类似这个
越界检查问题用这个很爽,越界读基本上检查不出来,越界写标志位能被检查。数组检查是设标志位的检查,就是抽查,数组后面给两个标志位,一个或者三个,给-1,看有没有被修改,没修改就检查不出来,这就是抽查机制,如果往后面,就检查不出来。因为这不是标志位。所以越界检查,C语言的普通静态数组是抽查,越界读不检查,写是抽查,多设置标志位,检查不完,
array越界读写都能检查。不是设标志位了,他是自定义类型,要调用operator【】,operator【】就可以强制加个断言检查,
vector不仅可以越界检查,还可以初始化,为什么用静态数组,还是有本质区别,vector在堆,array在栈,栈上开空间比堆上效率高。vector不管多大数组,始终16字节,arrray大小数组越大,占用越大。ayyar对比静态数组越界检查会更好,对比vector数据空间在栈上,效率高,一句指令就把所有变量空间开好了
模板的特化

函数模版可以特化,但是很多坑

指针比交,控制不住,所以函数模版特化,

特化是说当这个T类型是其他类型走上面,DAte*走下面这个,对DAte*特殊处理,
特化很不好,可以不用特化,直接写个函数
末班和现成的用现成的。所以函数模版推荐这样写。这个和特化可以同时存在,调用固定函数,特化不起作用了。
为什么函数模版特化恶心:
内置类型还好,自定义类型要调用拷贝构造。不好要这么写
这样写,特化不行,没跟原来地方完整匹配。
那我也这样写
也不行,因为上面const修饰left,修饰引用本身,下面const修饰指向内容,所以要把const放到*之后

还是直接用函数好

能不能匹配上特化上面那个可以匹配上,下一个匹配不上,匹配到原模版去了,特化的DAte*,和const DAte* 是两个类型,constDAte* 不能给DAte*,因为权限呗放大了,
这样就可以了。cosnt DAte*是本来就要特化成的。第二个const要修饰引用对象本身,对于普通类型const既可以放到之前也可以放到之后
这样写也可以
引用也可以
没有指针可以随便颠倒。


第一个匹配不上了

第二个可以走特化

特化两个版本可以解决这个问题
所以用普通函数很好,不写特化,DAte*权限缩小都不行,这里模版还是蛮严谨的。
这里也要写两份才能都匹配,特化是真的不好玩。特化必须和原模板相匹配。