# vector

向量,变长数组(长度根据需要而自动改变的数组)

# 使用前

添加

#include <vector>
using namespace std;

# 定义

# 一维

vector <typename> name;

vector<int> name;
vector<double> name;
vector<char> name;
vector<node> name;//node是结构体类型

vector <vector <int> > name; //>>之间要加空格

# 二维

vector<typename> Arrayname[arraySize];
vector<int> vi[100];

vector<vector<int> > namevector<int> name[Size] 不同,后者的一维长度固定为 Size

# 访问

# 通过下标访问

vi[index]

# 通过迭代器进行访问

vector<typename>::iterator it;

vector<int>::iterator it;
vector<double>::iterator it;

使用 *it 访问 vector 里面的元素

# 常用函数

* push_back()		在vector后面添加一个元素
* pop_back()		删除vector的尾元素
* size()			获得vector()中元素的个数
* clear()			清空vector中的所有元素
* insert()			用来向vector的任意迭代器it处插入一个元素x
* erase()
	erase(it)		删除迭代器为it处的元素
	erase(first, last)		删除[first, last)内的所有元素

上面的 insert 和 erase 是只能用迭代器的吗? 是的,可以输入看看代码提示

# set

集合,内部自动有序且不含重复元素的容器

# 使用前添加

#include <set>
using namespace std;

# 访问

只能通过迭代器访问

set<typename>::iterator it;
set<int>::iterator it;

由于除开 vector 和 string 之外的 STL 容器都不支持 *(it+i) 的访问方式,因此只能按如下方式枚举

#include <stdio.h>
#include <set>
using namespace std;
int main(void)
{
	set<int> st;
	st.insert(3);
	st.insert(5);
	st.insert(2);
	st.insert(3);
	for (set<int>::iterator it = st.begin(); it != st.end(); it++)
		printf("%d ", *it);
	return 0;
}

set 内的元素自动递增排序,且自动去除了重复元素

# 常用函数

* insert(x)		将x插入set容器中,并自动递增排序和去重
* find(value)	返回set中对应值为value的迭代器,如果没找到则返回s.end(),末尾迭代器的后一个迭代器
* erase()
	* st.erase(it)		it为所需要删除元素的迭代器(删除单个元素)
	* st.erase(value)	value为所需要删除元素的值(删除单个元素)
	* st.erase(first, second)	first为所需要删除区间的起始迭代器,second为所需要删除区间的末尾迭代器的下一个地址
* size()	获得set内元素的个数
* clear()	清空set中的所有元素
* count(u)	查询u在set中出现的次数(0或1)

# string

# 使用前添加

#include <string>
using namespace std;

# 定义

string str;
string str = "abcd";  // 可以在定义时直接初始化

# 访问

#### 通过下标

str[index]

如果要读入和输出整个字符串,则只能用 cin 和 cout

#include <iostream> //cin 和 cout 在 iostream 头文件中
#include <string>
using namespace std;
int main(void)
{
	string str;
	cin >> str;
	cout << str;
	return 0;
}

c_str() 将 string 类型转换为字符数组,用 printf 进行输出

#include <iostream> //cin 和 cout 在 iostream 头文件中
#include <string>
using namespace std;
int main(void)
{
	string str = "abcd";
	printf("%s", str.c_str());
	return 0;
}

# 通过迭代器

# 定义
string::iterator it;

通过 * it 来访问 string 里的每一位

#include <iostream>
#include <string>
using namespace std;
int main(void)
{
	string str = "abcd";
	for (string::iterator it = str.begin(); it != str.end(); it++)
		printf("%c", *it);
	return 0;
}

string 和 vector 一样,支持直接对迭代器进行加减某个数字,如 str.begin () + 3 的写法是可行的

