C++ STL总结 (带实例)文档 入门STL

C++ STL总结

主要通过实例来解释C++一些STL库的用法,也可以当作手册阅读。本文的样例代码默认使用std名称空间。会持续更新(有空就会加一些)

主要内容包括:string,stack,queue,list,vector,map,deque,set,pair的用法,和algorithm中的常用函数。

1. string

string 是C++用来高效处理字符串的类,封装了很多常用的字符串处理方法。下列样例str开头的变量都是string类,cstr表示C风格字符串.

#include 使用是要引入该库

1.1 string的构造

  1. string str; 构造空字符串
  2. string str = str_a/cstr; 通过直接赋值构造
  3. string str(str_a); 深拷贝一个字符串
  4. string str(cstr); 用c风格字符串给字符串初始化
  5. string str(cstr,num); 用c风格字符串的前num个字符给字符串初始化
  6. string str(str_a,index); 用字符串a从index位置开始(包括)的字符串来初始化
  7. string str(num,char); 用num个字符char拼接成一个字符串
string str_a = "this is a string"; 	  //this is a string
string str_b(str_a); 				//	this is a string
char cstr[20] = "this is a string";   //this is a string
string str_c(cstr);              //this is a string
string str_d(cstr,3);             //thi             
string str_e(str_a,3);            //s is a string   
string str_f(10,'#');             //##########      

1.2 string的长度

  1. size()/length():返回string对象的长度。切记length()不是length(python)
  2. max_size():返回string对象最多能接受的字符个数,超出会抛出length_error异常,不同环境下可能不一样
  3. capacity():重新分配内存之前,string对象能包含的最大字符个数。
string str_a = "12345";
string str_b = "";
cout << str_a.size() << endl;           // size=5
cout << str_a.length() << endl;         // length=5
cout << str_b.size() << endl;           // size=0
cout << str_b.max_size() << endl;       // max_size=9223372036854775807
cout << str_b.capacity() << endl;       // capacity=15

1.2 string的比较

  1. 比较操作符: >, >=, <, <=, ==, !=
    比较算法:对于两个字符串开始,从前往后遍历字符,对相同位置上的不同字符按照字典序比较得出大小。

  2. compare()方法
    支持多参数处理,支持用索引值和长度定位子串进行比较,前面减去后面的ASCII码,>0返回1,<0返回-1,相同返回0

    1. str1.compare(str2):两个完整长度的字符串比较。
    2. str1.compare(Off, N0, str2):str1[Off, Off + N0] 和str2比较
    3. _str1.compare(_Off, N0, str2, Roff, Count):str1[Off, Off + N0] 和str2[Roff, Roff+ Count]比较
    4. str1.compare(*Ptr):str1 和 Ptr指针到null处的字符串比较
    5. str1.compare(Off, N0, *Ptr, Count):str1 和 Ptr指针到Ptr+Count处的字符串比较
string str_a = "12345";
string str_b = "123456";
string str_c = "12346";
string str_d = "  123456";
string str_e = "  123466";
char cstr[20] = "  123456" ;
cout << (str_a > str_b)<< endl;           // 12345 > 123456 false
cout << (str_a > str_c)<< endl;           // 12345 > 12346  false
cout <<str_a.compare(str_a) << endl;      // 12345 cmp 12345 0
cout <<str_a.compare(str_b) << endl;      // 12345 cmp 123456 -1
cout <<str_d.compare(2,5,str_a) << endl;      // 12345 cmp 12345 0
cout <<str_d.compare(2,5,str_e,2,5) << endl;      // 12345 cmp 12346 -1
cout <<str_d.compare(2,5,cstr+2,5) << endl;     // 12345 cmp 12345 0

1.3 string的遍历

  • 迭代器 :
    • 正向迭代器:str.begin() str.end()
    • 反向迭代器: str.rbegin() str.rend()
  • 下标法:类C风格字符串处理方法
string str_a = "12345";
    
    string::iterator iter = str_a.begin();
    for(; iter!=str_a.end();iter++){
        cout<<*iter;
    } 
    cout<<endl; // 12345

    string::reverse_iterator iter2 = str_a.rbegin(); //注意这里用reverse_iterator
    for(; iter2!=str_a.rend();iter2++){
        cout<<*iter2;
    }
    cout<<endl; // 54321

    for(int i=0;i<str_a.size();i++){
        cout<<str_a[i];
    }
    cout<<endl;// 12345

