你有没有被面试官说过:你这个STL了解的不够啊。。有没有看到同样是C++为什么别人的代码还能那么少。。。好吧玄机都在#include
考试用#include
常用功能:交换swap,逆序reverse ,旋转rotate,排序sort,排列组合permutation,查找find,划分(partition)去重set vec(不是alg的),统计count,初始化fill(不是alg的)
目录
再插几条新闻(常错和捡漏)
1. map
2. queue
3. algorithm
4. string
5. 优先级队列、大根堆、小根堆、priority_queue / multiset / multimap
插播两条新闻
1. erase函数 左闭右开:
2. char 变成 int ('10'-'0')
3. 字符串拼接 9后面跟着n个0 (直接+=)
4. cctype
5. 利用set为vector数组去重(set(vec.begin(), vec.end()))
1. 交换两个元素 swap(arr[1], arr[2]);//直接交换不用&换地址
2. 反转元素的次序 reverse()
全部逆序
部分逆序,实现左移n为字符串的功能
3. rotate/rotate_copy旋转
rotate(vec.begin(),vec.begin()+3,vec.end())前面3个移到后面
rotate_copy(input.first(),input.middle,input.last(),res.first())
4. std::sort(str.begin(),str.end(),cmp);某认从小到大
string内部排序
vector排序,按照字典序(ASCII 码值)排序,不用管长度
自定义排序示例,bool cmp(string qian,string hou);qian,从小到大<>
其他排序方式的实现 (struct中bool operator() (int i,int j))
5. 是否是用一个父产生的排序 is_permutation
6. 按字典序的上/下一个排列 next_permutation(start(),end(),cmp)
部分排列
自定义排列的顺序。
7. 字典序lexicographical_compare
8. 查找find ,find_first_of , find_if , adjacent_find(二分可用)
find(vec.begin(),vec.end(),value); 本身就是查找第一个
find_first_of (r1.begin(),r1.end(),r2.begin(),r2.end()) 在r1中查找第一个r2中的元素
find_if(first,end,pre) pre是一个bool的判断谓词
adjacent_find 用于查找相等或满足条件的邻近元素对
9. 前后划分partition/stable_partition(如:奇数在前,偶数在后。前后的这种划分)
10. 计数count(a.begin(),a.end(),value)
count_if(a.begin(),a.end(),pre)
11. 容器相等equal (I1 first1, I1 last1, I2 first2, pred);pre可有可无
12. 替换 replace_if (v.begin(), v.end(), IsOdd, 0)
13. 移除 std::remove_if (pbegin, pend, IsOdd);
14. 随机打乱 std::random_shuffle ( v.begin(), v.end() );
15. 构建大根堆
来一道今年前些天华为的真题试试威力(字符串输入合法非法去重左移外排)
for ( auto it = mymap.begin(); it != mymap.end(); ++it )
std::cout << " " << it->first << ":" << it->second;
map.find的用法,而不是find(map.begin()...)
it = mymap.find('b');
if (it != mymap.end())
mymap.erase (it);
mymap['a']=20;mymap['b']=40;mymap['c']=60;
mymap['d']=80;mymap['e']=100;
itlow=mymap.lower_bound ('b'); // itlow points to b
itup=mymap.upper_bound ('d'); // itup points to e (not d!)
mymap.erase(itlow,itup); // erases [itlow,itup)
for (std::map::iterator it=mymap.begin(); it!=mymap.end(); ++it)
std::cout << it->first << " => " << it->second << '\n';
out:
a => 20
e => 100
std::map foo,bar;
foo['x']=100;
foo['y']=200;
bar['a']=11;
bar['b']=22;
bar['c']=33;
foo.swap(bar);
foo contains:
a => 11
b => 22
c => 33
bar contains:
x => 100
y => 200
注意是front,priority_queue中是top。
std::sort (v.begin(), v.end()); // 10 10 10 20 20 20 30 30
std::vector::iterator low,up;// 索引
low=std::lower_bound (v.begin(), v.end(), 20); // ^
up= std::upper_bound (v.begin(), v.end(), 20); // ^
int pos3=lower_bound(num,num+6,7,greater())-num; //返回数组中第一个小于或等于被查数的值 int pos4=upper_bound(num,num+6,7,greater())-num; //返回数组中第一个小于被查数的值
set_intersection (first, first+5, second, second+5, v.begin())
int first[] = {5,10,15,20,25};
int second[] = {50,40,30,20,10};
std::vector v(10); // 0 0 0 0 0 0 0 0 0 0
std::vector::iterator it;
std::sort (first,first+5); // 5 10 15 20 25
std::sort (second,second+5); // 10 20 30 40 50
// it只想最后一个交集
it=std::set_intersection (first, first+5, second, second+5, v.begin());
// resize(2)变成2个
// 10 20 0 0 0 0 0 0 0 0
v.resize(it-v.begin()); // 10 20
push_back 和 pop_back
if(str.find_first_of('a')==-1)如果没有找到该字符
str.erase(str.begin() + right);
priority_queue
std::priority_queue mypq;
mypq.push(30);
mypq.push(100);
mypq.push(25);
mypq.push(40);
std::cout << "Popping out elements...";
while (!mypq.empty())
{
std::cout << ' ' << mypq.top();
mypq.pop();
}
std::cout << '\n';
priority_queue
priority_queue
struct cmp {// 小根堆~!~~~~~~ 这里是ListNode是结构体,必须这么写
bool operator()(ListNode* l1, ListNode* l2) {
return l1->val > l2->val;
}
};
priority_queue里面是top不是front了。而且priority_queue中的greater和set中的正相反。
--------------------------------------------------------------------------------------
multiset> greadterSet; 9 9 8 7 7 5 4 1 0 0
multiset> lessSet; 0 0 1 4 5 7 7 8 9 9 // 这里less是小根堆,优先级队列相反
multiset defaultSet; 0 0 1 4 5 7 7 8 9 9 // 默认小根堆
---------------------------------------------------------------------------------------
使用mutimap代替优先队列,mutimap会自动对key从小到大排序,可以免去编写比较函数的麻
multimap
multimap
(1)erase(pos,n); 删除从pos开始后的n个字符,比如erase(0,1)就是删除第一个字符
(2)erase(position);删除position处的一个字符(position是个string类型的迭代器)
(3)erase(first,last);删除从first到last之间的字符(first和last都是迭代器) 左闭右开
// string::erase
#include
#include
int main ()
{
std::string str ("This is an example sentence.");
std::cout << str << '\n';
// "This is an example sentence."
str.erase (10,8); // ^^^^^^^^
std::cout << str << '\n';
// "This is an sentence."
str.erase (str.begin()+9); // ^
std::cout << str << '\n';
// "This is a sentence."
str.erase (str.begin()+5, str.end()-9); // ^^^^^
std::cout << str << '\n';
// "This sentence."
return 0;
}
'10'->10 '10'-'0'
9后面跟着n个0
string a="9";
string b="0"
for(int i =0;i
不常用的勾掉了。右图显示了char的while的使用
set
vec.assign(st.begin(), st.end());#用其他的模块初始化
vector
vector vec;
vec = { 1, 2, 3, 4, 8, 9, 3, 2, 1, 0, 4, 8 };
set st(vec.begin(), vec.end());
vec.assign(st.begin(), st.end());#用其他的模块初始化
这个需要注意的是std中也有swap, 当你引入algorithm和std之后,用swap时可以加入std::swap
int arr[1,2,3,4];
swap(arr[1], arr[2]);//直接交换不用&换地址
string str("hello");
//如何才能只反转ello,即变成holle?如下
reverse(str.begin()+1,str.end());
如:abcdef,左移2,是cdefab
reverse(str.begin(),str.begin()+2);
reverse(str.begin()+2,str.end());
reverse(str.begin(),str.end());
其实和上面的用reverse实现的左移的功能是一样的。
template
void rotate (ForwardIterator first, ForwardIterator middle,
ForwardIterator last)
{
ForwardIterator next = middle;
while (first!=next)
{
swap (*first++,*next++);
if (next==last) next=middle;
else if (first==middle) middle=next;
}
}
int main () {
std::vector myvector;
// set some values:
for (int i=1; i<10; ++i) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9
std::rotate(myvector.begin(),myvector.begin()+3,myvector.end());
// 4 5 6 7 8 9 1 2 3
// print out content:
std::cout << "myvector contains:";
for (std::vector::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
first(),
input.middle,
input.last(),res.first()
)template
OutputIterator rotate_copy (ForwardIterator first, ForwardIterator middle,
ForwardIterator last, OutputIterator result)
{
result=std::copy (middle,last,result);
return std::copy (first,middle,result);
}
int main () {
int myints[] = {10,20,30,40,50,60,70};
std::vector myvector (7);
std::rotate_copy(myints,myints+3,myints+7,myvector.begin());
// print out content:
std::cout << "myvector contains:";
for (std::vector::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
myvector contains: 40 50 60 70 10 20 30
是一种根据实际数据智能选择排序算法的函数,sort()会将区间[beg,end)内的元素排序,默认升序
sort(v.begin(), v.end()); //实现排序,正序排列
bool cmp(int a,int b)
{
return a>b;//降序排列
}
int array[5]={1,2,3,4,5};
sort(array,array+4,cmp);//通过自定义cmp函数将其改为降序排序
输出为:4 3 2 1 5
sort(str.begin(),str.end());
先放到vector
然后sort(vec.begin(),vec.end());
题目大致是:输入若干行由0和1组成的串,将这些串排序输出。
排序规则是:首先按长度排序,长度相同时,按1 的个数多少进行排序,1 的个数相同时再按ASCII 码值排序。
bool cmp(string s1, string s2)
{
int t1 = count(str1.begin(),str1.end(), '1');
int t2 = count(str2.begin(),str2.end(), '1');
if(s1.length() !=s2.length())
{
return s1.length()
struct myclass {
bool operator() (int i,int j) {
return (i
将range [first1,last1]中的元素与以first2开头的元素进行比较,如果两个范围中的所有元素都匹配,即使顺序不同,也会返回true。
std::array bar = {3,1,4,5,2};
std::is_permutatio cegin()) 这两个是相等的。
按字典序的下一个排列next_permutation
(),按字典序的前一个排列 prev_permutation
(),需要先将其sort升序排列好,再用
do//do-while循环和next_permutation、prev_permutation更配喔~
{
res.push_back(str);
}while(next_permutation(str.begin(),str.end()));
//next_permutation()执行一次 当前的str序列abc 就变成了 升序中的下一个str序列acb
//当 当前的str序列 是 最后一种str序列cba ,那么它就会变成最初的str序列abc
while(next_permutation(num,num+3))中的3改为2时,输出就变为了:
如修改字典序为:'A'<'a'<'B'<'b'<...<'Z'<'z'.请按照这个依次写出排列的内容。
//我把cmp中char a看成是前一个内容,b是后一个内容,return a
lexicographical_compare(first.begin(),first.end(),last.begin(),last.end(),cmp)默认ascii码从小到大,默认前小,返回true
// lexicographical_compare example
#include // std::cout, std::boolalpha
#include // std::lexicographical_compare
#include // std::tolower
// a case-insensitive comparison function:
bool mycomp (char c1, char c2)
{ return std::tolower(c1)
vector::itertation iter = find(vec.begin(),vec.end(),value);
if(iter!=vec.end())
//说明存在,iter就是地址,*iter就是value,
//这个是因为,函数设定成这样了,如果find不存在,自动返回vec.end()的地址。
类似地,由于指针的行为与作用在内置数组上的迭代器一样,因此也可以使用find来搜索数组:
int ia[6] = {27 , 210 , 12 , 47 , 109 , 83};
int search_value = 83;
int *result = find(ia , ia + 6 , search_value);
cout<<"The value "<
roster1可以是list对象,而roster2则可以是vector对象、 deque对象或者是其他序列。只要这两个序列的的元素可使用相等(==)操作符进行比较即可。如果roster1是list< string>对象,则roster2可以使vector
这个算法带有两对迭代器参数来标记两端元素范围:第一段范围内查找与第二段范围中任意元素匹配的元素,然后返回一个迭代器,指向第一个匹配的元素。如果找不到匹配元素,则返回第一个范围的end迭代器。
假设roster1和roster2是两个存放名字的list对象,可使用find_first_of统计有多少个名字同时出现在这两个列表中:
size_t cnt = 0;
list::iterator it = roster1.begin();
// look in roster1 for any name also in roster2
while((it = find_first_of(it , roster1.end() , roster2.begin() , roster2.end())) != roster1.end())
{
++cnt;
// we got a match , increment it to look in the rest of roster1
++it;
}
cout<<"Found "<
//谓词判断函数 divbyfive : 判断x是否能5整除
bool divbyfive(int x)
{return x % 5 ? 0 : 1;}
参考自:https://blog.csdn.net/hyg0811/article/details/10390591
bool myfunction (int i, int j) {
return (i==j);//前一个等于后一个
}
int main () {
int myints[] = {5,20,5,30,30,20,10,10,20};
std::vector myvector (myints,myints+8);
std::vector::iterator it;
// using default comparison:
it = std::adjacent_find (myvector.begin(), myvector.end());
if (it!=myvector.end())
std::cout << "the first pair of repeated elements are: " << *it << '\n';
//using predicate comparison:
it = std::adjacent_find (++it, myvector.end(), myfunction);
if (it!=myvector.end())
std::cout << "the second pair of repeated elements are: " << *it << '\n';
return 0;
}
Output:
the first pair of repeated elements are: 30
the second pair of repeated elements are: 10
双向迭代器 BidirectionalIterator stable_partition (BidirectionalIterator first, BidirectionalIterator last, UnaryPredicate pred)
返回值:指向第二组(哪些使pred返回false)第一个元素的迭代器,或者第二组为空,返回last.
如:奇数在前,偶数在后,传统的方法,是定义前后指针,前面的指针如果指向的值是奇数就遍历,偶数就不动(while),后指针,如果指向的是偶数就遍历,奇数就不动,然后再前后交换,使得奇数在前,偶数在后,但是会发生位置的相对变化。利用partition的方法。
bool IsOdd (int i) { return (i%2)==1; }
int main () {
std::vector myvector;
// set some values:
for (int i=1; i<10; ++i) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9
std::vector::iterator bound;
bound = std::stable_partition (myvector.begin(), myvector.end(), IsOdd);
// print out content:
std::cout << "odd elements:";
for (std::vector::iterator it=myvector.begin(); it!=bound; ++it)
std::cout << ' ' << *it;
std::cout << '\n';
std::cout << "even elements:";
for (std::vector::iterator it=bound; it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
odd elements: 1 3 5 7 9
even elements: 2 4 6 8
bool IsOdd (int i) { return ((i%2)==1); }
// equal algorithm example
#include // std::cout
#include // std::equal
#include // std::vector
bool mypredicate (int i, int j) {
return (i==j);
}
int main () {
int myints[] = {20,40,60,80,100}; // myints: 20 40 60 80 100
std::vectormyvector (myints,myints+5); // myvector: 20 40 60 80 100
// using default comparison:
if ( std::equal (myvector.begin(), myvector.end(), myints) )
std::cout << "The contents of both sequences are equal.\n";
else
std::cout << "The contents of both sequences differ.\n";
myvector[3]=81; // myvector: 20 40 60 81 100
// using predicate comparison:
if ( std::equal (myvector.begin(), myvector.end(), myints, mypredicate) )
std::cout << "The contents of both sequences are equal.\n";
else
std::cout << "The contents of both sequences differ.\n";
return 0;
}
一是在找k个小的树的时候
第一种直接构建相关变量
第二种利用push_heap,pop_heap的操作,将一个vector弄成大根堆。
形式一:
typedef multiset> intSet;#直接定义个大根堆
typedef multiset>::iterator intSetIter;
intSet& leastNumbers,如果leastNumbers > intSet;
typedef multiset >::iterator setIterator;
void GetLeastNumbers_Solution2(const vector& data, intSet& leastNumbers, int k)
{
leastNumbers.clear();
if(k < 1 || data.size() < k)
return;
vector::const_iterator iter = data.begin();
for(; iter != data.end(); ++ iter)
{
if((leastNumbers.size()) < k)
leastNumbers.insert(*iter);
else
{
setIterator iterGreatest = leastNumbers.begin();
if(*iter < *(leastNumbers.begin()))
{
leastNumbers.erase(iterGreatest);
leastNumbers.insert(*iter);
}
}
}
}
形式二:
利用函数和vector弄
先定义私有成员变量 vector max;
利用push_heap pop_heap的方式结合vector.pop_back()的方法
max.push_back(num);
push_heap(max.begin(), max.end(), less());
num = max[0];##记录堆顶
pop_heap(max.begin(), max.end(), less());##堆顶和最后的互换
max.pop_back();##弹出最后一个 上两个结合heapify
min.push_back(num);
push_heap(min.begin(), min.end(), greater());
template class DynamicArray
{
public:
void Insert(T num)
{
if(((min.size() + max.size()) & 1) == 0)
{
if(max.size() > 0 && num < max[0])
{
max.push_back(num);
push_heap(max.begin(), max.end(), less());
num = max[0];
pop_heap(max.begin(), max.end(), less());
max.pop_back();
}
min.push_back(num);
push_heap(min.begin(), min.end(), greater());
}
else
{
if(min.size() > 0 && min[0] < num)
{
min.push_back(num);
push_heap(min.begin(), min.end(), greater());
num = min[0];
pop_heap(min.begin(), min.end(), greater());
min.pop_back();
}
max.push_back(num);
push_heap(max.begin(), max.end(), less());
}
}
T GetMedian()
{
int size = min.size() + max.size();
if(size == 0)
throw exception("No numbers are available");
T median = 0;
if((size & 1) == 1)
median = min[0];
else
median = (min[0] + max[0]) / 2;
return median;
}
private:
vector min;
vector max;
};
图片摘自网络
#include
#include
#include
#include
#include
#include
using namespace std;
int main() {
vectorvalid_vec;//有效的字符串
vectorinvalid_vec;//无效字符串
char input[100];
do{// 判断是否 输入结束了
cin.getline(input, 100);
bool valid = true;
int i = 0;
do{//判断字符串是否结束了
charc = input[i];
if (!isalnum(c)) {
valid = false;
break;
}
i++;
} while (input[i] != '\0');//判断字符串是否结束了
if (!valid)
invalid_vec.push_back(input);
else
valid_vec.push_back(input);
} while (input[0] != '\0');//判断输入是否是空行,如果是,就结束了
// 去重valid_vec存储去重后的
setst(valid_vec.begin(), valid_vec.end());
valid_vec.assign(st.begin(), st.end());
//输出去重后的合法字符串
int nums_valid = valid_vec.size();
for (int i = 0; i < nums_valid-1; i++)
{
cout << valid_vec[i] << " ";
}
cout << valid_vec[nums_valid - 1]<