C++ 中的STL

STL中的基本概念
  • STL(Standard Template Library),标准模板库。
  • 容器:容纳各种数据类型的通用数据结构,是类模板
  • 迭代器:依次存取容器中的元素,类似指针
  • 算法:操作容器中的元素的函数模板
容器的分类
  • 顺序容器:vector , deque , list
  • 关联容器:set , mutiset , map , mutimap
  • 容器适配器:stack , queue , priority_queue
    放入容器中的对象,所属的类,应该重载 == 和 “<”运算符
顺序容器
  • vector 头文件
    动态数组,内存连续,存取元素在常数时间内完成,在尾部删除元素具有较好的性能。
    在这里插入图片描述
  • deque 头文件
    双向队列,内存连续,存取元素在常数时间内完成(仅次于vector),在两端删除元素具有较好的性能。
    在这里插入图片描述
  • lIst 头文件
    双向链表。元素在内存中不连续存放,在任何位置存取元素都能在常数时间内完成,不支持随机存取。
    在这里插入图片描述
关联容器

元素是排序的
插入任何元素,都按照其特定的排序规则确定其位置
在查找时具有较好的性能
通常以平衡二叉树的方式实现,插入和检索的时间都是O(log(N))

  • set/mutiset 头文件
    set就是集合,其中不允许相同元素,mutiset中允许有相同的元素
  • map/mutimap 头文件
    map与set的不同之处在于map中的元素只有两个成员变量,一个名字为first,另一个为secoond,map根据first的值对元素进行从小到大的排序,并可以快速的根据first的值来检索元素。
容器适配器简介
  • stack
    删除、检索、修改的项只能是最近插入序列的项,即栈顶的项,后进先出
    在这里插入图片描述
  • queue
    队列。插入只可以在尾部进行,删除、检索和修改只允许头部进行。先进先出。
    在这里插入图片描述
  • priority_queue
    优先级队列,最高优先级的元素总是第一个出队
顺序容器和关联容器中都有的成员函数
  • begin:指向容器中第一个元素的迭代器
  • end :指向容器中最后一个元素后面位置的迭代器
  • rbegin : 指向容器中最后一个元素的迭代器
  • rend :指向容器中第一个元素前面位置的迭代器
  • erase: 从容器中删除一个或者几个元素
  • clear: 从容器中删除所有的元素
顺序容器中的常用成员函数
  • front :返回容器中第一个元素的引用
  • back :返回容器中最后一个元素的引用
  • push_back :在元素尾部添加新元素
  • pop_back : 删除元素末尾的元素
  • erase :删除迭代器指向的元素,或者删除一个区间,返回被删除元素后面位置的迭代器
迭代器
  • 用于指向顺序容器和关联容器中的元素
  • 迭代器用法和指针类似
  • 有const和非const 两种
  • 通过迭代器可以读取它指向的元素
  • 通过非const迭代器可以修改它指向的元素
  • 定义迭代器的方法:
    容器类名::iterator 变量名
    或者
    容器类名::const_iterator 变量名
    访问一个迭代器指向的元素
    *迭代器变量名
    迭代器可以执行++操作,以使其指向容器中的下一个元素,如果迭代器到达了容器中最后一个元素的后面,此时再使用它,就会报错,类似于使用NULL或者未初始化的指针一样。
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;

int main(int argc, char *argv[])
{
    vector<int> v ;//一个存放 int 元素的数组,一开始里面没有元素
    v.push_back( 1 );
    v.push_back( 2 );
    v.push_back( 3 );
    v.push_back( 4 );
    vector<int>::const_iterator i;//常量迭代器
    for( i = v.begin() ; i != v.end() ; i++ )
    {
       cout << *i << " , " ;
    } 
    cout << endl;
    vector<int>::reverse_iterator r ; //反向迭代器
    for( r = v.rbegin() ; r != v.rend() ; r++ )
    {
       cout << *r << " , " ;
    } 
    cout << endl;
    vector<int>::iterator j ;
    for( j = v.begin() ; j != v.end() ; j++ )
    {
       *j = 200 ;
    }
    cout << endl;
    for( i = v.begin() ; i != v.end() ; i ++ )
    {
       cout << *i << " , " ;   
    }
    cout << endl;
    system("PAUSE");
    return EXIT_SUCCESS;
}