1.4 string的内容处理(插入,拼接,删除,替换)

  1. 插入字符:
    • str.push_back(char) 尾插一个字符
    • str.insert(pos,char) 在特定位置插入一个字符
  2. 拼接字符串:append() 、 +
  3. 删除:
    1. 通过迭代器:
      1. erase(iterator p):删除字符串中p所指的字符
      2. erase(iterator first, iterator last):删除字符串中迭代器区间 [first, last] 上所有字符
    2. 通过位置和长度 erase(size_t pos, size_t len):删除字符串中从索引位置 pos 开始的 len 个字符
    3. 清空 clear()
  4. 替换:
    1. replace(size_t pos, size_t n, const char *s):将当前字符串从pos索引开始的n个字符,替换成字符串s
    2. replace(size_t pos, size_t n, size_t n1, char c):将当前字符串从pos索引开始的n个字符,替换成n1个字符c
    3. replace(iterator i1, iterator i2, const char* s):将当前字符串[i1,i2)区间中的字符串替换为字符串s
//插入
string str="12345";
str.push_back('6');
str.push_back('8');
cout<<str<<endl; // 1234568
str.insert(str.begin()+6,'7');
cout<<str<<endl; // 12345678

//拼接
//方法一:append()
string s1 = "abc";
s1.append("def");
cout<<s1<<endl; // abcdef
// 方法二:+ 操作符
string s2 = "abc";
string s3 = "def";
s2 += s3;
cout<<s2<<endl; // s2:abcdef


// 删除
string s1 = "123456789";
string s2 = "123456789";
string s3 = "123456789";
s1.erase(s1.begin() + 1);                 
s2.erase(s2.begin() + 1, s2.end() - 2);   
s3.erase(1,6);   
cout<<s1<<endl;             //  13456789                 
cout<<s2<<endl;             //  189           
cout<<s3<<endl;             //  189 


//替换
string s1("hello,world!"),s2("hello,world!"),s3("hello,world!");

s1.replace(6, 5, "girl");                       // 结果:hello,girl.
s2.replace(6, 5, 4, 'p');                       // 结果:hello,pppp!
s3.replace(s3.begin(), s3.begin() + 5, "boy");  // 结果:boy,girl.   
cout<<s1<<endl<<s2<<endl<<s3<<endl;



1.5 string的大小写转换

  1. tolower(char) 和 toupper(char) :逐一将字符进行大小写转换
  2. transform(),具体使用方法见代码
string s = "ABCDEFG";

for( int i = 0; i < s.size(); i++ )
{
    s[i] = tolower(s[i]);
} 
cout << s << endl;  //abcdefg

transform(s.begin(), s.end(), s.begin(), ::toupper); 
cout << s << endl;  //"ABCDEFG"
transform(s.begin(), s.end(), s.begin(), ::tolower); 
cout << s << endl;  //"abcdefg"

1.6 string的查找(前后空格处理小窍门)

  1. find (const char* s, size_t pos):在当前字符串的pos索引位置开始,查找子串s,返回找到的位置索引
  2. find (char c, size_t pos):在当前字符串的pos索引位置开始,查找字符c,返回找到的位置索引
  3. rfind (const char* s, size_t pos):在当前字符串的pos索引位置开始,反向查找子串s,返回找到的位置索引
  4. rfind (char c, size_t pos):在当前字符串的pos索引位置开始,反向查找字符c,返回找到的位置索引
  5. find_first_of (const char* s, size_t pos):在当前字符串的pos索引位置开始,查找子串s的字符,返回找到的位置索引
  6. find_first_not_of (const char* s, size_t pos):在当前字符串的pos索引位置开始,查找第一个不位于子串s的字符,返回找到的位置索引
  7. find_last_of(const char* s, size_t pos):在当前字符串的pos索引位置开始,向前查找第一个位于子串s的字符,返回找到的位置索引
  8. find_last_not_of (const char* s, size_t pos):在当前字符串的pos索引位置开始,向前查找第一个不位于子串s的字符,返回找到的位置索引
string s("this is a buct bird.");

//字符串查找-----找到后返回首字母在字符串中的下标
// 1. 查找一个字符串
cout << s.find("buct") << endl;        // 结果是:10
cout << int(s.find("ttt")) << endl;        // 结果是:-1
// 2. 从下标为6开始找字符'i',返回找到的第一个i的下标
cout << s.find('i', 6) << endl;            // 结果是:16