# 常用函数

  • operator+= 将两个 string 直接拼接起来

    #include <iostream>
    #include <string>
    using namespace std;
    int main(void)
    {
    	string str1 = "abc", str2 = "xyz", str3;
    	str3 = str1 + str2;  // 将 str1 和 str2 拼接起来,赋值给 str3
    	str1 += str2;  // 将 str2 直接拼接到 str1 上
    	cout << str1 << endl;
    	cout << str3 << endl;
    	//abcxyz
    	return 0;
    }
  • compare operator

    两个 string 类型可以直接使用 ==、!=、<、<=、>、>= 比较大小,比较规则是字典序

    #include <iostream>
    #include <string>
    using namespace std;
    int main(void)
    {
    	string str1 = "aa", str2 = "aaa", str3 = "abc", str4 = "xyz";
    	if (str1 < str2)
    		cout << "ok1" << endl;
    	if (str1 != str3)
    		cout << "ok2" << endl;
    	if (str4 > str3)
    		cout << "ok3" << endl;
    	return 0;
    }
  • length()/size()

    str.size();
  • insert()

    • insert (pos, string) 在 pos 号位置插入字符串 string

      string str1 = "abcxyz", str2 = "opa";
      str1.insert(3, str2);  // 往 str2 [3] 处插入 opq,这里 str2 直接写成 "opq" 也是可以的
      //abcopqxyz
    • insert (it, it2, it3) it 为原字符串的欲插入位置,it2 和 it3 为待插入字符串的首尾迭代器,用来表示串 [it2, it3) 将被插在 it 的位置上

      #include <iostream>
      #include <string>
      using namespace std;
      int main(void)
      {
      	string str = "abcxyz", str2 = "opq";
      	str.insert(str.begin() + 3, str2.begin(), str2.end());
      	return 0;
      }
  • erase()

    • str.erase (it) 用于删除单个元素,it 为需要删除的元素的迭代器
    • str.erase (first, last) first 为需要删除区间的起始迭代器,last 为需要删除区间的末尾迭代器的下一个地址
    • str.erase (pos, length),pos 为需要开始删除的起始位置(整数),length 为删除的字符个数
  • clear () 清空 string 中的数据

  • substr (pos, len) 返回从 pos 位开始、长度为 len 的子串

  • string::npos

    string::npos 是一个常数,其本身的值为 - 1,但由于是 unsigned_int 类型,因此实际上也可以认为是 unsigned_int 类型的最大值。string_npos 用以作为 find 函数失配时的返回值。

    #include <iostream>
    #include <string>
    using namespace std;
    int main(void)
    {
    	if (string::npos == -1)
    		cout << "-1 is true." << endl;
    	if (string::npos == 4294967295)
    		cout << "4294967295 is also true." << endl;
    	return 0;
    }
  • find()

    • str.find (str2) 当 str2 是 str 的子串(str 也可以是一个字符)时,返回其在 str 中第一次出现的位置(字符串中字符的位置编号从 0 开始);如果 str2 不是 str 的子串,那么返回 string::npos
    • str.find (str2, pos) 从 str 的 pos 号位开始匹配 str2,返回值与上相同
  • replace()

    • str.replace (pos, len, str2) 把 str 从 pos 号位开始、长度为 len 的子串替换为 str2
    • str.replace (it1, it2, str2) 把 str 的迭代器 [it1, it2) 范围的子串替换为 str2

# 注:

可以直接将字符和 string 类型的字符串通过 + 拼接起来

string str;
str = '0' + str;

但是,不能加上一个整数,以下两种都是错误的

str = '0' + 2 + str;
str = ('0' + 2) + str;

应改为

str = char('0' + 2) + str;

# map

map 可以将任何基本类型(包括 STL 容器)映射到任何基本类型(包括 STL 容器)

# 使用前添加

#include <map>
using namespace std;

# 定义

map<typename1, typename2> mp;

map<int, int> mp;
map<string, int> mp;
map<set<int>, string> mp;

# 访问

# 通过下标

map<char, int> mp;
mp['a'] = 20;
printf("%d", mp['a']);

# 通过迭代器

# 定义
map<typename1, typename2>::iterator it;

通过 it->first 访问键, it->second 访问值

# 代码
#include <stdio.h>
#include <map>
#include <iostream>
using namespace std;
int main(void)
{
	map<char, int> mp;
	mp['a'] = 1;
	mp['b'] = 2;
	mp['c'] = 3;
	for (map<char, int>::iterator it = mp.begin(); it != mp.end(); it++)
		cout << it->first << it->second << endl;
}