输出结果如下:
在这里插入图片描述

双向迭代器

如果p 和p1都是双向迭代器,则可以对p , p1进行如下的操作:

  • ++p , p++ 使p指向容器中下一个元素
  • –p , p-- 使p指向容器中上一个元素
  • *p ,取出p指向的元素
  • p = p1 ,赋值
  • p == p1 , 或者p != p1 ,判断是否相等,不相等
随机访问迭代器

若p和p1都是随机访问迭代器,则可以对p和p1进行如下操作

  • 双向迭代器的所有操作
  • p += i ,将p向后移动 i 个元素
  • p -= i , 将p向前移动 i 个元素
  • p + i , 指向p后面的第 i 个元素的迭代器
  • p - i , 指向p前面的第 i 个元素的迭代器
  • p[i] , p后面第i个元素的引用
  • p < p1 , p <= p1 , p> p1 , p >= p1
    在这里插入图片描述
  vector<int> v(100);
    int i ;
    for( i = 0 ; i < v.size() ; i++ )
    {
       cout << v[i] << " " ; //根据下标随机访问 
    }
    vector<int> ::const_iterator ii ;
    for( ii = v.begin() ; ii != v.end() ; ii++ )
    {
       cout << *ii << " " ;
    }
    ii = v.begin();
    while( ii < v.end() )
    {
       cout << *ii ;
       ii = ii + 2 ;       
    }
    list<int> listv;
    list<int>::const_iterator vv ;
    for( vv = listv.begin() ; vv != listv.end() ; vv++ )
    {
       cout << *vv << " " ;     
    }
    //错误的用法如下
    /*
       for( vv = listv.begin() ; vv < list.end() ; vv++ );
       for( int i = 0 ; i < listv.size() ; i++ ); 
    */
算法
  • 算法就是一个函数模板,大多数在中定义,
  • STL提供能在各种容器中通用的算法,比如查找,排序等
  • 算法通过迭代器操作元素。通常可以对容器中的某个局部区间进行操作,因此需要两个参数,一个是起始元素的迭代器,另一个是终止元素后面位置的一个迭代器。比如排序和查找
  • 有的算法返回一个迭代器
  • 算法可以处理容器,也可以处理普通数组
    举例:
	template< class Init , class T >
	Init find( Init first , Init last , const T &val );
  • first 和 last 这两个参数都是容器的迭代器 ,它们给出了容器中查找区间的起点和终点[ first , last )。区间的起点位于查找范围之中,而终点不是。find在 [ first ,last )中查找等于val的人。
  • 用 == 运算符判断相等。
  • 函数返回值是一个迭代器,如果找到,则该迭代器指向被找到的元素,否则,返回的迭代器等于last 。
  • 举个例子:
	#include <vector>
	#include <algorithm>
	#include <iostream>
	using namespace std;
	int main() 
	{
       //find算法示例
       int array[10] = { 10 , 20 , 30 , 40 } ;
       vector<int> v;
       v.push_back( 1 );
       v.push_back( 2 );
       v.push_back( 3 );
       v.push_back( 4 );
       vector<int>::iterator p ;
       p = find( v.begin() , v.end() , 3 );
       if( p != v.end() )
       {
 	      cout << *p << endl;
 	   }
 	   p = find( v.begin() , v.end() , 9 );
 	   if( p != v.end() )
 	   {
           cout << *p <<endl;
       }
       else
       {
           cout << "not found" << endl;
       }
       p = find( v.begin() + 1 , v.end() - 2 , 1);// 整个容器[ 1 , 2 , 3 , 4 ] 查找区间[ 2 . 3 )
       if( p != v.end() )
       {
           cout << *p << endl;
   	   }
   	   int *pp = find( array , array + 4  , 20 );//数组名是迭代器
   	   cout << *pp << endl;
    }

