1. 程式人生 > >STL標準庫的使用【2】

STL標準庫的使用【2】

我們繼續來介紹STL的相關容器的使用

一、vector

vector 是將元素置於一個動態陣列中加以管理的容器

vector 可以隨機存取元素 (用 [] 操作符 或 at () 方法)

vector 尾部新增或移除元素非常快速,但是在中部和頭部時比較費時

1、vector 資料的訪問

void func1()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(6);

	// 第一個元素
	cout << v.front() << endl;

	// 最後一個元素
	cout << v.back() << endl;

	// 返回值是一個引用
	v.front() = 10;
	v.back()  = 8;

	while(!v.empty())
	{
		cout << v.back() << endl;

		// 刪除最後一個元素,沒有返回值
		v.pop_back();
	}
}

2、遍歷
void printV(vector<int> &v1)
{
	for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
	{
		cout << *it << " "; 
	}
	cout << endl;
}

3、構造
void func2()
{
	// 定義一個容器,一開始賦予10個物件空間
	vector<int> v1(10);
	cout << "當前元素個數: " << v1.size() << endl;

	v1[0] = 17;
	v1.at(1) = 9;
	v1.push_back(7);
	cout << "當前元素個數: " << v1.size() << endl;
	printV(v1);

	vector<int>  v2(10, 2);
	printV(v2);

	vector<int> v3 = v2;
	printV(v3);
	v3 = v1;
	printV(v3);

	vector<int>  v4(v3.begin(), v3.begin()+4);
	printV(v4);
}

4、元素刪除
void func3()
{
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printV(v1);

	vector<int>::iterator it = find(v1.begin(), v1.end(), 5);
	// 單個元素刪除
	v1.erase(it);
	printV(v1);

	vector<int>::iterator it1 = find(v1.begin(), v1.end(), 3);
	vector<int>::iterator it2 = find(v1.begin(), v1.end(), 8);
	// 區間刪除
	v1.erase(it1, it2);
	printV(v1);

	// 清空容器
	// v1.clear();
	vector<int> v2;   // 空的容器

	// 容器交換
	v1.swap(v2);

	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(2);
	v1.push_back(6);
	v1.push_back(2);
	v1.push_back(2);

	//for(vector<int>::iterator it = v1.begin(); it != v1.end();)
	//{
	//	if (*it == 2)
	//	{
	//		// 返回指向刪除元素下一個元素的迭代器,需要接收回來
	//		it = v1.erase(it);
	//	}
	//	else
	//	{
	//		it ++;
	//	}
	//		
	//}

	it = v1.begin();
	while(it != v1.end())
	{
		if (*it == 2)
			it = v1.erase(it);
		else
			it++;
	}


	printV(v1);
}

5、元素插入
void func4()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(6);

	v.insert(v.begin(), 10);
	printV(v);

	v.insert(v.begin()+2, 3);
	printV(v);

	v.insert(v.end(), 4);
	printV(v);

	vector<int> v1;

	v1.insert(v1.begin(), v.begin(), v.end());
	printV(v1);
}

二、stack 和 queue

stack是堆疊容器,是一種“先進後出”的容器

queue是佇列容器,是一種“先進先出”的容器

棧這個容器的相關操作

void func1()
{
	stack<int> s;
	s.push(1);
	s.push(5);
	s.push(3);
	s.push(10);         //插入

	cout << "棧頂元素: " << s.top() << endl;
	cout << "元素個數: " << s.size() << endl;

	while (!s.empty())
	{
		cout << s.top() << endl;  // 列印棧頂元素
		s.pop();  
	}
}

佇列的相關操作(和棧類似)
void func2()
{
	queue<int> q;
	q.push(1);
	q.push(10);
	q.push(2);
	q.push(5);

	cout << "隊頭元素: " << q.front() << endl;
	cout << "隊尾個數: " << q.back() << endl;

	while (!q.empty())
	{
		cout << q.front() << endl;  // 列印棧頂元素
		q.pop();  
	}
}

用兩個棧實現一個佇列
class MyQueue
{
public:
	// 出隊
	void pop()
	{
		// 第一種:
		// 1、先把 s1 留一個元素, 其他匯入到 s2 中
		// 2、s1 出棧
		// 3、將 s2 元素再匯入到 s1 中

		// 第二種
		// 1、先判斷 s2 是否為空
		// 2、不為空,s2直接出棧
		// 3、如果空,將 s1 留一個元素, 其他匯入到 s2 中
		// 4、s1出棧
		if(s2.empty())
		{
			while (s1.size() > 1)
			{
				s2.push(s1.top());
				s1.pop();
			}

			if (!s1.empty())
				s1.pop();
		}
		else
		{
			s2.pop();
		}
	}

	// 入隊
	void push(int num)
	{
		// 入 s1
		s1.push(num);
	}
private:
	stack<int> s1;
	stack<int> s2;
};
三、list容器

list是一個雙向連結串列容器,可以高效地進行插入和刪除
list不可以隨機的儲存元素

1、list 的賦值 刪除  反序

