您的位置:首页 > 编程语言 > C语言/C++

STL + c++ + 模板 + 重要思维 + 基础算法+ 经典算法 + 经典实例 + 编程总结+ 心得+ 入门必会 + 知识点汇总。

2018-03-15 14:28 1206 查看
              STL及经典实例
STL简介:
    接下来我们主要从顺序性容器,关联容器,容器适配器,迭代器,算法等进行展开。

顺序性容器:

一:vector
1.vector是一个可变长数组,也就是长度不固定。
2.vector:将元素置于一个动态数组中加以管理,可以随机存取
元素(用索引直接存取)(与数组功能差不多).在尾部插入和删
除元素很容易实现(push_back( )和pop_back( ) ).但是在中部或
者头部安插元素比较费时;
3.具体代码:1)定义:
vector<int> vec1;
vector<elem> vec2;
2)操作
vec1.push_back(data);
vec1.pop_back();
if(vec1.size()!=0)//返回当前vec1中元素个数(不是容量喔)
vec1.clear();
这几个基本操作是最重要的,要十分熟练的掌握
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int> vec1;
for(int i=0;i<5;i++)
{
vec1.push_back(i);
}
while(!vec1.empty())
{
int temp;
temp=vec1[vec1.size()-1];
cout<<temp<<endl;
vec1.pop_back();
}
return 0;
}
可以看出vec1.empty()的作用很大,我们可以使用while(!vec1.empty())进行vec1的遍历。也还有几个操作需要掌握一些,但是这几个操作可以用其他操作
或者代码来实现。(掌握最好)
对vector越熟练,操作越多,以后我们就能摆脱数组,使用
vector,从而让自己思路更加广。vec1.front() :返回第一个元素的引用
vec.back(); 返回最末一个元素。
swap() 交换两个vector;
直接就是swap(vec1,vec2); //像数组一样能够利用swap,这样就很牛逼了。还有很重要的一点;那就是对vector的遍历为了成功实现遍历,我们先需要明确几个概念:

vec.begin():返回vec的首部的迭代器,(即是遍历vec时访问的起点)

vec.end(): 返回vector尾部的迭代器(即遍历时的终点)

迭代器可以理解为指针,定义形式为vector<elemtype>::iterator it;

迭代器只能进行++操作。像--或者+3操作都是不允许的。

#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int> vec1,vec2;
vector <int>::iterator it;
for(int i=0;i<5;i++)
{
vec1.push_back(i);
}
for(it=vec1.begin();it<vec1.end();it++)
{
cout<<*it<<endl;
//上面也有提到,it是迭代器,可以理解为指针,所以输出时,前面要加一个*,表示不是地址了,而是数据了。
}
return 0;
}
//上面只是说明使用迭代器能完成遍历,但是我们最后使用通俗易用的遍历方法://下面就是for加i来完成遍历。
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int> vec1,vec2;
for(int i=0;i<5;i++)
{
vec1.push_back(i);

for(int i=0;i<vec1.size();i++)//充分说明vec.size()的重要性。类似size()的有max_size():表示能容纳元素的最大数量
{
cout<<vec1[i]<<endl;
}
return 0;

}
//要尽快熟练vector,进行思维转变。关于删除和插入我们也有对应的操作(这里一带而过,但是要掌握,因为在后面deque时我们进行了详细的介绍和实例说明)vec1.insert(pos,num)在pos处插入元素num;

vec1.insert(pos,n,num)在pos处插入n个元素num;

vec1.insert(pos,beg,end)插入区间为[beg,end]的元素;

vec1.erase(pos);删除位置为pos处的元素。

vec1.erase(beg,end)删除区间[beg,end]处的元素。sort(vector1.begin(),vector1.end())进行排序

二:dequeue

1.可以随机存取(用索引直接存取),双向队列的头部和尾部添
加或者移除元素都十分快速,但是在中部安插元素比较费时;
2.与vector类似,支持随机访问和快速插入删除,但是deque还
支持从开始端插入数据(push_front() );
3.具体代码上的使用。定义:

deque<int> q1;

deque<elemtype> q2;

基本操作:

q1.empty() 判断是否为空;

q1.front()

q1.back()

q.size()

q.max_size()

q.clear()

q.push_back()

q.pop_back()

q.push_front()

q.pop_front()

//这些是必须熟练掌握的基本操作写一个完整程序验证上述基本操作:#include<bits/stdc++.h>
using namespace std;
int main()
{
deque<int> q1;
int i;
for(i=0;i<7;i++)
{
q1.push_back(i+1);
}
int len=q1.size();
/* for(i=0;i<len;i++)
{
// cout<<q1[i]<<endl;
int temp;
temp=q1.front();
q1.pop_front();
cout<<temp<<endl; //进行头部删除和取出测试
} */
q1.clear();//清空作用
cout<<q1.size()<<endl;
return 0;
}
关于插入元素:q1.insert(pos,num)在pos处插入元素num;

