STL常用容器详解

    容器部分主要由头文件, , , , , 组成。
    对于常用的一些容器和容器适配器(可以看作由其它容器实现的容器),可以通过下表总结

    1.序列容器--->元素都有固定位置和顺序,取决于插入时间和地点
        vector、deque、list
    2.关联式容器--->元素位置取决于特定的排序规则
        set、multiset、map、multimap
    数据结构:

        |数据结构                    |    描述                                                                         |    实现头文件    |
        |向量(vector)               |    连续存储的元素                                         |                          |
        |列表(list)                    |    由节点组成的双向链表,每个结点包含着一个元素  |                 |
        |双队列(deque)           |    连续存储的指向不同元素的指针所组成的数组         |           |
        |集合(set)                    |    由节点组成的红黑树,每个节点都包含着一个元素 |                 |
        |                                  |    节点之间以某种作用于元素对的谓词排列,没有两个 |                       |
        |                                  |    不同的元素能够拥有相同的次序                             |                           |
        |多重集合(multiset)     |    允许存在两个次序相等的元素的集合                      |                  |
        |栈(stack)                   |    后进先出的值的排列                                                |              |
        |队列(queue)              |    先进先出的执的排列                                                |            |
        |优先队列(priority_queue)    |    元素的次序是由作用于所存储的值对上的某种谓词决定的的一种队列 |            |
        |映射(map)                |    由{键,值}对组成的集合,以某种作用于键对上的谓词排列                            |              |
        |多重映射(multimap) |    允许键对有相等的次序的映射                                                                          |              |

    3.迭代器
        头文件,
        迭代器在STL中用来将算法和容器联系起来
        STL提供的所有算法都是通 过迭代器存取元素序列进行工作的
        迭代器是一个“可遍历STL容器内全部或部分元素”的对象。
        迭代器指出容器中的一个特定位置。
        迭代器就如同一个指针。
        迭代器提供对一个容器中的对象的访问方法,并且可以定义了容器中对象的范围。
    4.算法
        算法部分主要由头文件组 成
一、容器deque的使用方法
    适合    在头尾添加移除元素。使用方法与vector类似。
二、容器queue,stack的使用方法
    适合队列,堆栈的操作方式。
三、容器list的使用方法
    适合在任意位置快速插入移除元素

容器是与模板配合使用的。

Vector

一、概念

vector是将元素置于一个动态数组中加以管理的容器。

vector可以随机存取元素(支持索引值直接存取, 用[]操作符或at()方法,这个等下会详讲)

vector尾部添加或移除元素非常快速。但是在中部或头部插入元素或移除元素比较费时

二、代码实现

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
class Container
{
public:
	virtual ~Container() {}
public:
	virtual int process() = 0;
};
//类模板中函数的定义和声明要写在一块
template
class MVector : public Container
{
public:
    MVector() {}
    virtual ~MVector() {}

public:
    vector m_vec;


public:
    virtual int process() override
    {
	return 0;
    }
public:  //vector构造函数 将数组arr的数据拷贝到vector中
    void MVectorConstr(T* arr, int n)
    {
	//正确
	vector  vecIntA(arr, arr + n);
	//错误
	//m_vec(arr, arr + n);
	m_vec = vecIntA;
	//遍历
	//for (auto const& value : m_vec)
	//{ 
	//	std::cout << value<<"---"; 
	//}
	//std::cout << std::endl;
	for (std::vector::iterator it = m_vec.begin(); it != m_vec.end(); it++)
	{
		std::cout << *it << "---";
	}
	std::cout << std::endl;
	m_vec.clear();
	std::cout << "m_vec size:" << m_vec.size() << std::endl;
    }
    //带参数的构造  将[beg, end)区间中的元素拷贝给本身。注意该区间是左闭右开的区间
    vector MVectorConstr1(vector vecElem)
    {
	//正确
	vector  vecIntA(vecElem.begin(), vecElem.end());
	//错误
	//m_vec(vecElem.begin(), vecElem.end());
	m_vec = vecIntA;
	for (vector::iterator it = m_vec.begin(); it != m_vec.end(); it++)
	{
		std::cout << *it << "---";
	}
	std::cout << std::endl;
	std::cout << "m_vec size:" << m_vec.size() << std::endl;
	m_vec.clear();
	return m_vec;
    }

