STL(常用)
STL
- 簡單記錄、講解一些初級階段常用的用法。
STL是C++的一個標準模板庫,其中包含了許多在計算機領域常用的基本資料結構以及基本演算法。STL主要依賴於模板,使得STL具有廣泛的通用性。這篇文章旨在介紹一些常用的STL工具及其用法。
Algorithm
- 該標頭檔案涉及許多常用的功能,例如比較、交換、查詢、遍歷、絕對值、複製、修改、反轉、排序等。
具體用法
/** 稍微列舉部分可能用到的 **/ #include <iostream> #include <algorithm> #include <cstdio> using namespace std; int main () { //排序 int a[5] = {5, 1, 2, 3,7}; sort (a, a+5); // stable_sort (a, a+5); for (int i = 0; i < 5; i++) cout << a[i] << " "; cout << endl; // 反轉 reverse(a, a+5); for (int i = 0; i < 5; i++) cout << a[i] << " "; cout << endl; // 絕對值 cout << abs(-5) << endl; // 最大值最小值 cout << max(5, 3) << " " << min(5, 3) << endl; // 交換 int x = 1, y = 2; swap (x, y); cout << x << " " << y << endl; // 賦值函式fill int b[4] = {1, 2, 3, 4}; fill (b, b+4, -1); for (int i = 0; i < 4; i ++) cout << b[i] << " "; cout << endl; //求全排列的下一個順序, next_permutation若有下一個全排列返回true沒有則返回false char str[3] = {'a', 'b', 'c'}; do { cout << str << endl; }while (next_permutation(str, str+3)); //..... return 0; }
Container
vector
vector這個容器實際上是加強版的陣列。陣列在定義的時候長度就被確定下來了,但是vector容器隨著新增的資料量增加,它的長度也會隨之增加。容器可以存個種類型的資料。
使用時包含標頭檔案#include
初始化(常用)
vector<int> vec; // 整型 vector<char> vec1; // 字元型 int b[4] = {1, 2, 3, 4}; vector<int> a(b, b+4); // 用陣列賦值 vector<int> c(10); // 10個長度的整型 vector<int> c1(10, 1); // 10個長度的整型,且每個元素為1 vector<int> c2(c) // 用c賦值建立c2
常用函式方法
方法 | 作用 |
---|---|
vec.push_back() |
在vector末尾新增一個元素 |
vec.begin() vec.end() |
返回vector首尾迭代器 |
vec.front() vec.back() |
返回vector首尾元素 |
vec.size() |
返回vector中元素的個數 |
vec.pop_back() |
刪除vector最後一個元素 |
vec.capacity() |
返回記憶體中總共容納的元素個數 |
vec.empty() |
返回1表示空,0表示不為空 |
vec.clear() |
清空vector |
vector容器也可通過[]方式來訪問,第一個下標和陣列相同是0,例如vec[0]。
stack
stack翻譯過來是棧的意思,是一種基礎的資料結構。它的特點是先進後出,棧中可以存放各種資料型別,也包括自定義的資料型別。
宣告:#include <stack>
使用棧,需要知道一個幾個概念
- 棧頂:棧頂部的元素(進出棧都必須經過棧頂)
- 進棧:進入棧中(壓棧)
- 出棧:從棧中出去(彈棧)
初始化(常用)
stack<int> s;
stack<char> t;
struct node {
...
};
stack<node> n;
常用函式方法
方法 | 作用 |
---|---|
s.top() |
返回棧頂元素 |
s.empty() |
判斷為空返回1,否則0 |
s.size() |
返回棧中元素個數 |
s.push() |
壓棧 |
s.pop() |
彈棧 |
queue
queue表示佇列,是一種基本資料結構。特點是先進先出,想象成排隊買票的過程,先排隊的先買票,後排隊的後買票。
宣告:#include <queue>
初始化(常用)
queue<int> s;
queue<char> t;
struct node {
...
};
queue<node> n;
常用函式方法
方法 | 作用 |
---|---|
q.front() q.back() |
返回隊首、隊尾元素 |
q.empty() |
判斷為空返回1,否則0 |
q.size() |
返回佇列長度 |
q.push() |
從隊尾新增一個元素 |
q.pop() |
從隊首刪除一個元素 |
清空佇列只能一個一個彈出。另外,佇列是不能隨機訪問的。
priority_queue
priority_queue也是佇列的一種,是優先佇列。普通的佇列是一種先進先出的資料結構,但是優先佇列中的元素被賦予了優先順序,優先順序高的元素排在佇列前,優先出佇列。優先順序的規則可以由自定義。
優先佇列具有所有佇列的基本操作,本質上是一個堆。預設是大頂堆,降序序列。
宣告:
#include <queue>
初始化(常用)
priority_queue <int> q; // 預設從大到小
struct node {
...
};
priority_queue <node> q1;
priority_queue <int, vector<int>, greater<int> > t; // 小頂堆,從小到大
常用函式方法
方法 | 作用 |
---|---|
q.empty() |
判斷為空返回1,否則0 |
q.size() |
返回佇列長度 |
q.push() |
從隊尾新增一個元素 |
q.pop() |
從隊首刪除一個元素 |
q.top() |
訪問隊首元素 |
自定義優先順序
需要注意的是,優先佇列模板中帶3個引數,priority_queue<Type, Container, Functional>。Type表示資料型別,Container表示儲存資料的容器,Functional為元素的比較方式。後兩個引數可以不寫,Container預設是Vector,比較方式預設的是operator <,即大頂堆,降序。
對於自定義的資料結構,需要自定義排序規則,那麼就需要重寫operator<。
struct node {
int x, y;
node (int x1, int y1):x(x1), y(y1) {}
};
// 小頂堆
bool operator < (node a, node b) {
if (a.x == b.x) return a.y > b.y; // x相等,按照y從小到大升序
return a.x > b.x; // x大的優先順序低,按照x從小到大升序
}
//大頂堆
bool operator < (node a, node b) {
if (a.x == b.x) return a.y < b.y; // x相等,按照y從大到小升序
return a.x < b.x; // x小的優先順序低,按照x從大到小升序
}
//小頂堆,寫在結構體內部
struct node {
int x, y;
node (int x1, int y1):x(x1), y(y1) {}
bool operator < (const node &a) const { //小頂堆,按照x升序
if (x == a.x) return y > a.y;
return x > a.x;
}
};
priority_queue <node> q;
也可以自定義比較函式cmp,作為第3個引數,此時容器引數不能省略
struct node {
int x, y;
node (int x1, int y1):x(x1), y(y1) {}
};
struct cmp {
bool operator() (node a, node b) {
if (a.x == b.x) return a.y > b.y;
return a.x > b.x;
}
};
priority_queue <node, vector<node>, cmp > q;
deque
deque是一種雙端佇列,普通的佇列是先進先出,而雙端佇列既可以從隊首進出,也可以從隊尾進出。
而deque和queue不同的地方在於,可以通過下標訪問其中的元素,也就是支援隨機訪問。
初始化(常用)
#include <queue>
struct node {
...
};
deque<int> a;
deque<node> b;
常用函式方法
方法 | 作用 |
---|---|
q.push_front() q.push_back() |
在隊首、隊尾插入元素 |
q.front() q.back() |
獲取隊首、隊尾元素 |
q.pop_front() q.pop_back() |
隊首、隊尾出隊一個元素 |
q.begin() q.end() |
返回隊首、隊尾的迭代器 |
q.clear() |
清空佇列 |
set
set可以理解成一個集合,這個集合的特點就是其中的元素無重複。假定集合中已有一個元素,那麼新增相同的元素進去是無效的,還是隻有那一個唯一的元素。同時set中的元素是預設升序的。(紅黑樹實現)
初始化(常用)
#include <set>
queue<int> s;
queue<char> t;
struct node {
...
};
queue<node> n;
常用函式方法
方法 | 作用 |
---|---|
s.begin() s.end() |
返回集合首尾迭代器 |
s.insert(k) |
集合中插入元素k |
s.erase(k) |
集合中刪除元素k |
s.size() |
返回集合元素個數 |
s.empty() |
判斷集合是否為空 |
s.clear() |
清空集合 |
map
map是一種關聯容器,提供資料一種一對一的對映關係(每一個元素都有一個唯一的關鍵字,這個關鍵字對應一個鍵值)。map也是紅黑樹實現的,它的好處在於可以快速方便的增加、刪除、查詢、遍歷等。
初始化(常用)
map <int, char> m;
m.insert(pair<int, char>(65, 'A'));
m.insert(map<int, char>::value_type (66, 'B'));
m[67] = 'C';
使用insert方法插入時,會保證key(map中的第一個引數)的唯一性,有相同的key值插入是不會成功的。
但是m[67] = 'C',這種方式會直接造成覆蓋。
常用函式方法
方法 | 作用 |
---|---|
m.begin() m.end() |
返回第一個和最後一個迭代器位置 |
m.insert(map<Type, Type>::value_type()) |
插入元素,包含關鍵字和對應值 |
m.count(k) |
檢視關鍵字為k的元素個數(map特性,只能為0或者1) |
m.find(k) |
查關鍵字為k元素,有返回迭代器位置沒有返回end位置 |
m.erase() |
可根據關鍵字、迭代器刪除(也可成片刪除) |
m.lower_bound() m.upper_bound() |
返回鍵值>=、<=給定元素的第一個迭代器位置 |
m.size() |
返回map中元素個數 |
m.clear() |
刪除所有元素 |
Iterator
簡單來說,可以用於迭代遍歷STL中各種容器的資料型別。
類似於指標,可以指向要訪問的索引的值。
簡單用法
/**
遍歷set、map等
**/
#include <iostream>
#include <map>
#include <set>
#include <iterator>
using namespace std;
int main () {
map <int, char> m;
map <int, char>::iterator it;
m.insert(map<int, char>::value_type (66, 'B'));
m.insert(pair<int, char>(65, 'A'));
m[67] = 'C';
for (it = m.begin(); it != m.end(); it++)
cout << it->first << " " << it->second << endl;
cout << endl;
vector<int> v;
vector<int>::iterator it_v;
for (int i = 1; i <= 10; i++)
v.push_back(i);
for (it_v = v.begin(); it_v != v.end(); it_v++)
cout << *it_v << " ";
cout << endl;
set <int> s;
set <int>::iterator it_s;
for (int i = 1; i <= 10; i++)
s.insert(i);
for (it_s = s.begin(); it_s != s.end(); it_s++)
cout << *it_s << " ";
cout << endl;
return 0;
}
-------------------------------------
// 可以進行查詢等
#include <iostream>
#include <map>
using namespace std;
int main () {
map <int, char> m;
map <int, char>::iterator it;
m.insert(map<int, char>::value_type (66, 'B'));
m.insert(pair<int, char>(65, 'A'));
m[67] = 'C';
it = m.find(66);
if (it != m.end())
cout << it->first << " " << it->second;
return 0;
}