q1.insert(pos,n,num)在pos处插入n个元素num;

q1.insert(pos,beg,end)插入区间为[beg,end]的元素;

**十分重要的要注意,pos代表是位置,对应相当于迭代器类型,所以pos一般是q1.be
4000
gin(),q1.end(),it,或者it++再it++后的it.
不能是所谓的i,n,或者长度等的。
具体实现过程为:
#include<bits/stdc++.h>
using namespace std;
int main()
{
deque<int> q1;
for(int i=1;i<5;i++)
q1.push_back(i);
deque<int>::iterator it;
cout << "insert before:" ;
for(it=q1.begin();it!=q1.end();it++){
cout << *it << " ";     }
cout << enq1l;
q1.insert(q1.end(),22);
it=q1.begin();
it++;
it++;
q1.insert(it,33);
q1.insert(q1.end(), 3,88);
int a[5] = {1,2,3,4,5};
q1.insert(q1.begin(),a,a+3);//在q1.begin()位置插入区间(a,a+3)这部分元素。
cout << "insert after:" ;
/* for(it=q1.begin();it!=q1.end();it++){
cout << *it << " ";
}   */
for(int i=0;i<q1.size();i++)
cout<<q1[i]<<" ";
cout << endl;
return 0;
}
同理,关于删除元素:

q1.erase(pos);删除位置为pos处的元素。

q1.erase(beg,end)删除区间[beg,end]处的元素。
具体实现过程为:#include<bits/stdc++.h>
using namespace std;
int main()
{
deque<int> q1;
for(int i=1;i<5;i++)
q1.push_back(i);
deque<int>::iterator it;
cout << "insert before:" ;
for(it=q1.begin();it!=q1.end();it++)
cout << *it << " ";
cout << endl;
it=q1.begin();
it++;
it++;
q1.erase(q1.begin(),it);
for(it=q1.begin();it!=q1.end();it++)
cout << *it << " ";
cout << endl;
return 0;
}

排序:deque同样适用sort(deque1.begin(),deque1.end() );进行排


三:list
可以参考博客点击打开链接
(http://blog.csdn.net/xiaoquantouer/article/details/703398
69)
1.双向链表,不提供随机存取(需要按顺序找到需要存取的元
素),在任何位置执行插入或者删除动作都十分迅速。(内部只
需调整一下指针);
2.线性表结构,它的数据由若干个节点构成,每一个节点都包括
一个信息块(即实际存储的数据)和一个前驱指针和一个后继指
针。
3.具体代码上的使用。

定义://以下这些都是比较基础的,经常使用的,要熟练掌握
(但是前面的vector和deque我们已经进行详细介绍,这里我们就不再赘述了)
list<int> list1

list<elemtype>list2
操作:

list1.begin()

list1.end();

list1.front()

list1.back()

list1.empty()

list1.size()

list1.max_size()

list1.clear()

list1.push_back(num)

list1.pop_back()

list1.pop_front()

list1.pop_back()

list1.swap()

swap(list1,list2);
//这些都是很重要的喔。要加强记忆。

c.insert(pos,num)      在pos位置插入元素num。

c.insert(pos,n,num)      在pos位置插入n个元素num。

c.insert(pos,beg,end)      在pos位置插入区间为[beg,end)的元素。

c.erase(pos)    删除pos位置的元素

//这几个vector和deque也进行实例解释了,这里自己进行记忆
接下来还的介绍几个不熟悉但是十分有帮助的基本操作使用:
A.MERGE  B.SPLICE  C.REVERSE   D.ERASE  E.SORT 
F.REMOVE  G.INSERT   H.UNIQUE
A.关于merge的用法
list1.merge(list2)//合并两个链表,并使之有序
1)默认为升序,但是在使用merge之前我们需要先使用
list1.sort()和list2.sort()对两个list进行升序排列。然后使用
merge后会进行一次大的排序(按所有参与进来的再进行一次排
序) list1.sort( );
list2.sort( );

list1.merge(list2);
**在这里我们要注意一点,对list进行升序或者降序排列,我们
与之前在数组里面不一样,我们是使用list.sort()

E.sort
写到这我们自然想知道对于vector怎样利用sort()进行排
序,
sort(vector1.begin(),vector1.end())进行排序。经过检验发现
deque同样适用sort(deque1.begin(),deque1.end() );进行排