在这里插入图片描述

STL中大小的概念
  • 关联容器内部元素是从小到大排序
  • 有些算法要求其区间是从小到达排序的,称为有序区间算法
    例如:binary_search
  • 有些算法会对其区间进行从小到大排序,称为排序算法
    例如:sort
  • 还有一些算法涉及大小的概念
    使用STL时,在缺省的条件下,以下三种说法等价:
  • x 比 y小
  • 表达式 "x < y"为真
  • y 比 x 大
    STL中相等的概念
  • 有时,x 和 y 相等,等价于 "x == y " 为真
    例如:在未排序的区间上进行的算法,如顺序查找 find
  • 有时,x 和 y 相等,等价于 “x小于y和y小于x同时为假”
    例如有序区间算法binary_search ,关联容器自身成员函数find
    STL中相等概念演示:
	#include <iostream>
	#include <algorithm>
	using namespace std;
	class A
	{
         int v ;
         public: A( int n ):v( n){}
         bool operator < ( const A &a2 ) const 
         {
              cout << v << " < " << a2.v << "?" <<endl;
              return false;
         }
         bool operator == ( const A &a2 ) const
         {
              cout << v << " == " << a2.v << "?" << endl;
              return v == a2.v;
         }
    };
    int main() 
    {
         A a[] = { A(1) , A(2) , A(3) , A(4) , A(5) };
         cout << binary_search( a , a + 4 , A(9) ) << endl;
         return 0;
    }

在这里插入图片描述
用 vector 实现二维数组

	#include <iostream>
	#include <vector>
	using namespace std;
	int main()
	{
       vector<vector<int>> v(3);
       //v中有3个元素,每个元素都是vector<int>类型
       for( int i = 0 ; i < v.size() ; i++ )
       {
            for( int j = 0 ; j < 4 ; j++ )
            {
                 v[i].push_back( j );
            }
       }
       for( int i = 0 ; i < v.size() ; i++ )
       {
            for( int j = 0 ; j < v[i].size() ; j ++ )
            {
                 cout << v[i][j] << " " ;
            }
            cout << endl;
       }
    }

程序执行结果:
在这里插入图片描述
vector 示例程序

	#include <iostream>
	#include <vector>
	using namespace std;
	template < class T >
	void printVector( T s , T e )
	{
         for( ; s != e ; s++ )
         {
              cout << *s << " " ;
         }
         cout << endl;
    }
    int main()
    {
         int a[5] = { 1 , 2 , 3 , 4 , 5 };
         vector<int> v( a, a + 5 );
         cout << v.end() - v.begin() << endl;
         //两个随机迭代器可以相减,结果为5
         printVector( v.begin() , v.end() ) ;
         v.insert( v.begin() + 2 , 13 );
         printVector( v.begin() , v.end() );
         v.erase( v.begin() + 2 );
         printVector( v.begin() , v.end() );
         vector<int> v2( 4 , 100 );
         //v2中有4个元素,都是100
         v2.insert( v2.begin() , v.begin() + 1 , v.begin() + 3 );
         // 2 3 100 100 100 100
         printVector( v2.begin() , v2.end() );
         v.erase( v.begin() + 1 , v.begin() + 3 );//删除 2 3
         printVector( v.begin() , v.end() ); // 1 4 5
         return 0 ;
    }

结果如下:
在这里插入图片描述

deque
  • 所有适合 vector 的操作都适合于 deque
  • deque 还有push_front(将元素插入到前面)和pop_front(删除最前面位置的元素的操作),复杂的为O(1)。