map 会以键从小到大的顺序自动排序

# 插入

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main(void)
{
	map<int, string> mp;
	mp.insert(make_pair(0, "zero"));
	mp.insert(pair<int, string>(1, "one"));
	mp[2] = "two";
	for (map<int, string>::iterator it = mp.begin(); it != mp.end(); it++)
	{
		cout << it->first << " " << it->second << endl;
	}
}

以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,用 insert 函数插入数据,在数据的 插入上涉及到集合的唯一性这个概念,即当 map 中有这个关键字时,insert 操作是不能在插入数据的,但是用数组方式就不同了,它可以覆盖以前该关键字对 应的值

# 常用函数

* find(key)		返回键为key的映射的迭代器
  
* erase()
    mp.erase(it)	it为需要删除元素的迭代器
    mp.erase(key)	key为欲删除的映射的键
    mp.erase(first, last)	first为需要删除区间的起始迭代器,last为需要删除区间的末尾迭代器的下一个地址
  
* size()	获得map中映射的对数
  
* clear()	清空map中的所有元素
  
* count(x)	x为数对中的first,返回个数,即:有则返回1,没有则返回0
#include <iostream>
#include <map>
using namespace std;
map<int, int> mp;
int main()
{
	mp[1] = 0;
	cout << mp.count(1) << endl;  //1
	cout << mp.count(2) << endl;  //0
	cout << mp.count(2) << endl;  //0
}

#

如果有 map<int, int> mp ,但实现并没有存储 mp[0] 而直接输出时, mp[0] 为 0

如果有 map<string, string> mp ,但并没有存储 mp["s"] 而直接输出时, mp["s"] 为空字符串 ""

#include <iostream>
#include <string>
#include <map>
using namespace std;
int main(void)
{
	map<string, int> m;
	cout << m["jjj"] << endl;
}
// 输出 0

# queue

# 使用前添加

#include <queue>
using namespace std;

# 定义

queue<typename> name;

# 常用函数

* push()	入队
* front()	获得队首元素
* back()	获得队尾元素
* pop()		队首元素出队

# priority_queue

# 使用前添加

#include <queue>
using namespace std;

# 定义

priority_queue<typename> name;

# 访问

只能通过 top() 函数访问队首元素(也可以称为堆顶元素),即优先级最高的元素。

#include <iostream>
#include <queue>
using namespace std;
int main(void)
{
	priority_queue<int> q;
	q.push(3);
	q.push(4);
	q.push(1);
	cout << q.top() << endl; // 输出 4
	return 0;
}

# 常用函数

* push()  q.push(x)将x入队
* top()   q.top()获得队首元素
* pop()   q.pop()令队首元素(即堆顶元素)出队
* empty()  检测优先队列是否为空,返回true则空,返回false则非空
* size()  返回优先队列内元素的个数

# 元素优先级的设置

# 基本数据类型

(int、double、char 等),优先队列对它们的优先级设置一般是数字大的优先级越高(如果是 char 型,则是字典序最大的)。对基本数据类型来说,下面两种优先队列的定义时等价的(以 int 型为例,注意最后两个 > 之间有一个空格)

priority_queue<int> q;
priority_queue<int, vector<int>, less<int> > q;

第二种定义方式的尖括号内多出了两个参数:一个是 vector <int> ,另一个是 less <int> 。其中 vector <int> 填写的是来承载底层数据结构堆(heap)的容器,如果第一个参数是 double 或 char 型,则此处填写的是 vector <double> 或 vector <char> ;而第三个参数 less <int> 则是对第一个参数的比较类,less <int> 表示数字大的优先级大,而 greater <int> 表示数字小的优先级越大。

如果想让优先队列总是把最小的元素放在队首,只需进行如下定义:

priority_queue<int, vector<int>, greater<int> > q;

# 结构体

小于号的作用不变(return 中还是小于号),则数字大的优先级高

对水果的名称和价格建立一个结构体

struct fruit{
    string name;
    int price;
}

现在希望按水果的价格高的为优先级高,就需要重载(overload)小于号 “<”。重载是指对已有的运算符进行重新定义,也就是说,可以改变小于号的功能(例如把它重载为大于号的功能)。

