【两万字精编】蓝桥杯算法竞赛系列第0章——蓝桥必考点及标准模板库STL(下)_stl sprintf-CSDN博客
[TOC]
【补充】:常用头文件及库函数
#include<stdio.h>
- scanf()
- printf()
- getchar()
- putchar()
- gets()
- puts()
- sscanf()
- sprintf()
#include<stdlib.h>
主要用于生成随机数以及动态内存开辟,常用的库函数有srand((unsigned int) time(NULL)), rand() 和动态内存开辟用的malloc(),用new会更简单一些
#include<time.h>
上面生成随机数的时候,常用time()函数用于生成时间戳,作为随机数种子
#include<math.h>
- fabs()
- sqrt()
- pow()
- floor()
- ceil()
- round()
(1).fabs(double x)
该函数用于对double 型变量取绝对值。
(2).pow(double r, double p)
该函数用于返回 r ^ p ,要求r 和 p 都是double类型的
(3).sqrt(double x)
该函数用于返回double型变量的算数平方根
#include<string.h>
- strlen()
- strcmp()
- strcpy()
- strcat()
(1).strlen()
strlen()函数可以得到字符数组中第一个\0之前的字符的个数
(2).strcmp()
strcmp()函数返回两个字符串大小的比较结果,比较原则是按字典序,所谓字典序就是字符串在字典中的顺序,因此如果有两个字符数组 str1 和 str2, 且满足str1[0...k - 1] == str2[0...k - 1]、str1[k] < str2[k], 那么就说 str1 的字典序小于 str2。例如"a" 的字典序小于"b"、"aaaa" 的字典序小于"aab"
strcmp()函数的返回值:
- 如果字符数组1 < 字符数组2,则返回一个负整数(不一定是-1,由编译器决定)
- 如果字符数组1 == 字符数组2,则返回0
- 如果字符数组1 > 字符数组2,则返回一个正整数(不一定是1,由编译器决定)
(3).strcpy()
strcpy()函数可以把一个字符串复制给另一个字符串,格式如下:
strcpy(字符数组1, 字符数组2);
注意哦,是把字符数组2复制给字符数组1,这里的“复制” 包括了结束标志\0 ,而且需要特别注意的是字符数组1一定是足够大的!
#include <bits/stdc++.h>
//#include <iostream>
//#include <string.h>
using namespace std;
int main() {
char str1[50] = "Thank";
char str2[50] = "you for your smile.";
strcpy(str1, str2);
puts(str1);
// printf("%s\n", str1);
return 0;
}
you for your smile.
--------------------------------
Process exited after 0.01272 seconds with return value 0
(4).strcat()
strcat()可以把一个字符串拼接到另一个字符串的后面
strcat(字符数组1, 字符数组2);
注意哦,是把字符数组2拼接到字符数组1的后面
#include <bits/stdc++.h>
//#include <iostream>
//#include <string.h>
using namespace std;
int main() {
char str1[50] = "Thank";
char str2[50] = "you for your smile.";
strcat(str1, str2);
puts(str1);
// printf("%s\n", str1);
return 0;
}
Thankyou for your smile.
--------------------------------
Process exited after 0.01203 seconds with return value 0
#include<vector>
常用函数:
- push_back()
- pop_back()
- size()
- clear()
#include<queue>
常用函数:
- push()
- pop()
- front()
- back()
- empty()
- size()
#include<stack>
常用函数:
- push()
- pop()
- top()
- empty()
- size()
#include<algorithm>
常用函数:
- max()
- min()
- swap()
- fill()
- sort()
下面在介绍一些常见的容器:
一、string的常见用法详解
在C语言中,一般使用字符数组
char str[ ]来存放字符串,但是使用字符数组有时会显得操作麻烦,而且容易因经验不足产生错误,得不偿失。为了使编程者可以更方便的对字符串进行操作,C++在STL中加入了string类型,对字符串常用的需求功能进行了封装,使得操作起来更方便,且不易出错。
1.string的定义和初始化
string str1;
string str2 = "abcd";
2.string中内容的访问
(1).通过下标访问
一般来说,可以直接像字符数组那样去访问string:
#include<stdio.h>
#include<string>
using namespace std;
int main() {
string str = "nmsl";
for (int i = 0; i < str.length(); ++i) {
printf("%c ", str[i]);
}
return 0;
}
n m s l
--------------------------------
Process exited after 0.013 seconds with return value 0
注意哦,如果要读入和输出整个字符串,则只能用 cin 和 cout
#include<iostream>
#include<string>
using namespace std;
int main() {
string str;
cin >> str;
cout << str;
return 0;
}
(2).通过迭代器访问
由于string不像其他STL容器那样需要参数,因此可以直接入下定义:
string::iterator it;
这样就得到了迭代器it, 并且可以通过*it 来访问string里的每一位:
#include<iostream>
#include<string>
using namespace std;
int main() {
string str;
str = "n~m~s~l";
for (string::iterator it = str.begin(); it != str.end(); ++it) {
cout << *it << " ";
}
return 0;
}
n ~ m ~ s ~ l
--------------------------------
Process exited after 0.01281 seconds with return value 0
最后指出,string和vector一样,支持直接对迭代器进行加减某个数字,如
str.begin() + 3的写法是可行的
#include<iostream>
#include<string>
using namespace std;
int main() {
string str;
str = "n~m~s~l";
string::iterator iEnd = str.end();
cout << *(str.begin()+6) << "\n";
cout << *(iEnd-1) << "\n";
cout << str.size() << endl;
cout << *(iEnd-7);
return 0;
}
l
l
7
n
--------------------------------
Process exited after 0.01326 seconds with return value 0
3.string常用函数实例解析
- operator+=
- compare operator
- length() / size()
- insert()
- erase()
- clear()
- substr()
- string::nops
- find()
- replace()
(1).operator+=
这是string的加法,可以将两个string直接拼接起来
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str1 = "abc", str2 = "xyz", str3;
str3 = str1 + str2;//将str1和str2拼接,赋值给str3
str1 = str1 + str2;//将str2直接拼接到str1上
cout << str1 << endl;//输出abcxyz
cout << str3 << endl;//输出abcxyz
return 0;
}
(2).compare operator(比较操作符)
示例如下:
#include<stdio.h>
#include<string>
using namespace std;
int main()
{
string str1 = "aa", str2 = "aaa", str3 = "abc", str4 = "xyz";
if (str1 < str2)//如果str1字典序小于str2,输出ok1
{
printf("ok1\n");//输出ok1
}
if (str1 != str3)//如果str1和str3字典序不等,输出ok2
{
printf("ok2\n");//输出ok2
}
if (str4 >= str3)//如果str4字典序大于等于str3,输出ok3
{
printf("ok3\n");//输出ok3
}
return 0;
}
(3).length() / size()
length()返回string的长度,即存放的字符数。时间复杂度为O(1)。size()与length()基本相同
string str = "abcdef";
printf("%d %d\n", str.length(), str.size());//输出6 6
(4).insert()
string的insert()函数有很多种写法,这里给出几种常用的写法。时间复杂度为O(N)
insert(pos, string), 在pos号位置插入一个字符串string
string str = "abcxyz", str2 = "opq";
str.insert(3, str2);//往str[3]处插入opq,将括号里的str2直接写成"opq"也是可以的
cout<<str<<endl;//输出abcopqxyz
insert(it, it2, it3), it 为原字符串的欲插入位置,it2 和 it3 为待插字符串的首尾迭代器,用来表示串 [it2, it3) 将被插在 it 的位置上
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str = "abcxyz", str2 = "opq";//str为原字符串,str2为待插字符串
//在str的3号位(即c和x之间)插入str2
str.insert(str.begin() + 3, str2.begin(), str2.end());
cout << str << endl;//输出abcopqxyz
return 0;
}
(5).erase()
erase()有两种用法:删除单个元素、删除一个区间内的所有元素。时间复杂度均为O(N)
- 删除单个元素:
str.erase(it)用于删除单个元素,it 为需要删除的元素的迭代器
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
string str = "abcdefg";
str.erase(str.begin() + 4);//删除4号位(即e)
cout << str << endl;//输出abcdfg
return 0;
}
- 删除一个区间内的所有元素:有两种方法:
str.erase(first, last), 其中first为需要删除的区间的起始迭代器,而last为需要删除的区间的末尾迭代器的下一个地址,即为删除[first, last)
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str = "abcdefg";
//删除在[str.begin() + 2, str.end() - 1)内的元素,即cdef
str.erase(str.begin() + 2, str.end() - 1);
cout << str << endl;//输出abg
return 0;
}
str.erase(pos, length), 其中pos为需要开始删除的起始位置,length为删除的字符个数。
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str = "abcdefg";
str.erase(3, 2);//删除de
cout << str << endl;//输出abcfg
return 0;
}
(6).clear()
clear()可以清空string中的数据,时间复杂度一般为O(1)
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str = "abcd";
str.clear();//清空字符串
cout << str.length() << endl;//输出0
return 0;
}
(7).substr()
substr(pos, len)返回从pos号位开始、长度为len的子串,时间复杂度为O(len)
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str = "Thank you for your smile.";
cout << str.substr(0, 5) << endl;//输出Thank
cout << str.substr(14, 4) << endl;//输出your
cout << str.substr(19, 5) << endl;//输出smile
return 0;
}
(8).string::npos
string::npos是一个常数,其本身的值为-1 ,但由于是unsigned int 类型,因此实际上也可以认为是unsigned int 类型的最大值,可认为是4,294,967,295。string::npos用以作为 find 函数失配时的返回值。
(9).find()
str.find(str2)当str2 是str 的子串时,返回其在str 中第一次出现的位置,如果str2 不是str 的子串,那么返回string::npos
str.find(str2, pos), 从str 的pos 号位开始匹配str2,返回值与上相同。时间复杂度为O(M*N),M和N 分别是str2 和str的长度
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str = "Thank you for your smile";
string str2 = "you";
string str3 = "me";
if (str.find(str2) != string::npos)
{
cout << str.find(str2) << endl;//输出6
}
if (str.find(str2, 7) != string::npos)
{
cout << str.find(str2, 7) << endl;//输出14
}
if (str.find(str3) != string::npos)
{
cout << str.find(str3) << endl;
}
else
{
cout << "I know there is no position for me." << endl;
}
return 0;
}
(10).replace()
str.replace(pos,len,str2)把str 从pos 号位开始、长度为len 的子串替换为上str2
str.replace(it1,it2,str2)把str 的迭代器[it1, it2)范围的子串替换为str2
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str = "Maybe you will turn around.";
string str2 = "will not";
string str3 = "surely";
cout << str.replace(10, 4, str2) << endl;
cout << str.replace(str.begin(), str.begin() + 5, str3) << endl;
return 0;
}
Maybe you will not turn around.
surely you will not turn around.
--------------------------------
Process exited after 0.01848 seconds with return value 0
二、queue的常见用法详解
queue翻译为队列,在STL中主要则是实现一个先进先出的容器,当需要实现广度优先搜索时,可以不用自己手动实现一个队列,而是用queue代替,以提高程序的准确性。
1.queue的定义
其定义的写法和其他STL容器相同,typename 可以是任意基本数据类型和容器:
queue<typename> name;
2.queue容器内元素的访问
由于队列(queue)本身就是一种先进先出的限制性数据结构,因此在STL中只能通过front() 来访问队首元素,或是通过back() 来访问队尾元素。
#include<stdio.h>
#include<queue>
using namespace std;
int main()
{
queue<int> q;
for (int i = 1; i <= 5; i++)
{
q.push(i);//push(i)用以将i压入队列,因此依次入队1 2 3 4 5
}
printf("%d %d\n", q.front(), q.back());//输出结果为1 5
return 0;
}
3.queue常用函数实例解析
- push()
- front()
- back()
- pop()
- empty()
- size()
(1).push()
push(x) 将 x 进行入队,时间复杂度为O(1)
(2).front(), back()
front(), back() 可以分别获得队首元素和队尾元素,时间复杂度为 O(1)
注意哦,使用 front() 和 pop() 函数之前,必须用 empty() 判断队列是否为空,否则可能会因为队列空导致错误
(3).pop()
pop()令队首元素出队,时间复杂度为O(1)
#include<stdio.h>
#include<queue>
using namespace std;
int main()
{
queue<int> q;
for (int i = 1; i <= 5; i++)
{
q.push(i);
}
for (int i = 0; i < 3; i++)
{
q.pop();//出队列元素3次,依次出队1 2 3
}
printf("%d\n", q.front());//输出4
return 0;
}
(4).empty()
empty() 检测 queue 是否为空,返回 true 则为空,返回 false 则非空,时间复杂度为 O(1)
#include<stdio.h>
#include<queue>
using namespace std;
int main()
{
queue<int> q;
if (q.empty() == true)//一开始队列里没有元素,所以是空
{
printf("Empty\n");
}
else
{
printf("Not Empty\n");
}
q.push(1);
if (q.empty() == true)
{
printf("Empty\n");
}
else
{
printf("Not Empty\n");
}
return 0;
}
(5).size()
size() 返回 queue 内元素的个数,时间复杂度为 O(1)
#include<stdio.h>
#include<queue>
using namespace std;
int main()
{
queue<int> q;
for (int i = 1; i <= 5; i++)
{
q.push(i);
}
printf("%d\n", q.size());//输出5
return 0;
}
【延伸】:STL容器中还有两种容器跟队列有关,分别是双端队列(deque) 和优先队列(priority_queue) ,前者是首尾皆可插入和删除的队列,后者是使用堆实现的默许将当前队列最大元素置于队首的容器,这里暂时先不介绍,后期如果需要再进行补充。
三、stack的常见用法详解
stack 翻译为栈,是STL中实现的一个先进后出的容器,stack 用来模拟实现一些递归,防止程序对栈内存的限制而导致程序运行出错。
1.stack的定义
其定义的写法和其他STL容器相同,typename可以是任意基本数据类型或容器:
stack<typename> name;
2.stack容器内元素的访问
由于栈(stack) 本身就是一种先进后出的数据结构,在STL的stack 中只能通过top() 来访问栈顶元素
#include<stdio.h>
#include<stack>
using namespace std;
int main()
{
stack<int> st;
for (int i = 1; i <= 5; i++)
{
st.push(i);//依次入栈1 2 3 4 5
}
printf("%d\n", st.top());//输出5
return 0;
}
3.stack常用函数实例解析
- push()
- top()
- pop()
- empty()
- size()
(1).push()
push(x) 将x 入栈,时间复杂度为O(1),
(2).top()
top()获得栈顶元素,时间复杂度为O(1)
(3).pop()
pop()用以弹出栈顶元素,时间复杂度为O(1)
#include<stdio.h>
#include<stack>
using namespace std;
int main()
{
stack<int> st;
for (int i = 1; i <= 5; i++)
{
st.push(i);
}
for (int i = 0; i < 3; i++)
{
st.pop();
}
printf("%d\n", st.top());//输出2
return 0;
}
(4).empty()
empty()可以检测stack 内是否为空,返回true 为空,返回false 为非空,时间复杂度为O(1)
(5).size()
size()返回stack 内元素的个数,时间复杂度为O(1)
四、algorithm头文件下的常用函数
- max()、min()、abs()
- swap()
- reverse()
- next_permutation()
- fill()
- sort()
- lower_bound() 和 upper_bound()
1.max()、min()和abs()
max(x,y)和min(x,y) 分别返回x, y中的最大值和最小值,且参数必须是两个,可以是浮点数,如果想返回三个数x,y,z的最大值,可以使用
max(x, max(y, z))的写法;abs(x) 返回x的绝对值。注意:此时的x 必须是整数,浮点数的绝对值请用math 头文件下的fabs
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
int x = -1;
int y = -2;
int z = 0;
printf("%d %d\n", max(x, y), min(x, y));//输出-1 -2
printf( "%d %d\n", max(x, max(y, z)), min(x, min(y, z)) );//输出0 -2
printf("%d %d\n", abs(x), abs(y));//输出1 2
return 0;
}
2.swap()
swap(x, y)用来交换x 和 y 的值
3.reverse()
reverse(it, it2)可以将数组指针在 [it, it2) 之间的元素或容器的迭代器在 [it, it2) 范围内的元素进行反转
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
int arr[10] = { 10,11,12,13,14,15 };
reverse(arr, arr + 4);//将arr[0]~arr[3]反转
for (int i = 0; i < 6; i++)
{
printf("%d ", arr[i]);//输出13 12 11 10 14 15
}
return 0;
}
如果要是对容器中的元素(例如string 字符串)进行反转,结果也是一样
#include<stdio.h>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
string str = "abcdefghi";
reverse(str.begin() + 2, str.begin() + 6);//对str[2]~str[5]反转
for (int i = 0; i < str.length(); i++)
{
printf("%c", str[i]);//输出abfedcghi
}
return 0;
}
4.next_permutation()
next_permutation()给出一个序列在全排列中得下一个序列
例如,当 n == 3 时的全排列为:
123
132
213
231
312
321
这样231的下一个序列就是312
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
int a[10] = { 1,2,3 };
//a[0]~a[2]之间的序列需要求解next_permutation
do
{
printf("%d%d%d\n", a[0], a[1], a[2]);
} while (next_permutation(a, a + 3));
return 0;
}
在上述的代码中,使用循环是因为next_permutation在已经到达全排列的最后一个时会返回false, 这样会方便退出循环。而使用do...while语句而不使用while语句是因为序列1 2 3本身也需要输出,如果使用while会直接跳到下一个序列再输出,这样的话结果会少一个123
注意:next_permutation(start, end) 是左闭右开的!
5.fill()
fill()可以把数组或容器中的某一段区间赋为某个相同的值。和 memset 不同,这里的赋值可以是数组类型对应范围中的任意值
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
int a[5] = { 1,2,3,4,5 };
fill(a, a + 5, 133);//将a[0]~a[4]均赋值为133
for (int i = 0; i < 5; i++)
{
printf("%d ", a[i]);//输出133 133 133 133 133
}
return 0;
}
6.sort()
顾名思义,sort()就是用来排序的函数,它根据具体情形使用不同的排序方法,效率较高。一般来说,不推荐使用C语言中的qsort函数,原因是qsort 用起来比较繁琐,涉及很多指针的操作。
- 如何使用sort排序?
sort函数的使用必须加上头文件#include<algorithm> 和 "using namespace std;",其使用的方式如下:
sort(首元素地址(必填),尾元素地址的下一个地址(必填),比较函数(非必填));
可以看到,sort的参数有三个,其中前两个是必填的,而比较函数则可以根据需要填写,如果不写比较函数,则默认对前面给出的区间进行递增排序。
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
int a[6] = { 9,4,2,5,6,-1 };
//将a[0]~a[3]进行从小到大排序
sort(a, a + 4);
for (int i = 0; i < 6; i++)
{
printf("%d ", a[i]);//输出2 4 5 9 6 -1
}
putchar('\n');
//将a[0]~a[5]进行从小到大排序
sort(a, a + 6);
for (int i = 0; i < 6; i++)
{
printf("%d ", a[i]);//输出-1 2 4 5 6 9
}
putchar('\n');
//将a[0]~a[5]进行从大到小排序
sort(a, a + 6, greater<int>());
for (int i = 0; i < 6; i++)
{
printf("%d ", a[i]);//输出9 6 5 4 2 -1
}
return 0;
}
【敲黑板】:特别需要注意理解的是尾元素地址的下一个地址!
对double数组进行排序:
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
double a[] = { 1.4, -2.1, 9 };
sort(a, a + 3);
for (int i = 0; i < 3; i++)
{
printf("%.1lf ", a[i]);//输出-2.1 1.4 9.0
}
return 0;
}
对char型数组进行排序(默认是字典序)
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
char c[] = { 'T', 'W','A', 'K' };
sort(c, c + 4);
for (int i = 0; i < 4; i++)
{
printf("%c", c[i]);//输出AKTW
}
return 0;
}
我们需要知道的是,如果对序列进行排序,那么序列中的元素一定要有可比性,因此需要制定排序规则来建立这种可比性。特别是像结构体,本身并没有大小关系,需要认为制定比较的规则。sort 的第三个可选参数就是cmp函数,用来实现这个规则。
如何实现比较函数cmp
下面介绍对基本数据类型、结构体类型、STL容器进行自定义规则排序时cmp的写法。
<1>.基本数据类型数组的排序
如果想要从大到小来排序,则要使用比较函数cmp 来“告诉”sort 何时要交换元素(让元素的大小比较关系反过来)
#include<stdio.h>
#include<algorithm>
using namespace std;
bool cmp(int a, int b) {
return a > b;//可以理解为当a>b时把a放在b前面
}
int main()
{
char c[] = { 'T', 'W','A', 'K' };
sort(c, c + 4, cmp);
for (int i = 0; i < 4; i++)
{
printf("%c", c[i]);//输出WTKA
}
return 0;
}
【记忆方法】:
如果要把数据从小到大排列,那么就用'<', 因为"a<b" 就是左小右大;如果要把数据从大到小排列,那么就用'>', 因为"a>b" 就是左大右小。而当不确定或者忘记的时候,不妨两种都试一下,就会知道该用哪种了。
<2>.结构体数组的排序
现在定义了如下结构体:
struct node{
int x, y;
}ssd[10];
如果想将ssd数组按照 x 从大到小排序(即进行一级排序),那么可以这样写cmp函数:
bool cmp(node a, node b){
return a.x > b.x;
}
示例如下:
#include<stdio.h>
#include<algorithm>
using namespace std;
struct node
{
int x;
int y;
}ssd[10];
bool cmp(node a, node b)
{
return a.x > b.x;//按x值从大到小对结构体数组进行排序
}
int main()
{
ssd[0].x = 2;
ssd[0].y = 2;
ssd[1].x = 1;
ssd[1].y = 3;
ssd[2].x = 3;
ssd[2].y = 1;
sort(ssd, ssd + 3, cmp);
for (int i = 0; i < 3; i++)
{
printf("%d %d\n", ssd[i].x, ssd[i].y);
}
return 0;
}
3 1
2 2
1 3
--------------------------------
Process exited after 0.0284 seconds with return value 0
而如果想先按x 从大到小排序,但当x相等的情况下,按照y的大小从小到大来排序(即进行二级排序),那么cmp的写法是:
bool cmp(node a, node b)
{
if(a.x != b.x)
{
return a.x > b.x;
}
else
{
return a.y < b.y;
}
}
<3>.容器的排序
在STL标准容器中,只有vector、string、deque是可以使用sort的。这是因为像set、map这种容器是用红黑树实现的(了解即可),元素本身有序,故不允许使用sort排序
vector示例如下:
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
bool cmp(int a, int b)//因为vector中的元素为int型,因此仍然是int的比较
{
return a > b;
}
int main()
{
vector<int> vi;
vi.push_back(3);
vi.push_back(1);
vi.push_back(2);
sort(vi.begin(), vi.end(), cmp);
for (vector<int>::iterator it = vi.begin(); it != vi.end(); it++)
{
printf("%d ", *it);//输出3 2 1
}
return 0;
}
再来看string 的排序,示例如下:
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
string str[3] = { "bbbb", "cc", "aaa" };
sort(str, str + 3);//将string数组按字典树从小到大输出
for (int i = 0; i < 3; i++)
{
cout << str[i] << endl;
}
return 0;
}
如果上面这个例子中,需要按照字符串长度从小到大排序,那么可以这样写:
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
bool cmp(string str1, string str2)
{
return str1.length() < str2.length();//按照string 的长度从小到大排序
}
int main()
{
string str[3] = { "bbbb", "cc", "aaa" };
sort(str, str + 3, cmp);
for (int i = 0; i < 3; i++)
{
cout << str[i] << endl;
}
return 0;
}
7.lower_bound()和upper_bound()
lower_bound() 和 upper_bound() 需要用在一个有序数组或容器中
lower_bound(first, last, val) 用来寻找在数组或容器的[first, last) 范围内第一个值大于等于val元素的位置,如果是数组,则返回该位置的指针;如果是容器,则返回该位置的迭代器。
upper_bound(first, last, val) 用来寻找在数组或容器的[first, last) 范围内第一个值大于val 的元素的位置,如果是数组,则返回该位置的指针;如果是容器,则返回该位置的迭代器。
显然,如果数组或容器中没有需要寻找的元素,则 lower_bound() 和 upper_bound() 均返回可以插入该元素的位置的指针或迭代器(即假设存在该元素时,该元素应当在的位置)。
示例如下:
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
int a[10] = { 1,2,2,3,3,3,5,5,5,5 };
//寻找-1
int* lowerPos = lower_bound(a, a + 10, -1);
int* upperPos = upper_bound(a, a + 10, -1);
printf("%d %d\n", lowerPos - a, upperPos - a);//输出0 0
//寻找1
lowerPos = lower_bound(a, a + 10, 1);
upperPos = upper_bound(a, a + 10, 1);
printf("%d %d\n", lowerPos - a, upperPos - a);//输出0 1
//寻找3
lowerPos = lower_bound(a, a + 10, 3);
upperPos = upper_bound(a, a + 10, 3);
printf("%d %d\n", lowerPos - a, upperPos - a);//输出3 6
//寻找4
lowerPos = lower_bound(a, a + 10, 4);
upperPos = upper_bound(a, a + 10, 4);
printf("%d %d\n", lowerPos - a, upperPos - a);//输出6 6
//寻找6
lowerPos = lower_bound(a, a + 10, 6);
upperPos = upper_bound(a, a + 10, 6);
printf("%d %d\n", lowerPos - a, upperPos - a);//输出10 10
return 0;
}
显然,如果只想获得欲查元素的下标,就可以不使用临时指针,而直接令返回值减去数组首地址即可。
【敲黑板】:这里补充一条知识点,指针 - 指针 = 两指针之间的元素个数
示例如下:
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
int a[10] = { 1,2,2,3,3,3,5,5,5,5 };
//寻找3
printf("%d %d\n", lower_bound(a, a + 10, 3) - a, upper_bound(a, a + 10, 3) - a);//输出3 6
return 0;
}