    //将n个elem拷贝给本身
    vector MVectorConstr2(int n, T elem)
    {
	//正确
	vector  vecIntA(n, elem);
	//错误
	//m_vec(n, elem);
	m_vec = vecIntA;
	for (vector::iterator it = m_vec.begin(); it != m_vec.end(); it++)
	{
		std::cout << *it << "---";
	}
	std::cout << std::endl;
	std::cout << "m_vec size:" << m_vec.size() << std::endl;
	m_vec.clear();
	return m_vec;
    }

    vector MVectorConstr3(const vector &vec)  //拷贝构造函数
    {
	//正确
	vector  vecIntA(vec);
	//错误
	//m_vec(vec);
	m_vec = vecIntA;
	for (vector::iterator it = m_vec.begin(); it != m_vec.end(); it++)
	{
		std::cout << *it << "---";
	}
	std::cout << std::endl;
	std::cout << "m_vec size:" << m_vec.size() << std::endl;
	m_vec.clear();
	return m_vec;
    }
public:	//vector赋值
    //将[beg, end)区间中的数据拷贝赋值给本身,左闭右开
    vector MVAssign(vector vecElem)
    {
	m_vec.assign(vecElem.begin(), vecElem.end());
	for (vector::iterator it = m_vec.begin(); it != m_vec.end(); it++)
	{
		std::cout << *it << "---";
	}
	std::cout << std::endl;
	std::cout << "m_vec size:" << m_vec.size() << std::endl;
	m_vec.clear();
	return m_vec;
    }
    //将n个elem拷贝赋值给本身
    vector MVAssign(int n, T vecElem)
    {
	m_vec.assign(n, vecElem);
	for (vector::iterator it = m_vec.begin(); it != m_vec.end(); it++)
	{
		std::cout << *it << "---";
	}
	std::cout << std::endl;
	std::cout << "m_vec size:" << m_vec.size() << std::endl;
	m_vec.clear();
	return m_vec;
    }

    //重载等号操作符
    vector& MVOper(const vector  &vec)
    {
	m_vec = vec;
	for (vector::iterator it = m_vec.begin(); it != m_vec.end(); it++)
	{
        	std::cout << *it << "---";
	}
	std::cout << std::endl;
	std::cout << "m_vec size:" << m_vec.size() << std::endl;
	m_vec.clear();
	return m_vec;
    }
    // 将vec与本身的元素互换
    vector MVSwap(vector  &vec)
    {
	m_vec.swap(vec);
	return m_vec;
    }
public: //vector大小 判空 重置大小
    int MVSize()
    {
	return m_vec.size();
    }

    bool MVEmpty()
    {
	return m_vec.empty();
    }

    int MVResize(int num)
    {
	m_vec.resize(num);
    }
public: //末尾添加、移除操作
    void MVPushBack(T elem)
    {
    	m_vec.push_back(elem);
    }
    void MVPop_bak()
    {
    	m_vec.pop_back();
    }
public:
    //at 如果elem越界,抛出out_of_range异常
    //[] 返回索引idx所指的数据,越界时,运行直接报错
    //m_vec.at(2) == m_vec[2]	
    T MVAt(int elem)
    {
    	return m_vec.at(elem);
    }
    T MVFront()
    {
    	return m_vec.front();
    }
    T MVBack()
    {
    	return m_vec.back();
    }

    //正向遍历
    void Traversal()
    {
	for (vector::iterator it = m_vec.begin(); it != m_vec.end(); ++it)
	{
        	cout << *it;
	}
    }