list 容器
  • 在任何位置插入删除都是常数时间,不支持随机存取
  • 除了具有顺序容器都有的成员函数外,还支持8个成员函数
  • push_front :在前面插入
  • pop_front :删除前面的元素
  • sort:排序,list不支持STL中的算法 sort
  • remove:删除和指定值相等的所有元素
  • unique:删除所有和前一个元素相同的元素,要做到不重复,删除之前还要sort
  • merge:合并两个链表,并清空被合并的那个
  • reverse:颠倒链表
  • splice :在指定位置插入另一个链表中的一个或者多个元素,并在另一个链表中删除被插入的元素
    链表使用举例
	#include <list>
	#include <iostream>
	#include <algorithm>
	using namespace std;
	class A
	{
 		private:
 		 	int n;
 		public:
 			A( int n_)
 			{
 			    n = n_;
 			}
 		friend bool operator<( const A &a1 , const A &a2 );
 		friend bool operator ==( const A &a1 , const A &a2 );
 		friend ostream & operator << ( ostream &o , const A &a );
    };
    bool operator < ( const A &a1 , const A &a2 )
    {
		return a1.n < a2.n;
	}
	bool operator == ( const A &a1 , const A &a2 )
	{
         return a1.n == a2.n;
	}
	ostream & operator << ( ostream &o , const A &a )
	{
		o << a.n;
		return o;
 	}
 	template <T>
 	void printList( const list<T> & lst )
 	{
		//推荐使用两个迭代器作为参数比较好
		list<T>::const_iterator i ;
		i = lst.begin();
		for( ; i != lst.end() ; i++ )
		{
	  		cout << *i << " " ;
		}
		cout << endl;
	}
	int main()
	{
 		list<A> list1 , 
 		 		list2 ;
 		list1.push_back( 1 );
 		list1.push_back( 3 );
 		list1.push_back( 2 );
 		list1.push_back( 4 );
 		list1.push_back( 2 );
 		list2.push_back( 10 );
 		list2.push_back( 20 );
 		list2.push_back( 30 );
 		list2.push_back( 30 );
 		list2.push_back( 30 );
 		list2.push_back( 40 );
 		list2.push_back( 40 );
 		cout << "list1: " ;
 		printList( list1 ); // 1 3 2 4 2
 		cout << "list2: " ;
 		printList( list2 ); // 10 20 30 30 30 40 40
 		list2.sort();
 		cout << "sorted list2: " ;
 		printList( list2 ); // 10 20 30 30 30 40 40
 		list2.pop_front();
 		cout << "list2 pop_front: " ;
 		printList( list2 ); // 20 30 30 30 40 40
 		list1.remove( 2 ); // 删除所有和A(2)相等的元素
 		cout << "list1 remove( 2 ) " ;
 		printList( list1 ); // 1 3 4
 		list2.unique(); //删除所有和前一个元素相等的元素
 		cout << "list2 unique(): " ;
 		printList( list2 ); // 20 30 40 
 		list1.merge( list2 ); // 合并list2到list1并清空list2 
 		cout << "list1 merge( list2): ";
 		printList( list1 ); // 1 3 4 20 30 40
 		list1.reverse();
 		cout << "list1.reverse(): " ;
 		printList( list1 );
 		list2.push_back( 100 );
 		list2.push_back( 200 );
 		list2.push_back( 300 );
 		list2.push_back( 400 );
 		list<A>::iterator p1 , p2 , p3 ;
 		p1 = find( list1.begin() , list1.end() , 3 );
 		p2 = find( list2.begin() , list2.end() , 200 );
 		p3 = find( list2.begin() , list2.end() , 400 );
 		list1.splice( p1 , list2 , p2 , p3 );
 		//将[ p2 , p3 )插入P1之前,并从list2中删除[ p2 , p3 )
 		cout << "list1 splice( p1 , list2 , p2 , p3 ): " ;
 		printList( list1 );
 		// 40 30 20 4 200 300 3 1
 		cout << "list2 spliced: " ;
 		printList( list2 );
 		// 100 400 
 		return 0;
	}

结果如下:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百万攻城狮

你的鼓励是我最大的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值