2)若我们想使用降序,两个list首先先得使用降序排列,然后使
用merge的时候也需要进行降序排列。 list1.sort(greater<int>());
list2.sort(greater<int>());
list1.merge(list2,greater<int());

3)如果合并前两个list的顺序没有规律,则使用merge后也发现
不了合并后的规律。那合并就失去了意义。

list1.merge(list2,comp)合并两个有序的链表并使之按照自定义
规则排序之后进行合并(合并之后都是放到list1,然后释放
list2)
B.SPLICE
上面讲了merge的用法,这里我们讲一下splice的用法

1.list1.splice(list1.beg,list2)      将list2连接在list1的beg位置,释放list2/

也可以是list1.splice(list1.end(),list2)
//我们要注意到第一个参数是一个位置,例如使用迭代器的位置(it)例如
list.begin(),例如list.end();list<int>::iterator it;
it=a1.begin();
it++;
it++;
a1.splice(it, a2);**很关键一点就是我们又掌握了连接两个链表的方法。
2.c1.splice(c1.beg,c2,c2.beg)      将c2的beg位置的元素连接到c1的beg位置,
并且在c2中施放掉beg位置的元素#include<bits/stdc++.h>
using namespace std;
int main()
{
list<int> a1,a2;
for(int i=0;i<4;i++)
{
int m;
cin>>m;
a1.push_back(m);
}
for(int i=0;i<4;i++)
{
int n;
cin>>n;
a2.push_back(n);
}
a1.splice(a1.begin(), a2);
list<int>::iterator it;
for(it = a1.begin();it!=a1.end();it++){
cout << *it << " ";
}
cout << endl;
}C.REVERSE

   list.reverse(): 进行链表的反转。
    eg:list1.reverse();

D.ERASE
        erase() 删除一个元素或者一个区域块的元素。
1.list1.erase(list1.location);
    eg:list1.erase(list1.begin);
2.list.erase(location1,location2)
    eg:list1.erase(++list1.begin(),list1.end())

#include<bits/stdc++.h>
using namespace std;
int main()
{
list<int> a1,a2;
for(int i=0;i<4;i++)
{
int m;
cin>>m;
a1.push_back(m);
}
list<int>::iterator it;
// a1.erase(a1.begin());
a1.erase(++a1.begin(),a1.end());
for(it = a1.begin();it!=a1.end();it++){ //不能使用数组随机形式访问了,只能使用迭代器进行访问和遍历
cout << *it << " ";

}
cout << endl;
}

warning:list没有对应的数组类似的【】操作,及没有list【i】

D.sort
   上面刚刚提到。
F.remove.
1.remove():删除链表中匹配值的元素(匹配元素全部删除)   
        eg: a1.remove(4);  删除链表中值为4的元素,其他元素
的先后顺序不变。
2.remove_if():删除满足条件的元素。

G:insertinsert()在指定位置插入一个或多个元素(三个重载函数)

list1.insert(++list1.begin(),9); // list1(1,9,2,3)//在起始位置插入一个1

list1.insert(list1.begin(),2,9); // list1(9,9,1,2,3);//在起始位置插入两个9