	//反向遍历
    void reTraversal()
    {
	//注意,小括号内仍是++rit
    for (vector::reverse_iterator rit = m_vec.rbegin(); 
            rit != m_vec.rend(); ++rit)
	{
		cout << *rit;
	}
    }
	//删除pos位置的数据,返回下一个数据的位置。
    void MVErase(int n)
    {
	if (m_vec.size() > 0)
		m_vec.erase(n);
    }
    //删除[beg,end)区间的数据,返回下一个数据的位置
    void MVErase(vector vecElem)
    {
	if (vecElem.size() <= 0)
		return;
	m_vec = vecElem;
	m_vec.erase(vecElem.begin(), vecElem.end());
    }
};

int main()
{
	int arr[5] = { 0,1,2,3,4 };
	vector  vecIntA(arr, arr + 5);

	MVector mvc;
	mvc.MVectorConstr(arr,5);
	mvc.MVectorConstr1(vecIntA);
	mvc.MVectorConstr2(4,(int)5);
	mvc.MVectorConstr3(vecIntA);
	mvc.MVAssign(vecIntA);
	mvc.MVAssign(4, (int)5);
	mvc.MVOper(vecIntA);

	vector vc=mvc.MVSwap(vecIntA);
	for (vector::iterator it = vc.begin(); it != vc.end(); it++)
	{
		std::cout << *it << "---";
	}
	std::cout << std::endl;
	std::cout << "m_vec size:" << vc.size() << std::endl;

	for (vector::iterator it = vecIntA.begin(); it != vecIntA.end(); it++)
	{
		std::cout << *it << "---";
	}
	std::cout << std::endl;
	std::cout << "vecIntA size:" << vecIntA.size() << std::endl;

	for (int i = 0; i < 5;i++)
	{
		mvc.MVPushBack(i);
	}
	std::cout << "mvc size:" << mvc.MVSize() << std::endl;

	for (int i = 0; i < 5; i++)
	{
		mvc.MVPop_bak();
	}
	std::cout << "mvc size:" << mvc.MVSize() << std::endl;

}

deque 

一、概念
    deque  可以随机存取元素
    deque  是双端数组 vector是单端数组
                头部和尾部添加或移除元素都非常快速。但是在中部安插元素或移除元素比较费时
                 在接口上和vector非常相似,在许多操作的地方可以直接替换
二、代码实现

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
template
class MDeqeue : public Container
{
public:
	MDeqeue() {}
	virtual ~MDeqeue() {}

public:
	//
	deque m_deq;
public:
	virtual int process() override
	{
		return 0;
	}
public: //构造函数、赋值
	void MDConstrc(deque elem)
	{
		m_deq = elem;
		Traversal();
		m_deq.clear();
	}
	//构造函数将[beg, end)区间中的元素拷贝给本身
	void MDConstrc(deque elem, int n)
	{
		deque deq(elem.begin(), elem.begin() + n);
		m_deq = deq;
		Traversal();
		m_deq.clear();
	}
	//将[beg, end)区间中的数据拷贝赋值给本身
	void MDAssign(deque elem, int n)
	{
		m_deq.assign(elem.begin(), elem.begin() + n);
		Traversal();
		m_deq.clear();
	}
	//将n个elem拷贝赋值给本身
	void MDAssign(int n, T elem)
	{
		m_deq.assign(n, elem);
		Traversal();
		m_deq.clear();
	}
	// 将elem与本身的元素互换
	void MDSwap(deque& elem)
	{
		m_deq.swap(elem);
		Traversal();
		m_deq.clear();
	}
	int MDSize()
	{
		std::cout << "deque size:" << m_deq.size();
		return m_deq.size();
	}
	bool MDEmpty()
	{
		return m_deq.empty();
	}
	void MDResize(int n)
	{
		m_deq.resize(n);
	}

public: //插入删除
	 //在pos位置插入一个elem元素的拷贝,返回新数据的位置。
	void MDInsertElem(T elem)
	{
		m_deq.insert(m_deq.begin(), elem);
	}
	//在pos位置插入n个elem数据,无返回值。
	void MDInsert_N_Elem(int n, T elem)
	{
		m_deq.insert(m_deq.begin(), n, elem);
	}
	//在pos位置插入[beg,end)区间的数据,无返回值。
	void MDInsert_beg_end_elem(int n, deque elem)
	{
		m_deq.insert(m_deq.begin(), elem.begin(), elem.begin() + n);
	}
	//在容器尾部添加一个数据
	void MDPush_Back(T elem)
	{
		m_deq.push_back(elem);
	}
	//删除容器最后一个数
	void MDPop_Back()
	{
		if (m_deq.size() > 0)
			m_deq.pop_back();
	}
	//在容器头部插入一个数据
	void MDPush_Front(T elem)
	{
		m_deq.push_front(elem);
	}