struct fruit{
    string name;
    int price;
    friend bool operator < (fruit f1, fruit f2)
    {
        return f1.price < f2.price;
    }
}

可以看到,fruit 结构体中增加了一个函数,其中 “friend” 为友元。后面的 bool operator < (fruit f1, fruit f2) 对 fruit 类型的操作符 < 进行了重载(重载大于号会编译错误,因为从数字上来说只需要重载小于号,即 f1> f2 等价于判断 f2 < f1,而 f1 == f2 则等价于判断!(f1 < f2) && !(f2 < f1),函数内部为 return f1.price < f2.price ,因此重载后小于号还是小于号的作用。此时就可以直接定义 fruit 类型的优先队列,其内部就是以价格高的水果为优先级高。

priority_queue<fruit> q;

同理,如果想要以价格低的水果为优先级高,那么只需要把 return 中的小于号改为大于号即可。

#include <iostream>
#include <string>
#include <queue>
using namespace std;
struct fruit {
	string name;
	int price;
	friend bool operator < (fruit f1, fruit f2)
	{
		return f1.price > f2.price;
	}
}f1, f2, f3;
int main(void)
{
	priority_queue<fruit> q;
	f1.name = "桃子";
	f1.price = 3;
	f2.name = "梨子";
	f2.price = 4;
	f3.name = "苹果";
	f3.price = 1;
	q.push(f1);
	q.push(f2);
	q.push(f3);
	cout << q.top().name << " " << q.top().price << endl;
	return 0;
}

此处对小于号的重载与排序函数 sort 中的 cmp 函数有些相似,它们的参数都是两个变量,函数内部都是 return 了 true 或者 false。事实上,这两者的作用确实是类似的,只不过效果看上去似乎是 “相反的”。在排序中,如果是 return f1.price > f2.price ,那么则是按价格从高到低排序,但是在优先队列中却是把价格低的放到队首。原因在于,优先队列本身默认的规则就是优先级高的放在队首,因此把小于号重载为大于号的功能时只是把这个规则反向了一下。

跟 sort 中的 cmp 函数那样写在结构体外面:只需要把 friend 去掉,把小于号改成一对小括号,然后把重载的函数写在结构体外面,然后把重载的函数写在结构体外面,同时将其用 struct 包装起来,如下

struct cmp {
	bool operator () (fruit f1, fruit f2)
	{
		return f1.price > f2.price;
	}
};

在这种情况下,需要用之前讲解的第二种定义方式来定义优先队列:

priority_queue<fruit, vector<fruit>, cmp> q;

可以看到,此处只是把 greater<> 部分换成了 cmp

#include <iostream>
#include <string>
#include <queue>
using namespace std;
struct fruit {
	string name;
	int price;
}f1, f2, f3;
struct cmp {
	bool operator () (fruit f1, fruit f2)
	{
		return f1.price > f2.price;
	}
};
int main(void)
{
	priority_queue<fruit, vector<fruit>, cmp> q;
	f1.name = "桃子";
	f1.price = 3;
	f2.name = "梨子";
	f2.price = 4;
	f3.name = "苹果";
	f3.price = 1;
	q.push(f1);
	q.push(f2);
	q.push(f3);
	cout << q.top().name << " " << q.top().price << endl;
	return 0;
}

最后指出,如果结构体内的数据较为庞大(例如出现了字符串或者数组),建议使用引用来提高效率,此时比较类的参数中需要加上 const& ,如下所示:

friend bool operator < (const fruit & f1, const fruit & f2)
    return f1.price < f2.price;
bool operator () (const fruit& f1, const fruit & f2)
    return f1.price < f2.price;

# 应用

  • 可以采用从小到大的优先队列实现哈夫曼树的计数

# deque

# 使用前添加

#include <deque>
using namespace std;

# 定义

deque<typename> name;
deque<int> d;

# 常用函数

* begin()		返回指向容器中第一个元素的迭代器
* end()			返回指向容器中最后一个元素所在位置后一个位置的迭代器
* rbegin()		返回指向最后一个元素的迭代器
* rend()		返回指向第一个元素所在位置的前一个位置的迭代器
* size()		返回实际元素个数
* empty()		判断容器中是否有元素,若无元素,则返回true,否则返回false
* front()		返回第一个元素的引用
* back()		返回最后一个元素的引用
* push_back()	在序列的尾部添加一个元素
* push_front()	在序列的头部添加一个元素
* pop_back()	移除容器尾部的元素
* pop_front()	移除容器头部的元素

# stack

# 使用前添加

#include <stack>
using namespace std;

# 定义

stack<typename> name;

# 访问

只能通过 top() 访问栈顶元素

st.top()

# 常用函数

* push()  st.push(x)将x入栈
* top()	  st.top()获得栈顶元素
* pop()	  st.pop()弹出栈顶元素
* empty()  st.empty()检测stack内是否为空,返回true为空,返回false为非空
* size()  st.size()返回st内的元素个数

# pair

# 使用前添加

#include <utility>
using namespace std;

注:由于 map 的内部实现中设计 pair,因此添加 map 头文件时会自动添加 utility 头文件,此时如果需要使用 pair,就不需要额外再去添加 utility 头文件了。因此,记不住 “utility” 拼写的读者可以偷懒的用 map 头文件来代替 utility 头文件。

# 定义

pair 有两个参数,分别对应 first 和 second 的数据类型,它们可以是任意的基本数据类型或容器

pair<typename1, typename2> name;
pair<string, int> p;
pair<string, int> p("haha", 5);// 后面跟上填写有想要初始化的元素的小括号进行初始化

如果想要在代码中临时构建一个 pair,有如下两种方法

  • pair<string, int>("haha", 5)
  • make_pair("haha", 5)

# 访问

按结构体的方式去访问

#include <iostream>
#include <utility>
#include <string>
using namespace std;
int main(void)
{
	pair<string, int> p;
	p.first = "haha";
	p.second = 5;
	cout << p.first << " " << p.second << endl;
	p = make_pair("xixi", 55);
	cout << p.first << " " << p.second << endl;
	p = pair<string, int>("heihei", 555);
	cout << p.first << " " << p.second << endl;
	return 0;
}

# 常用函数

  • 比较操作数 两个 pair 类型数据可以直接使用 ==、!=、<、<=、>、>= 比较大小,比较规则是先以 first 的大小作为标准,只有当 first 相等时才去判别 second 的大小
pair<int, int> p1(5, 10);
pair<int, int> p2(2, 5);
if(p1 < p2) printf("y");

# 用途

  1. 用来代替二元结构体及其构造函数
  2. 作为 map 的键值对来进行插入
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main(void)
{
	map<string, int> mp;
	mp.insert(make_pair("haha", 5));
	mp.insert(pair<string, int>("heihei", 10));
	for (map<string, int>::iterator it = mp.begin(); it != mp.end(); it++)
		cout << it->first << " " << it->second << endl;
	return 0;
}

# algorithm 头文件下的常用函数

需要在头问下加一行 using namespace std; 才能正常使用

# 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。

# swap()

swap (x, y) 用来交换 x 和 y 的值

# reverse()

reverse (it, it2) 可以将数组指针在 [it, it2) 之间的元素或容器的迭代器在 [it, it2) 范围内的元素进行反转。

# fill()

fill () 可以把数组或容器中的某一段区间赋为相同的值。和 memset 不同,这里的赋值可以是数组类型对应范围中的任意值。

#include <iostream>
#include <algorithm>
using namespace std;
int main(void)
{
    int a[5] = {1, 2, 3, 4, 5};
    fill(a, a + 5, 233);  // 将 a [0]~a [4] 均赋值为 233
    for(int i = 0; i < 5, i++)
        cout << a[i] << " ";
}
/*
a 为起始元素的地址,5 为元素
*/

# sort()

使用方式

sort(首元素地址(必填), 尾元素地址的下一个地址(必填), 比较函数(非必填));

如果不写比较函数,则默认对前面给出的区间进行递增排序。

# unique()

功能是将数组中相邻的重复元素去除。然而其本质是将重复的元素移动到数组的末尾,最后再将迭代器末尾指向第一个重复元素的下标(最后一个元素的下一个元素)。

unique 函数可以去除数组中相邻重复项。例如:

输入数组 a[]={1,2,3,4,4,5,6,6,6,7,8,6,7,8}

输出数组 a[]={1,2,3,4,5,6,7,8,6,7,8}

注意:想要实现完全去重功能,需要在执行 unique 函数之前先对数组进行排序。

#include<bits/stdc++.h>
using namespace std;
const int N = 100000;
int a[N+5];
int main()
{
    int n;
    while (cin>>n)
    {
        for (int i = 0;i < n;++i)
        {
            scanf("%d",&a[i]);
        }
        sort(a,a+n);

        n = unique(a,a+n) - a;  //n为元素个数

        for (int i = 0;i < n;++i)
        {
            printf("%d ",a[i]);
        }
        puts("");
    }
    return 0;
}

# 实现基本比较函数 cmp

# 基本数据类型数组的排序

若比较函数不填,则默认从小到大的顺序排序。

如果想要从大到小来排序,则要使用比较函数 cmp 来 “告诉” sort 何时要交换元素(让元素的大小比较关系反过来)。

#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
bool cmp(int a, int b)
{
	return a > b;  // 可以理解为当 a > b 时把 a 放在 b 前面
}
int main(void)
{
	int a[] = { 3, 1, 4, 2 };
	sort(a, a + 4, cmp);
	for (int i = 0; i < 4; i++)
		cout << a[i] << " ";
	return 0;
}

对 double 和 char 型的数组排序只需要把上面的 int 改成 double 或者 char 即可。

记忆方法:如果要把数据从小到大排序,那么就用”<“,因为”a < b“就是左小右大;如果要把数据从大到小排列,那么就用”>“,因为”a > b“就是左大右小。

# 结构体数组的排序

如果想将 ssd 数组按照 x 从大到小排序(即进行一级排序),则代码如下:

#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct node {
	int x, y;
}ssd[10];
bool cmp(node a, node b)
{
	return a.x > b.x;  // 按 x 值从大到小对结构体数组排序
}
int main(void)
{
	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++)
		cout << ssd[i].x << " " << ssd[i].y << endl;
}

