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

              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.begin(),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:insert

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

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>
#include<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需要讲的太多)









  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值