void func1()
{
	list<int> list1;
	list1.push_back(1);
	list1.push_back(2);
	list1.push_back(2);
	list1.push_back(2);
	list1.push_back(2);
	list1.push_back(2);
	list1.push_back(2);
	list1.push_back(3);

	list1.push_front(-1);
	list1.push_front(-2);
	list1.push_front(-3);

	printL(list1);

	list<int>::iterator it = list1.begin();
	it++;
	it++;

	// list1.erase(list1.begin(), list1.end());       刪除區間資料返回下一個資料的位置
	//list1.erase(list1.begin(), list1.begin());
	//printL(list1);

	list1.remove(2);           //刪除匹配的元素
	printL(list1);

	list1.reverse();          //反序列表
	printL(list1);
}

2、list 與  迭代器
void func2()
{
	vector<int> v(10);
	for (int i = 0; i < 10; i++)
	{
		v[i] = i;
	}

	// 正向迭代器
	for(vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;

	// 反向迭代器
	for(vector<int>::reverse_iterator it = v.rbegin(); it != v.rend(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;

}

四、優先順序佇列 priority_queue

優先順序佇列內部資料是排完序的,預設是從大到小排序

void func1()
{
	// 優先順序佇列內部資料是排完序的,預設是從大到小排序
	// priority_queue<int> q;
	// priority_queue<int, vector<int>, less<int>> q;
	priority_queue<int, vector<int>, greater<int>> q;
	q.push(10);
	q.push(4);
	q.push(2);
	q.push(65);


	while (!q.empty())
	{
		cout << q.top() << endl;
		q.pop();
	}
}


五、set/multiset

set 是一個集合容器,其中所包含的元素是唯一的,集合中的元素按一定順序排列

元素插入過程是按排序規則插入,所以不能指定插入位置

multiset與set的區別:set支援唯一鍵值,每個元素值只能出現一次;

而multiset中同一值可以出現多次。

set.insert(elem);     //在容器中插入元素。

set.begin();  //返回容器中第一個資料的迭代器。

set.end();  //返回容器中最後一個數據之後的迭代器。

set.rbegin();  //返回容器中倒數第一個元素的迭代器。

set.rend();   //返回容器中倒數最後一個元素的後面的迭代器。

set<int,less<int> >  setIntA;  //該容器是按升序方式排列元素。

set<int,greater<int>> setIntB;   //該容器是按降序方式排列元素。

六、map/multimap

map的使用  容器:存的是鍵  值   對

map 和 set 一樣會自動排序,是以鍵進行排序 ,map 鍵唯一

通過 map 插入有3種方式

void func1()
{
	// 鍵 : int 型別
	// 值 : string 型別
	// 存學生的 id 和 姓名
	map<int, string> m;
	
	// 資料插入:
	// 1、通過 pair 鍵值對插入資料
	m.insert(pair<int, string>(7, "鄭"));
	m.insert(pair<int, string>(8, "王"));

	// 2、通過 make pair 構建鍵值對
	m.insert(make_pair(5, "周"));
	m.insert(make_pair(1, "趙"));

	// 3、通過map型別插入
	m.insert(map<int, string>::value_type(3, "孫"));
	m.insert(map<int, string>::value_type(2, "錢"));

	// 4、通過 [] 方式插入資料,  []不代表陣列下標,[]內部的值是 map 鍵
	m[4] = "李";
	m[6] = "吳";

	printM(m);
}

還有一種方式是通過 [ ] 方式插入資料,[ ] 不代表陣列下標, [ ] 內部的值是 map 鍵  

新增使用者(這個使用者是類呢)

class Student 
{
public:
	Student(int id, string name)
	{
		this->id = id;
		this->name = name;
	}
private:
	int id;
	string name;
};

class UserManager
{
public:
	UserManager()
	{

	}

	// 新增使用者
	void add(int id, string name)
	{
		Student *ps = new Student(id, name);

		m.insert(pair<string, Student*>(name, ps));
	}

	~UserManager()
	{
		map<string, Student*>::iterator it =  m.begin();
		while(it != m.end())
		{
			delete it->second;
			it = m.erase(it);
		}
	}
private:
	// 鍵: 學生名字  值 : 學生   
	map<string, Student*> m;
};

map 迭代器的刪除和查詢
// 迭代器刪除
	m.erase(m.begin());
	printM(m);

	// 通過鍵刪除資料
	cout << "-----------------" << endl;
	m.erase("趙");
	printM(m);


	cout << "-----------------" << endl;
	// 查詢資料: 查詢通過鍵查詢
	map<string, int>::iterator it = m.find("孫");
	if (it != m.end())
	{
		cout << "id = " << it->second << endl;
	}

	pair<map<string, int>::iterator, map<string, int>::iterator> ret = m.equal_range("孫");
	if (ret.first != m.end())
		cout << "id = " << ret.first->second << endl;

	if (ret.second != m.end())
		cout << "id = " << ret.second->second << endl;
}

void func4()
{
	map<string, int> m1;
	m1.insert(make_pair("王", 8));

	// [] 不一定是插入  
	// 如果鍵存在,修改原鍵的值,如果鍵不存在,就建立一個新的鍵值對
	m1["張"] = 10;
}

multimap與map的區別:map支援唯一鍵值,每個鍵只能出現一次;

而multimap中相同鍵可以出現多次。multimap不支援[]操作符。