而如果想先按 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;
}
# 容器的排序

在 STL 标准容器中,只有 vector、string、deque 是可以使用 sort 的。这是因为像 set、map 这种容器是用红黑树实现的,元素本身有序,故不允许使用 sort 排序。

以 vector 为例:

#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool cmp(int a, int b)  // 因为 vector 中的元素为 int 型,因此仍然是 int 的比较
{
	return a > b;
}
int main(void)
{
	vector<int> v;
	v.push_back(3);
	v.push_back(1);
	v.push_back(2);
	sort(v.begin(), v.end(), cmp);
	for (int i = 0; i < 3; i++)
		cout << v[i] << " ";
}

string 的排序

#include <stdio.h>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main(void)
{
	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 <stdio.h>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
bool cmp(string str1, string str2)
{
	return str1.length() < str2.length();
}
int main(void)
{
	string str[3] = { "bbbb", "cc", "aaa" };
	sort(str, str + 3, cmp);  // 将 string 型数组按字典序从小到大输出
	for (int i = 0; i < 3; i++)
		cout << str[i] << endl;
	return 0;
}

# 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(void)
{
	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);
	// 寻找 1
	lowerPos = lower_bound(a, a + 10, 1);
	upperPos = upper_bound(a, a + 10, 1);
	printf("%d, %d\n", lowerPos - a, upperPos - a);
	// 寻找 3
	lowerPos = lower_bound(a, a + 10, 3);
	upperPos = upper_bound(a, a + 10, 3);
	printf("%d, %d\n", lowerPos - a, upperPos - a);
	// 寻找 6
	lowerPos = lower_bound(a, a + 10, 6);
	upperPos = upper_bound(a, a + 10, 6);
	printf("%d, %d\n", lowerPos - a, upperPos - a);
	return 0;
}

显然,如果只是想获得欲查元素的下标,就可以不使用临时指针,而直接令返回值减去数组首地址即可:

更新于

请我喝[茶]~( ̄▽ ̄)~*

yuan 微信支付

微信支付

yuan 支付宝

支付宝

yuan 贝宝

贝宝