	//删除容器第一个数据
	void MDPop_Front()
	{
		if (m_deq.size() > 0)
			m_deq.pop_front();
	}
	//返回第一个数据。		
	T MDDeqFrontElem()
	{
		return m_deq.front();
	}
	//返回最后一个数据。		
	T MDDeqBackElem()
	{
		return m_deq.back();
	}

	//deque.clear();	//移除
	//deque.erase(beg, end);//删除[beg,end)区间的数据,返回下一个数据的位置
	//deque.erase(pos); //删除pos位置的数据

public: //遍历
	//正向遍历
	void Traversal()
	{
		for (deque::iterator it = m_deq.begin(); it != m_deq.end(); ++it)
		{
			cout << *it;
			//m_deq.erase(it);
		}
	}

	//反向遍历
	void reTraversal()
	{
		//注意,小括号内仍是++rit
		for (deque::reverse_iterator rit = m_deq.rbegin(); rit != m_deq.rend(); ++rit)
		{
			cout << *rit;
		}
	}

};

int main()
{
    	deque m_deq;
	for (size_t i = 0; i < 6; i++)
	{
		m_deq.push_back(i);
	}
	MDeqeue mde;
	
	//mde.MDConstrc(m_deq);

	//构造函数将[beg, end)区间中的元素拷贝给本身
	mde.MDConstrc(m_deq, 2);

	//将[beg, end)区间中的数据拷贝赋值给本身
	mde.MDAssign(m_deq, 3);

	//将n个elem拷贝赋值给本身
	mde.MDAssign(4, 4);

	// 将elem与本身的元素互换
	mde.MDSwap(m_deq);
	for (deque::iterator it = m_deq.begin(); it != m_deq.end(); ++it)
	{		
		cout << *it;
	}

	mde.MDSize();

	mde.MDResize(5);

	 //在pos位置插入一个elem元素的拷贝,返回新数据的位置。

	mde.MDInsertElem(9);
	mde.Traversal();
	mde.m_deq.clear();


	//在pos位置插入n个elem数据,无返回值。
	mde.MDInsert_N_Elem(2,6);
	mde.Traversal();

	//在pos位置插入[beg,end)区间的数据,无返回值。
	mde.MDInsert_beg_end_elem(3, m_deq);
	mde.Traversal();

	//在容器尾部添加一个数据
	mde.MDPush_Back(8);
	mde.Traversal();

	//删除容器最后一个数
	mde.MDPop_Back();
	mde.Traversal();

	在容器头部插入一个数据
	mde.MDPush_Front(1);

	//删除容器第一个数据
	mde.MDPop_Front();

	返回第一个数据。		
	mde.MDDeqFrontElem();

	返回最后一个数据。		
	mde.MDDeqBackElem();
	//正向遍历
	mde.Traversal();

	反向遍历
	mde.reTraversal();
}

queue

一、概念

queue是队列容器,是一种“先进先出”的容器。
queue是简单地装饰deque容器而成为另外的一种容器

二、代码实现

template
class MQueue : public Container
{
public:
	MQueue() {}
	virtual ~MQueue() { }
	virtual int process() override
	{
		return 0;
	}
	queue m_que;
public:
	void MQConstruc(queue elem)
	{
		queue qu(elem);
		m_que = qu;
	}

