C++算法设计工具STL


算法设计工具STL

STL概述

STL组成成分

STL主要由

  • container -容器
  • algorithm - 算法
  • iterator - 迭代器

三大件组成

什么是STL容器

简单说STL容器就是一种数据结构

注意:
C++引入了命名空间概念,在不同命名空间中可以存在相同名字的标识符。
using namespace std;
  • 常用的数据结构和相应头文件
数据结构 说明 头文件
vector 底层是数组,支持随机访问 <vector>
string 字符处理容器 <string>
deque 双端队列 <deque>
list 链表,底层为双向链表 <list>
stack <stack>
queue 队列 <queue>
priority-queue 优先队列 <queue>
set/multiset 结点组成的红黑树 <set>
map/mutimap key-value结构,底层红黑树 <map>

什么是STL算法

STL算法是用来操作容器中数据的模板函数,大概100个算法模板函数

void testSort(){
    int a[]={2,5,4,1,3};
    sort(a,a+5);
    printArray(a,5);
}

什么是STL迭代器

简单地说,STL迭代器用于访问容器中数据对象。

常用迭代器

  • iterator - 指向容器中存放元素的迭代器,用于正向遍历容器中的元素
  • const_iterator - 指向容器中存放元素的常量迭代器,只能读取容器11中的元素
  • reverse_iterator - 指向容器中存放元素的反响迭代器,用于反向遍历容器中的元素
  • const_reverse_iterator - 常量反向迭代器

迭代器常用操作:

  • ++ 正向移动迭代器
  • – 反向移动迭代器
  • * 返回迭代器值
void testFrontIterator(){ 
    vector<int> myv; 
    myv.push_back(1); 
    myv.push_back(2); 
    myv.push_back(3); 
    vector<int>::iterator it; 
    for(it=myv.begin();it!=myv.end();++it){ 
        cout<<*it<<endl; 
        } 
    } 
    void testBackIterator(){ 
        vector<int> myv; 
        myv.push_back(1); 
        myv.push_back(2); 
        myv.push_back(3); 
        ector<int>::reverse_iterator rit; 
        for(rit=myv.rbegin();rit!=myv.rend();++rit){ 
            cout<<*rit<<endl; 
            } 
        }

常用的STL容器

顺序容器

vector 向量容器

它是一个向量类模版。向量容器相当于数组,操作起来和数组的优缺点一样

定义方式

vector<int> v1; // 定义元素为int的向量v1
v1 vector<int> v2(10); // 指向向量v2的初始大小为10个int元素 
vector<double> v3(10,1.23); // 指向v3的10个初始元素的初值为1.23
vector<int> v4(a,a+5); // 用数组a 0~4共5个元素初始化v4

vector提供了一系列的成员函数

- empty()                判断当前向量是否为空
- size()                 返回当前容量中实际元素个数
- []                     返回指定下标元素
- reserve(n)             为当前向量容器预分配n个元素的存储空间 
- capacity()             返回当前向量容器在重新进行内存分配以前所能容纳的个数 
- resize(n)              调整当前容量容器大小,使其能容纳n个元素 
- push_back()            在当前向量容器尾部添加一个元素
- insert(pos,elem)       在pos位置插入元素elem,即将元素elem插入迭代器pos指向位置之前 
- front()                获取当前向量容器的第一个元素 
- back()                 获取当前向量容器的最后一个元素 
- erase()                删除当前向量向量容器中某个迭代器或者迭代器区间指定的元素
- clear()                删除当前想向量容器中的所有元素 
- begin()                该函数的两个版本返回iterator或const_iterator,引用容器第一个元素 
- end()                  该函数的两个版本返回... ,引用容器的最后一个位置 
- rbegin()               该函数的两个版本返回reverse_iterator或const_reverse_iterator,引用容器的最后一个元素 
- rend()                 与rbegin反过来

关于size和capacity区别

#include <iostream> 
#include <vector> 

using std::vector; 
int main(void) 
{ 
    vector<int> v; 
    std::cout<<"v.size() == " << v.size() << " v.capacity() = " << v.capacity() << std::endl; 
    v.reserve(10); 
    std::cout<<"v.size() == " << v.size() << " v.capacity() = " << v.capacity() << std::endl; v.resize(10); 
    v.push_back(0); 
    std::cout<<"v.size() == " << v.size() << " v.capacity() = " << v.capacity() << std::endl; 

    return 0; 
}

执行结果

string

string是一个保存字符序列的容器,类似于vector

定义方式

char cstr[]="China!Greate Wall"; // 字符串
string s1(cstr); // s1 "China! Greate Wall" 
string s2(s1); // s2 "China! Greate Wall" 
string s3(cstr,7,11); // s3 "Greate Wall" 
string s4(cstr,6); // 
s4 "China" string s5(5,'A'); // s5 "AAAAA"

操作方式

empty()                                                     判断当前字符串是否为空串 
size()                                                      返回当前字符串实际字符个数(返回结果为size_type类型) 
length()                                                    返回当前字符串实际字符个数 
[idx]                                                       返回当前字符串位于idx位置的字符,idx从0开始 
at(idx)                                                     返回当前字符串位于idx位置的字符 
compare(const string& str)                                  返回当前字符串与字符串str的比较结果。相等是0,前者小于后者返回-1,否则返回1 
append(cstr)                                                在当前字符串的末尾添加一个字符串str 
insert(size_type idx,const string& str)                     在当前字符串的idx处插入一个字符串str 
find(string& s,size_type pos)                               从当前字符串中的pos位置开始查找字符串s的第一个位置,找到返回其位置,若没有找到返回-1 
replace(size_type idx,size_type len,const string& str)      将当前字符串中起始于idx的len个字符用一个字符串str替换 
substr(size_type idx)                                       返回当前字符串起始于idx的子串 
substr(size_type idx,size_type len)                         返回当前字符串起始于idx的长度为len的子串 
clear()                                                     删除当前字符串中的所有字符 
erase()                                                     删除当前字符串中的所有字符 
erase(size_type idx)                                        删除当前字符串换从idx开始的所有字符 
erase(size_type idx,size_type len)                          删除当前字符串从idx开始的len个字符

