Skip to content

sort(begin,end,cmp)函数

c++
//该函数位于#include<algorithm>
//它有三个参数sort(begin, end, cmp),其中begin为指向待sort()的数组的第一个元素的指针,end为指向待sort()的数组的最后一个元素的下一个位置的指针,cmp参数为排序准则,cmp参数可以不写,如果不写的话,默认从小到大进行排序。如果我们想从大到小排序可以将cmp参数写为greater<int>()就是对int数组进行排序,当然<>中我们也可以写double、long、float等等。如果我们需要按照其他的排序准则,那么就需要我们自己定义一个bool类型的函数来传入。比如我们对一个整型数组进行从大到小排序
bool com(string str1,string str2)
{
    int num1=0, num2=0;
    if(str1.length() != str2.length())
        return str1.length() < str2.length();
    else{
        for(char c:str1) if(c == '1') num1++;
        for(char c:str2) if(c == '1') num2++;
        if(num1 != num2) return num1 < num2;
        else return atoi(str1.c_str()) < atoi(str2.c_str());
    }
}
//以此函数为例,sort将会按返回值为true的情况排序

c_str()

c++
//该函数在#include<cstring>头文件中
//该函数返回值为const char *,本身执行的操作是将string类型转化为char数组进行操作,由于cpp在进行赋值时不允许将限制条件少的赋值给限制条件多的。(float和double是存储空间的区别,不是限制条件的区别)
//我们可以使用强制类型转化(char*)来将其转化为char*数据

strcpy (char dst, const char src)

cpp
//将后一个数组复制给前一个数组

atoi()

cpp
//将string已int的类型返回

pair<xxx,xxx>

c++
//创建pair类型,用于存放两个数据

//常用操作

1.定义

pair<T1, T2> p1;            //创建一个空的pair对象(使用默认构造),它的两个元素分别是T1和T2类型,采用值初始化。
pair<T1, T2> p1(v1, v2);    //创建一个pair对象,它的两个元素分别是T1和T2类型,其中first成员初始化为v1,second成员初始化为v2。
make_pair(v1, v2);          // 以v1和v2的值创建一个新的pair对象,其元素类型分别是v1和v2的类型。
p1 < p2;                    // 两个pair对象间的小于运算,其定义遵循字典次序:如 p1.first < p2.first 或者 !(p2.first < p1.first) && (p1.second < p2.second) 则返回true。
p1 == p2;                  // 如果两个对象的first和second依次相等,则这两个对象相等;该运算使用元素的==操作符。
p1.first;                   // 返回对象p1中名为first的公有数据成员
p1.second;                 // 返回对象p1中名为second的公有数据成员

2,pair的创建和初始化
pair包含两个数值,与容器一样,pair也是一种模板类型。但是又与之前介绍的容器不同;
在创建pair对象时,必须提供两个类型名,两个对应的类型名的类型不必相同
pair<string, string> anon;        // 创建一个空对象anon,两个元素类型都是string
pair<string, int> word_count;     // 创建一个空对象 word_count, 两个元素类型分别是string和int类型
pair<string, vector<int> > line;  // 创建一个空对象line,两个元素类型分别是string和vector类型

当然也可以在定义时进行成员初始化:
pair<string, string> author("James","Joy");    // 创建一个author对象,两个元素类型分别为string类型,并默认初始值为James和Joy。
pair<string, int> name_age("Tom", 18);
pair<string, int> name_age2(name_age);    // 拷贝构造初始化

pair类型的使用相当的繁琐,如果定义多个相同的pair类型对象,可以使用typedef简化声明:
typedef pair<string,string> Author;
Author proust("March","Proust");
Author Joy("James","Joy");

变量间赋值:
pair<int, double> p1(1, 1.2);
pair<int, double> p2 = p1;     // copy construction to initialize object

3,pair对象的操作

访问两个元素操作可以通过first和second访问:

pair<int ,double> p1;
 
p1.first = 1;
 
p1.second = 2.5;
 