	void MQPush(T elem)//往队尾添加元素
	{
		if (m_que.size() < 0)
			return;
		m_que.push(elem);
		cout << "Push queue size:" << m_que.size() << endl;
	}
	void MQPop()//从队头移除第一个元素
	{
		m_que.pop();
		cout << "Pop queue size:" << m_que.size() << endl;
	}
	//返回最后一个元素
	T MQBack() const { return m_que.back(); }
	//返回第一个元素
	T MQFront() const { return m_que.front(); }


};

int main()
{
    	queue m_que;
	for (int i = 0; i < 5;i++) 
	{
		m_que.push(i);
	}
	MQueue m_qu;

	m_qu.MQConstruc(m_que);

	m_qu.MQPush(8);
	m_qu.MQPop();
}

stack

一、概念

是堆栈容器,是一种“先进后出”的容器

二、代码实现

template
class MStack : public Container
{
public:
	MStack()
	{

	}
	virtual ~MStack()
	{

	}
	virtual int process() override
	{
		return 0;
	}
	stack m_stac;

	void MSConstruc(stack elem)
	{
		stack elm(elem);
		m_stac = elm;
	}
public://Push Pop
	void MSPush(T elem)  //栈头添加
	{
		m_stac.push(elem);
	}

	void MSPop()
	{
		if (m_stac.size() > 0)
			m_stac.pop()
	}
	T MSTop() //返回栈顶元素
	{
		if (m_stac.size() <= 0)
			return NULL;
		return m_stac.top();
	}
public: //构造 赋值
	void NSConstrc(stack elem)
	{
		stack eln(elem);
		m_stac = eln;
	}

};

list

一、概念

list是一个双向链表容器,可高效地进行插入删除元素
list不可以随机存取元素,所以不支持at.(pos)函数与[]操作符

二、代码实现

template
class MList : public Container
{
public:
	MList() {}
	virtual ~MList() {}
	virtual int process() override
	{
		return 0;
	}
	list m_lis;
public:
	void MLConstruc(list elem)
	{
		list list(elem);
		m_lis = list;
	}
	//在容器头加入一个元素
	void MLPush_back(T elem)
	{
		m_lis.push_front(elem);
	}
	//将n个elem拷贝到自身
	void MLAssign(int n, T elem)
	{
		m_lis.clear();
		m_lis.assign(n, elem);
	}
	//将[beg, end)区间中的数据拷贝赋值给本身。注意该区间是左闭右开的区间
	void MLAssign(list elem)
	{
		m_lis.clear();
		m_lis.assign(elem.begin(), elem.end());
	}
	//删除[beg,end)区间的数据,返回下一个数据的位置
	void MLEarse(list elem)
	{

	}
	//删除pos位置的数据,返回下一个数据的位置。
	void MLEarse(int pos)
	{
		m_lis.erase(pos);
	}
	//删除容器中所有与elem值匹配的元素
	void MLRemove(T elem)
	{
		m_lis.remove(elem);
	}

	void MLReverse() 
	{
		m_lis.reverse();
	}
	int MListSize() const { return m_lis.size(); }
	//删除容器开头的第一个元素
	void MLPop_back()
	{
		m_lis.pop_front();
	}
	T MLBack() const { return m_lis.back(); }
	T MLFront() const { return m_lis.front(); }

	//正向遍历
	void Traversal()
	{
		for (list::iterator it = m_lis.begin(); it != m_lis.end(); ++it)
		{
			cout << *it;
		}
	}

	//反向遍历
	void reTraversal()
	{
		//注意,小括号内仍是++rit
		for (list::reverse_iterator rit = m_lis.rbegin(); rit != m_lis.rend(); ++rit)
		{
			cout << *rit;
		}
	}
};

int main()
{
	list lis;
	for (int i = 6 - 1; i >= 0; i--)
	{
		lis.push_back(i);
	}
	MList m_lis;

	m_lis.MLConstruc(lis);
	cout<<"list head:"<

 

你可能感兴趣的:(C++11,C++)