list1.insert(list1.begin(),list2.begin(),--list2.end());//list1(4,5,1,2,3);//在list1的起始位置插入list2全部。H.unique
unique()  删除相邻重复元素  eg:list1.unique()(注意喔重复的元
素还是要留一个的,不是全部删了,留一个底子。
   L1(1,1,1,4,3,5,1)L1.unique();         // L1(1,4,3,5,1)
list目前总结的就先这么多操作吧!(要好好消化理解)
  

容器适配器

stl包含三种适配器:stack,queue,priority_queue.适配器是容
器的接口,它本身不能直接保存元素,但是它可以调用另一种顺
序容器去保存元素。可以把适配器看作:它保存一个容器,这个
容器再保存所有元素。

一 stack

 1.定义:stack<int>stack1,stack2;
              stack<elemtype>stack1;

2.操作:stack1.empty()
             stack.size()
             stack.top()
             stack.pop()
             stack.push(num)
3.具体实现:

//栈主要支持empty();size();topo();push();pop()
#include<stack>
#include<vector>
#include<list>
#include<cstdio>
using namespace std;
int main()
{
//可以使用list或者vector作为容器
//默认是使用dequeue的。
stack<int> a;
stack<int> b;
//stack<int,list<int> > a;
//stack<int,vector<int> > b;
int i;
for(i=0;i<10;i++)
{
a.push(i);
b.push(i);
}
printf("%d %d\n",a.size(),b.size());
while(!a.empty())
{
printf("%d ",a.top());
a.pop();
}
putchar('\n');
while(!b.empty())
{
printf("%d ",b.top());
b.pop();
}
putchar('\n');
return 0;
}为了进一步熟练,再来一个具体事例;//这个程序虽然短小,但是掌握了一个很深的内涵
//就是对于入栈数据我们想随意入我们想要的数据的时候,我们
//可以先进行进行scanf进入输入一个数据,然后进行push();
#include<iostream>
#include<cstring>
#in
c41e
clude<stack>
using namespace std;
int main()
{
int temp;
stack<int> s1;
for(int i=0;i<10;i++)
{
scanf("%d",&temp);
s1.push(temp);
}
while(!s1.empty())
{
printf("%d ",s1.top());
s1.pop();
}
return 0;
}

二:queue
1.定义:
queue<elemtype> q1,q2;
基本操作:
q1.empty()
q1.back()
q1.push()
q1.pop()
q1.size()
q1.front()
3,具体代码实现:/*给定一个队列(初始为空),只有两种操作入队和出队,
现给出这些操作请输出最终的队头元素。 操作解释:1表示入队,2表示出队
输入描述 Input Description
N(操作个数)
N个操作(如果是入队则后面还会有一个入队元素)
具体见样例(输入保证队空时不会出队)

输出描述 Output Description
最终队头元素,若最终队空,输出”impossible!”(不含引号)*/
#include<cstdio>
#include<queue>
using namespace std;
int i,n,x,a;
queue<int> q;
int main()
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&x);
if(x==2)
q.pop();
if(x==1)
{
scanf("%d",&a);
q.push(a);
}
}
if(q.size())
printf("%d",q.front());
else
printf("imposs ");
return 0;
}
三 priority_queue  可以参考博客点击打开链接 点击打开链接1
(http://blog.csdn.net/xiaoquantouer/article/details/520159
28)
1.头文件:#include<queue>
2.定义:priority_queue<int> p1;
3.说明:priority_queue<elemtype,container,functional).
             elemtype为数据类型,container为保存数据的容器,
             functional为元素比较方式。若不写后面两个参数,则
             默认为vector和 <(即大顶堆,即队头元素最大)。
             #include<iostream>
#include<queue>
using namespace std;

int main(){
priority_queue<int> p;
p.push(1);
p.push(2);
p.push(8);
p.push(5);
p.push(43);
for(int i=0;i<5;i++){
cout<<p.top()<<endl;//顶端默认是最大的
p.pop();//顶端的先出去
}
return 0;
}4.如不想默认,我们想从小到大输出,那么我们应该进行三个参数完整的
书写。
priority_queue<int, vector<int>, greater<int> >p;  

5.自定义比较方式。
方法二:自定义优先级,重载默认的 < 符号
#include<iostream>
#include<queue>
#include<cstdlib>
using namespace std;
struct Node{
int x,y;
Node(int a=0, int b=0):
x(a), y(b) {}
};

struct cmp{
bool operator()(Node a, Node b){
if(a.x == b.x) return a.y>b.y;
return a.x>b.x;
}
};

int main(){
priority_queue<Node, vector<Node>, cmp>p;

for(int i=0; i<10; ++i)
p.push(Node(rand(), rand()));

while(!p.empty()){
cout<<p.top().x<<' '<<p.top().y<<endl;
p.pop();
}//while
//getchar();
return 0;
}

迭代器

   迭代器是一种对象,它能够用来遍历STL容器中的部分或者全
部元素,每个迭代器对象代表容器中确定的地址。
     eg:vector<elemtype>::iterator it;
          it=vec1.begin();
          cout<<*it;

算法

string    经典函数    经典思维   经典算法   
string简介
http://blog.csdn.net/lsh_2013/article/details/46728993     
 http://www.cnblogs.com/wangkangluo1/archive/2011/07/22/2114118.html
一.string基本介绍
二.特性描述例如length()等
三.substr()
四.swap()
五.find()
六.replace()
七.insert()
八.系列基本函数

一.string基本介绍:

1.c++中string是一个类,不是一般的类型。
   1)进行赋值可以直接用=。((str1='qwe';))
   2)判断是否相等可以直接用==。if(str1==str2);
   3)两个字符串连接直接使用+。str1+str3;
二.特性描述例如length()等

1.capacity():返回当前容量(即string中不必增加内存即可存放
的元素个数)
2int max_size() 返回string对象中可存放的最大字符串长度。
3.int size():返回当前字符串的大小
4.int length():返回当前字符串的长度。
             
                         length专题
  1.eg:str4.length():返回字符串str4的长度。length和size的效
果一样。

2.注意区别strlen()和length()的区别:
s1.length()是求字符串长度。strlen(a[])是求字符数组的长度
(不要弄混,防止某天考试突然运行错误还找不到原因)
接下一篇(string需要讲的太多)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  STL DFS BFS C j