最近开始看一些简单的算法书,之前大一上学期学Python的时候,其实就有想写一些笔记的想法,但是之前一直太懒,没有实现。最近老师要求我们每个星期看一些算法书,并做一些笔记,希望这个习惯能够坚持下来吧。编程小白,错误之处请大佬们指正,也希望和大佬萌新们一起加油学习。
一.链表(list
)
STL
中的
list
是双向链表,它的特点是内存空间不连续,可以通 过指针来进行数据的访问,可以很快地在任意处插入和删除(这个操
作只需要常数时间。)
list
适用于插入和删除频繁,而随机访问较少。
vector
则相反。下面是
list
的一个实例:
(
1
)
hdu1276
士兵报数问题
注意,在这里使用了迭代器。
(
迭代器:要访问顺序容器和关联容器中的元素,需要通过“迭代器
- (iterator)”进行。迭代器是一个变量,相当于容器和操纵容器的算
法之间的中介。迭代器可以指向容器中的某个元素,通过迭代器就可
以读写它指向的元素。从这一点上看,迭代器和指针类似。注意
list
不支持“
<
”,因为双向迭代器不支持这种运算
)
。
二.集合(
set
)
集合具有元素自动去重的特点,并且
STL
中的
set
使用二叉搜索树
实现,访问元素的时间复杂度是
O
(
log
₂
n
)。
集合的大部分操作与
vector
等类似,但是多了:
A. lower_ /( upper_) bound(k)
//
返回一个迭代器,指向键值
不小于
/(
不大于
)k
的的第一个元素
下面是一个例子:
(2) hdu2094
冠军问题
![](https://img-blog.csdnimg.cn/20210423210815412.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzNTE5NDA2,size_16,color_FFFFFF,t_70)
注意这里
set
会自动去重,胜利者不会在
B
中,
A
中包含了所有的选
手,并且如果存在冠军,即胜利者唯一,故两集合的基的差值为
1
。
这就是这个算法的核心。
三.map
map 容器可以建立把不同类型的数据串接起来,它是关联容器,
可以实现键到值的映射。比如查找学生的姓名和学号。当然,c++中
的结构体(
struct
)也可以实现这一操作,但它需要遍历所有的
n
个
学生,是复杂度
O(n)
的算法。而
map
是通过平衡二叉搜索树来存储
和访问,因此它是
O(log
₂
n
)
的算法。这里补充说明一下平衡二叉树
(AVL)
:
平衡二叉树满足:
1.
是「二叉排序树」
(
即所有左子树的值小于根节点,右子树的
值大于根节点
)
2.
任何一个节点的左子树或者右子树都是「平衡二叉树」(左
右高度差小于等于
1
)
这样就避免了二叉树成为一个链表一样的排列,这个时候查找的
效率是最差情况
(the worst case)
,它是
O(n)
的复杂度。
下面是一个实例:
(3) hdu2648
购物问题
![](https://img-blog.csdnimg.cn/20210423211021809.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzNTE5NDA2,size_16,color_FFFFFF,t_70)
注意代码的最后一行的迭代器使用了
”it->second”,
这相当于 (*it).second,会得到值
(value)
,相对的
it->first
得到键
(key)
。
四.
Sort( )
函数
Sort( )
函数可以自定义排序,也可以使用系统自带的
4
种排序。其
中,最常用的有:
sort(a.begin(),a.end());
从小到大排序。当然也可以
有从大到小,大于等于等排序方法。
五.
next_permutation( )
函数
这个函数是
STL
中用来生成下一个组合的函数。它是
bool
形式的
函数,若存在下一个排列组合,则返回
true
,反之返回
false
。每执行
一次这个函数,就会把新的排列放到原来的空间里。算法的复杂度为
O(n)
,特别需要注意的是它排列的范围是左闭右开区间的。
下面是运用此函数实现找到下一个字典序更大的序列:
![](https://img-blog.csdnimg.cn/20210423211209829.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzNTE5NDA2,size_16,color_FFFFFF,t_70)
自己编写一个函数实现
next_permutation()
的功能。这个算法的原理
是:从右向左遍历,从这个序列中从右至左找第一个左邻小于右邻的
数,如果找不到,则所有排列求解完成,如果找得到则说明排列未完
成。将这个左侧的数记为
i
,在从右往左找到第一个大于
i
的数,记
为
j
,把
i
换成
j
,这个左侧数后面所有的数从小到大排序即可以得到
下一个更大的字典序。
(
因为字典序实际上是只比较到某一个位数上
的数的不等关系即可,若前几位数相同,则继续往后比较。
)