实例

void testString2()
{ 
    string s1="",s2,s3="Bye"; 
    s1.append("Good morning"); 
    s2=s1; int i=s2.find("morning"); 
    s2.replace(i,s2.length()-i,s3); // 相当于s2.replace(5,7,s3);
    cout<<"s1:"<<s1<<endl; 
    cout<<"s2:"<<s2<<endl; 
}
deque 双端队列容器

双端队列容器由若干个块构成,每个块中元素的地址是连续的,块之间的地址是不连续的

定义方式

deque<int> dq1; // 指定元素为int的双端队列dq1 
deque<int> dq2(10); // 指定dq2的初始大小为10个int元素 
deque<double> dq3(10,1.23); // 指定dq3的10个初始元素为1.23 
deque<int> dq4(dq2.begin(),dq2.end()); // 用dq2的所有元素初始化dq4

主要函数

empty() 
size() 
front() 
back() 
push_front(elem) 
push_back(elem) 
pop_front() 
pop_back() 
erase() 
clear() 
begin() 
end() 
rbegin() 
rend()

实例

void disp(deque<int> &dq){ 
    deque<int>::iterator iter; 
    for(iter=dq.begin();iter!=dq.end();iter++)
    { 
        cout<<*iter<<" "; 
    } 
     cout<<endl; 
     } 
void testDeque(){ 
    deque<int> dq; 
    dq.push_front(1); 
    dq.push_back(2); 
    dq.push_front(3); 
    dq.push_back(4); 
    cout<<"dq:"; 
    disp(dq); 
    dq.pop_front(); 
    dq.pop_back(); 
    disp(dq); 
    }
list 链表

实际是一个双向链表

定义方式

list<int> l1; // 定义元素为int的链表l1
list<int> l2(10); // 指定链表l2的初始大小为10个int 元素 
list<double> l3(10,1.23); // 指定l3的10个初始大小的初值1.23 
list<int> l4(a,a+5); // 用数组a[0..4]共5个元素初始化14

主要操作

empty() 
size() 
push_back() 
pop_back() 
remove() 
remove_if(cmp) 
erase() 
unique() 
clear() 
insert(pos,elem) 
insert(pos,n,elem) 
insert(pos,pos1,pos2) 
reverse() 
sort() 
begin() 
end() 
rbegin() 
rend()

示例

void disp_list(list<int> &lst){ 
    list<int>::iterator it; 
    for(it=lst.begin();it!=lst.end();it++){ 
        cout<<*it<<" ";
    } 
        cout<<endl; 
} 
void testList(){ 
    list<int> lst; 
    list<int>::iterator it,start,end,temp; 
    lst.push_back(5); 
    lst.push_back(2); 
    lst.push_back(4); 
    lst.push_back(1); 
    lst.push_back(3); 
    cout<<"初始lst"<<endl; disp_list(lst); 
    it=lst.begin(); start=++lst.begin(); 
    end=--lst.end(); temp=lst.end(); // lst.end(); 在最后位置+1
    lst.insert(it,start,end); // start在2的位置,end在3的位置,it在5的位置
    cout<<"执行后lst.insert(it,start,end);"<<endl;
    disp_list(lst); // 显示将 2 4 1 插入到5前边
}

关联容器

关联容器中的每个元素都有一个key(关键字),通过key来存储和读取元素,这些关键字可能与元素所在容器的位置无关,所以关联容器不提供顺序容器中的front()、push_front()、back()、push_back()、以及pop_back()等操作

set/multiset 集合容器/多重集合容器
map/multimap 映射容器/多重映射容器

适配器容器

stack 栈容器

默认底层是deque,用户也可以指定其他底层容器

定义

stack<string,vector<string>> myst;  // 第二个参数指定底层容器为vector

操作

栈只有一个出口,所以没有迭代器操作

empty()
size()
push(elem)
top()
pop()

例子

void testStack(){ 
    stack<int> st; 
    st.push(1); 
    st.push(2); 
    st.push(3); cout<<"栈顶元素:"<<st.top()<<endl; 
    cout<<"出栈顺序";
    while(!st.empty()){ 
        cout<<st.top()<<" "; 
        st.pop(); 
    } 
    cout<<endl; 
}
queue 队列容器

定义与stack相似

queue容器不允许顺序遍历,没有迭代器操作

操作

empty()
size()
front()
back()
push(elem)
pop()

例子

void testQueue(){ 
    queue<int> qu; 
    qu.push(1); 
    qu.push(2); 
    qu.push(3); 
    cout<<"队头元素:"<<qu.front()<<endl; 
    cout<<"队尾元素:"<<qu.back()<<endl; 
    cout<<"出队元素"; 
    while(!qu.empty()){ 
        cout<<qu.front()<<" "; 
        qu.pop(); 
    } 
    cout<<endl; 
}
priority_queue 优先队列

内置函数,需要重新定义优先运算符

总结

  • STL
    • STL概述 - 三大件 容器 算法 迭代器
      • 什么是STL容器
      • 什么是STL算法
      • 什么是STL迭代器
    • 常用STL容器
      • ˳顺序容器
        • vector !
        • string !
        • deque !
        • list !
      • 关联容器
        • set
        • map
      • 适配器容器
        • stack !
        • queue !
        • priority_queue

文章作者: Jelly
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Jelly !
  目录