// 3. 从字符串的末尾开始查找字符串,返回的还是首字母在字符串中的下标
cout << s.rfind("buct") << endl;       // 结果是:10

// 4. 从字符串的末尾开始查找字符
cout << s.rfind('i') << endl;             // 结果是:16

// 5. 在该字符串中查找第一个属于字符串s的字符
cout << s.find_first_of("13br98") << endl;  // 结果是:10("b")

// 6. 在该字符串中查找第一个不属于字符串s的字符,先匹配dog,然后bird匹配不到,所以打印4
cout << s.find_first_not_of("hello dog 2006") << endl; // 结果是:0

// 7. 在该字符串从后往前查找第一个属于字符串s的字符
cout << s.find_last_of("13r98") << endl;               // 结果是:17

// 8. 在该字符串从后往前查找第一个不属于字符串s的字符,先匹配tac,然后空格匹配不到,所以打印21
cout << s.find_last_not_of("teac") << endl;            // 结果是:19


string a = "   this is yzzer ha!    ";

//去除前后空额
a.erase(0,a.find_first_not_of(' '));
a.erase(a.find_last_not_of(' ')+1);
cout<<a<<endl;                          //结果是: "this is yzzer ha!"

1.7 string的分割和截取

  • 截取字符串 substr(index,length) 从index索引开始,截取length长度的字符串
  • 按符号分割字符串,这个没有自带的API,但是可以自己实现这个API:
//分割字符串函数
vector<string> split(string target, string split_c = " "){//默认按空格来分割
    int index = 0;
    vector<string> split_list;
    while(index < target.size()){
        int split_pos = target.find_first_of(split_c, index);
        if(split_pos == -1){ //找不到分隔符
            break;
        }
        if(split_pos != index) //连续的分隔符
            split_list.push_back(target.substr(index,split_pos - index));
        index = split_pos + 1;
    }
    return split_list;
}


/截取字符串
string number = "0123456789";
cout<< number.substr(3,4) <<endl;           // 3456

//按符号分割
vector<string> v = split("hahahah,lalalala,yzzer buct",", ");
for(auto i:v){
    cout<<i<<endl;
}
/*
hahahah
lalalala        
yzzer
buct
*/
	

1.8 string的排序

使用algorithm 的sort API

sort(iterator_begin, iterator_end)

string number = "949164461891615161";
sort(number.begin(),number.end());
cout<<number<<endl;  //111111444566668999

number = "949164461891615161";
sort(number.begin(),number.begin()+5);  // 949164
cout<<number<<endl;  //146994461891615161

1.9 string和int之间的互相转换

  1. int 转 string 用to_string函数
  2. string 转 int
    1. 用atoi()+str.c_str() c_str方法会返回C风格字符串 atoi会将C风格字符串转换成int (推荐)
    2. sstream头文件的字符串流来读入一个整型
//int 转 string
int a = 123456;
string str_a = to_string(a);
cout<<str_a[0]<<endl;  //1


// string 转 int   1
string str_b = "-12345";
int b = atoi(str_b.c_str());
cout<<b<<endl; //-12345

// string 转 int   2
string str_c = "-13456";
istringstream is(str_c);
int c;
is>>c;
cout<<c<<endl;  //-13456

2. stack

栈是一个先进后出的受限的线性结构容器(FILO),提供的操作较少。

C++的stack容器是基于底层的容器实现的,底层的结构可以是vector,list,deque,默认是deque。

#include 使用时引入该库

2.1初始化

stack可以用其他容器初始化,但前提是底层容器和用于初始化的容器类型相同。

 stack<int> num_stack_defaut; //使用默认底层容器 一般来说够用了

    //list作为底层容器  
    list<int> mylist(3,123); // 从左到右123 123 123
    mylist.push_back(11);
    mylist.push_back(22);
    mylist.push_back(33); // mylist 从左到右 123 123 123 11 22 33
    stack<int,list<int>> num_stack_list(mylist); //只能使用list初始化
    // 从栈顶到栈尾 33 22 11 123 123 123

   //vector作为底层容器
    vector<int> myvector(3,123); // 从左到右123 123 123
    myvector.push_back(11);
    myvector.push_back(22);
    myvector.push_back(33); // mylist 从左到右 123 123 123 11 22 33
    stack<int,vector<int>> num_stack_vector(myvector); //只能使用vector初始化
    // 从栈顶到栈尾 33 22 11 123 123 123