cout<<p1.first<<' '<<p1.second<<endl;
 
//输出结果:1 2.5
 
 
string firstBook;
if(author.first=="James" && author.second=="Joy")
    firstBook="Stephen Hero";
4,生成新的pair对象

还可以利用make_pair创建新的pair对象:
 pair<int, double> p1;
 p1 = make_pair(1, 1.2);
 
cout << p1.first << p1.second << endl;
 
//output: 1 1.2
 
int a = 8;
 
string m = "James";
 
pair<int, string> newone;
 
newone = make_pair(a, m);
cout << newone.first << newone.second << endl;
 
//output: 8 James

二分查找及其对应库函数

c++
#include<algorithm>

binary_search(str,str+n,x);//三个参数,分别为数组头地址/起始迭代器,数组末尾地址的后一个地址/末尾迭代器,要查找的数。具有bool类型返回值,表示该数是否存在于该数组/容器中
lower_bound(str,str+n,x);//三个参数,分别为数组头地址/起始迭代器,数组末尾地址的后一个地址/末尾迭代器,要查找的数。具有int */迭代器类型返回值,表示该数在数组/容器中第一次出现的地址(若该数存在),或第一个大于该数的数的地址/迭代器(若该数不存在)
//该函数对应我们的查找左边界
upper_bound(str,str+n,x);//三个参数,分别为数组头地址/起始迭代器,数组末尾地址的后一个地址/末尾迭代器,要查找的数。具有int */迭代器类型返回值,表示第一个大于该数的数的地址/迭代器
//该函数对应我们的查找右边界
cpp
lower_bound(str,str+n,x,greater<int>());//通过重载,我们可以将原本的大于等于转换为小于等于

第一类用法:针对数组

c++
#include<iostream>
#include<algorithm> //二分查找函数存在于STL基本算法库中

using namespace std;

const int N=1e5+10;
int str[N];
int n,m;

int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++) cin>>str[i];
    while(m--){
        int x;
        cin>>x;
        bool flag=binary_search(str,str+n,x);  
        if(!flag) cout<<"Not have"<<endl;
        else{
            int left=lower_bound(str,str+n,x)-str;  //此处若我们想要返回下标,只需要在返回值的基础上减去头地址的值即可(注意,这样的下标是从0开始的)
            int right= upper_bound(str,str+n,x)-str-1;//此处由于我们想要最后一个要找的数(x)出现的位置,而我们的upper_bound查找的是第一个大于x的数的地址,所以我们在减去头地址的基础上还需额外-1;
            cout<<left<<' '<<right<<endl;
        }
    }
}

第二类用法:针对vector

c++
#include<iostream>
#include<algorithm> //二分查找函数存在于STL基本算法库中

using namespace std;

vector<int> str;
int n,m;

int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++) {
        int x;
        cin>>x;
        str.push_back(x);
    }
    while(m--){
        int x;
        cin>>x;
        bool flag=binary_search(str,str+n,x);  
        if(!flag) cout<<"Not have"<<endl;
        else{
            int left=lower_bound(str.begin(),str.end,x)-str.begin();  //此处若我们想要返回下标,只需要在返回值的基础上减去起始迭代器的值即可(注意,这样的下标是从0开始的)
//在减去起始迭代器的值后,我们就可以将原本的返回值隐式类型转为int类型,对应的就是我们所要的下标
            int right= upper_bound(str.begin(),str.end,x)-str.begin()-1;//此处由于我们想要最后一个要找的数(x)出现的位置,而我们的upper_bound查找的是第一个大于x的数的地址,所以我们在减去起始迭代器的基础上还需额外-1;
            cout<<left<<' '<<right<<endl;
        }
    }
}

补充,如果不减去起始迭代器的情况下,我们无法用int来进行接收(因为返回的是迭代器),若要接收,需要使用auto或是vector<int>::iterator类型来进行接收,其效果类似于地址,用*任然表示该迭代器位置上存放的值
本站访客数 人次      本站总访问量