2.2 堆栈操作

  • top():返回一个栈顶元素的引用,类型为 T&。如果栈为空,返回值未定义。
  • push(const T& obj):可以将对象副本压入栈顶。这是通过调用底层容器的 push_back() 函数完成的。
  • pop():弹出栈顶元素。
  • size():返回栈中元素的个数。
  • empty():在栈中没有元素的情况下返回 true。
  • swap(stack & other_stack):将当前栈中的元素和参数中的元素交换。参数所包含元素的类型必须和当前栈的相同。对于 stack 对象有一个特例化的全局函数 swap() 可以使用。

一般来说最后一个不常用。

// 用模板语法实现的打印栈 (从栈顶到栈底)
void print_stack(stack<T,container> ss){
    cout<<"(size:"<<ss.size()<<')';  //获取栈有多少元素
    while(!ss.empty()){ //判断栈是否为空
        cout<<ss.top()<<' '; //获取栈顶元素
        ss.pop(); //弹出栈顶元素
    }
    cout<<endl;
}


stack<int> num_stack;
num_stack.push(1);// 入栈
num_stack.push(2);// 2会在1之上
num_stack.push(3);
num_stack.push(4);
print_stack(num_stack); //  (size:4)4 3 2 1 


stack<int> num_stack2;
num_stack2.push(4);
num_stack2.push(5);
num_stack2.push(6);
print_stack(num_stack2); //  (size:3)6 5 4

//交换两个栈 必须两个栈的底层容器相同
num_stack.swap(num_stack2);
print_stack(num_stack); // (size:3)6 5 4  
print_stack(num_stack2); //  (size:4)4 3 2 1

3. queue

队列是满足FIFO的线性结构。STL的queue模板提供了两个模块 queue循环队列和priority_queue优先队列/堆

#include 使用时引入

3.1 queue 的方法

  • front():返回 queue 中第一个元素的引用。如果 queue 是常量,就返回一个常引用;如果 queue为空,返回值是未定义的。
  • back():返回 queue 中最后一个元素的引用。如果 queue 是常量,就返回一个常引用;如果 queue为空,返回值是未定义的。
  • push(T& obj):在 queue 的尾部添加一个元素的副本。这是通过调用底层容器的成员函数 push_back()来完成的。
  • pop():删除 queue 中的第一个元素。
  • size():返回 queue 中元素的个数。
  • empty():判断队列中是否有元素,无元素返回 true。
  • emplace():用传给 emplace() 的参数调用 T 的构造函数,在 queue 的尾部生成对象。
  • swap(queue &other_q):将当前 queue 中的元素和参数 queue 中的元素交换。它们需要包含相同类型的元素。也可以调用全局函数模板 swap() 来完成同样的操作。
queue numQueue; // 声明
for(int i=0;i<5;i++){
    numQueue.push(i);
    cout<

3.2 priority_queue

类的方法和queue大部分一致,区别是声明和使用时的注意.

  • top():返回 堆顶元素。堆queue为空,返回值是未定义的。
  • push(T& obj):在 堆中添加一个元素的副本,堆会自动调整。
  • pop():删除 堆顶元素。
  • size():返回 堆中元素的个数。
  • empty():判断堆中是否有元素,无元素返回 true。
struct number{
    int num;
    number(int n=0){
        num = n;
    }

    // 小根堆重载<
    bool operator<(const number &a)const{
        return num  < a.num;
    }
    //大根堆重载>
    bool operator>(const number &a)const{
        return num  > a.num;
    }
};
priority_queue<number> q1;                          //大根堆(堆顶值最大)
priority_queue<number,vector<number>,greater<number> > q2;//  小根堆(堆顶值最小)


for(int i=0;i<10;i++){
    srand(i);
    q1.push(number(rand()));
    q2.push(number(rand()));
} 



cout<<"size:"<<q1.size()<<endl;
//size:10

while(!q1.empty()){
    cout<<q1.top().num<<' ';
    q1.pop();
}
cout<<endl;
// 68 64 61 58 54 51 48 45 41 38
// 降序输出,每次取出的是最大值

while(!q2.empty()){
    cout<<q2.top().num<<' ';
    q2.pop();
}
cout<<endl;
// 6151 6673 7196 7719 17422 17945 18467 28170 28693 29216
// 升序输出  每次取出的是最小值

你可能感兴趣的:(c++,stl)