C++STL學習筆記

C++STL泛型編程

ANSI C++中包含了一個C++ STL(Standard Template Library),即C++標準模板庫,又稱C++泛型庫,它在std命名空間中定義了常

用的數據結構和算法,使用起來很方便。

STL提供三種類型的組件:容器、迭代器、算法,它們都支持泛型程序設計標準。

容器主要有兩類:順序容器和關聯容器。順序容器和關聯容器又稱爲一級容器

順序容器:順序容器表示線性數據結構,包括vector、list、deque

關聯容器:關聯容器是非線性數據結構,可快速定位容器中的數據,包括set、multiset、map、multimap

容器適配器:容器適配器是順序容器的受限版本,用於處理特殊情況,包括stack、queue、priority_queue

迭代器的作用是遍歷容器。

STL算法包含四類:排序算法、不可變序算法、變序性算法、數值算法

STL容器類及其頭文件:

vector <vector>  直接訪問任意元素,快速插入、刪除尾部元素

duque <deque> 直接訪問任意元素,快速插入、刪除頭部和尾部元素

list    <list>  快速插入、刪除任意位置元素

set   <set>  快速查詢元素,無重複關鍵字

multiset  <set>  與set相同,但允許重複關鍵字

map  <map>  關鍵字/值對映射,不允許重複關鍵字,使用關鍵字快速查詢元素

multimap  <map>  與map相同,但允許重複關鍵字

stack  <stack>  後進先出容器

queue  <queue>  先進先出容器

priority_queue  <queue>  高優先級元素先刪除

STL迭代器:

每個容器都有自己的迭代器類型,函數begin()返回指向容器首元素的迭代器,函數end()返回指向容器尾元素之後位置的迭代器。

迭代器的類型:

1.輸入迭代器:用於從容器中讀取元素,每一步只能沿向前的方向移動一個元素;

2.輸出迭代器:用於從容器中寫入元素,每一步只能沿向前的方向移動一個元素;

3.向前迭代器:包含輸入輸出迭代器的所有功能,既支持讀操作又支持寫操作;

4.雙向迭代器:包含向前迭代器的所有功能,還有向後移動的能力,每一步可以自由選擇向前還是向後移動;

5.隨機訪問迭代器:好漢雙向迭代器的所有功能,具有按任意順序訪問任意元素的能力,即能向前或向後跳過任意多個元素

預定義的迭代器:

STL容器使用關鍵字來預定義迭代器。STL中預定義的迭代器有iterator、const_iterator、reverse_iterator和const_reverse_iterator。

每個一級容器中讀定義了這些迭代器。

由於迭代器是容器類中用typedef定義的,因此,需要用作用域解析運算符來引用它們。

例如:vector<int>::inerator  p1 =  intVector.begin()

const_iterator與iterator類似,差別在於不能通過const_iterator修改元素值,即const_iterator是隻讀的。

reverse_iterator:反向迭代器。

vector<int>::reverse_iterator p1 = intVector.rbegin();   函數rbegin()返回一個指向容器尾元素的reverse_iterator,函數rend()返回一個

指向容器首元素(逆序中)下一個位置的reverse_iterator

istream_iterator和ostream_iterator

 這兩個迭代器用於序列化元素,既可以用它們序列化容器中的元素,也可以用於序列化輸入/輸出流中的元素。

一個例子:使用istream_iterator從輸入流中讀取數據,以及使用ostream_iterator向輸出流寫入數據。

#include <iostream>
#include <iterator>
#include <cmath>
using namespace std;

int main()
{
	cout<<"please input three numbers:";
	istream_iterator<int> inputIterator(cin);	//輸入迭代器
	ostream_iterator<int> outputIterator(cout);	//輸出迭代器

	int number1 = *inputIterator;	//解引用,從cin讀取一個整數
	inputIterator++;		//將迭代器移動到輸入流中下一個數據
	int number2 = *inputIterator;
	inputIterator++;
	int number3 = *inputIterator;
	cout<<"the largest number is:";
	*outputIterator = max(max(number1, number2), number3);	//解引用,向cout寫入了一個整數
	return 0;
}


順序容器:

STL提供了三個順序容器:vector、list、deque。deque和vector都是用數組實現的,list是用鏈表實現的。

vector:如果數據以附加方式加入到vector(即加入到尾部),那麼vector具有很好的效率,但是在其他任意位置(除了尾部)插入和刪除

元素,vector效率則很低。

deque:(double-ended queue)雙端隊列,與向量很像,在其兩端進行插入操作則效率很高,但是在內部進行插入和刪除操作,效率

還是很低。

list:適合於需要頻繁在容器中間進行插入和刪除操作的應用。

順序容器中的共同函數:

assign(n, elem)    將指定元素的n份拷貝加入到容器中

assign(beg, end)   賦值從迭代器beg和end之間的元素

push_back(elem)   將元素附加到容器

pop_back()   刪除容器尾元素

front()    返回容器首元素

back()   返回容器尾元素

insert(position, elem)   將元素插入到容器的指定位置

1.vector:

vector的構造函數:

vector(n, element)  構造一個向量,填入指定元素的n份拷貝

vector(beg, end)  構造一個向量,用迭代器beg至end之間的 元素進行初始化

vector(size)   構造一個指定規模的向量

  一個使用vector的例子:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
	double values[] = {1,2,3,4,5,6,7};
	vector<double> doubleVector(values, values + 7);	//構造一個響亮

	for(vector<double>::iterator it = doubleVector.begin(); it != doubleVector.end(); it++)
	{
		cout<<*it<<" ";
	}
	cout<<"\n";

	doubleVector.assign(5, 9.9);	//assgn()函數會清除容器中的所有元素
	for(vector<double>::iterator it = doubleVector.begin(); it != doubleVector.end(); it++)
	{
		cout<<*it<<" ";
	}
	cout<<"\n";
	return 0;
}

2.deque:

雙端隊列在兩端進行插入和刪除操作都是很高效的。

deque的兩個特有函數:

push_front(element): 將元素插入到隊首

pop_front() : 刪除隊首元素

3.list:

list是作爲雙向鏈表實現的,因此,可高效地在列表的任意位置進行插入和刪除操作。

list的兩個特有函數:

push_front(element): 將元素插入到列表頭

pop_front() : 刪除列表頭元素

remove(element):刪除列表中所有與指定元素相等的元素

remove_if(oper):  刪除所有令oper(element)爲真的元素

splice(pos, list2): 將list2中所有元素移動到此列表指定位置之前,調用此函數後,list2變爲空

splice(pos1, list2, pos2): 將list2中從pos2開始的元素移動到本列表pos1之前,調用此函數後,list2變爲空

splice(pos1, list2, beg, end): 將list2中從beg至end之間的元素移動到本列表pos1之前,調用此函數後,list2變爲空

sort(): 將列表按升序排序

sort(oper): 排序列表,排序標準由oper指定

merge(list2): 假定本列表和list2都已排序,將list2合併至本列表,調用此函數後,list2變爲空

merge(list2, oper): 假定本列表和list2都已排序,按oper指出的排序標準將list2合併至本列表

reverse():  反轉本列表

vector和deque的迭代器都是隨機訪問迭代器,而list的迭代器是雙向迭代器。因此,不能用下標運算符[ ]訪問列表中的元素。

list、set、multiset、map和multimap支持雙向迭代器;

stack、queue、priority_queue不支持迭代器。


關聯容器:

STL提供了4個關聯容器:set、multiset、map、multimap。這些容器提供了通過關鍵字快速存儲和訪問數據元素的能力。關聯容器

中的數據元素根據某種排序標準進行了排序,默認情況下,使用<運算符進行排序。、

關聯容器的共同函數:

find(key): 搜索容器中具有指定關鍵字的元素,返回指向此元素的迭代器

lower_bound(key): 搜索容器中具有指定關鍵字的第一個元素,返回指向此元素的迭代器

upper_bound(key): 搜索容器中具有指定關鍵字的最後一個元素,返回指向此元素之後位置的迭代器

count(key): 返回容器中具有指定關鍵字的元素的數目。

默認情況下,集合中的元素是按升序存放的,爲了指定降序方式,可以這樣寫:

multiset<int, greater<int>>set1(values, values + 3);  greater<int> 之後的空格是必須的,如果缺少這個空格,C++會將其與>>運算

符混淆。

greater<int>和less<int>,下面看它們的定義:

		// TEMPLATE STRUCT greater
template<class _Ty>
	struct greater
		: public binary_function<_Ty, _Ty, bool>
	{	// functor for operator>
	bool operator()(const _Ty& _Left, const _Ty& _Right) const
		{	// apply operator> to operands
		return (_Left > _Right);
		}
	};

		// TEMPLATE STRUCT less
template<class _Ty>
	struct less
		: public binary_function<_Ty, _Ty, bool>
	{	// functor for operator<
	bool operator()(const _Ty& _Left, const _Ty& _Right) const
		{	// apply operator< to operands
		return (_Left < _Right);
		}
	};

 

set和multimap的用法的例子

#include <iostream>
#include <set>
using namespace std;

int main()
{
	int values[] = {1, 8, 2, 1, 3, 1, 2, 4, 5};
	set<int> set1(values, values + 8);
	set<int>::iterator it;
	//multiset<int> set1(values, values + 8);
	//multiset<int>::iterator it;
	cout<<"set:";
	for(it = set1.begin(); it != set1.end(); it++)
	{
		cout<<*it<<" ";
	}
	cout<<endl;
	//it = set1.lower_bound(2);
	it = set1.upper_bound(3);
	cout<<*it<<endl;
	return 0;
}

map的用法的例子:

#include <iostream>
#include <map>
#include <String>
using namespace std;

int main()
{
	map<int, string> map1;
	map1.insert(map<int, string>::value_type(001, "hello"));	//添加元素
	map1.insert(map<int, string>::value_type(002, "my"));
	map1.insert(map<int, string>::value_type(003, "love"));
	map<int, string>::iterator it = map1.begin();
	for(; it != map1.end(); it++)
	{
		cout<<it->first<<" "<<it->second<<endl;
	}
}

 

容器適配器:

STL提供了三種容器適配器:stack、queue、priority_queue。這些容器稱爲適配器(adapter),因爲它們是由順序容器變化而來,用

於處理特殊情況。

1.stack:

棧是一種後進先出的容器,可以選擇vector、deque、或list來構造一個stack對象。默認情況下,stack基於deque實現。

棧支持的函數:

push(element): 將元素添加到棧頂

pop():  刪除棧頂元素

top():   返回棧頂元素,不刪除它

size():  返回棧的大小

empty(): 若棧空返回真

一個使用stack的例子:

#include <iostream>
#include <stack>
#include <vector>
using namespace std;

template<typename T>
void printStack(T &s)
{
	while(!s.empty())
	{
		cout<<s.top()<<" ";
		s.pop();
	}
	cout<<"\n";
}

int main()
{
	stack<int> s1;
	stack<int, vector<int> >s2;
	for(int i = 0; i < 8; i++)
	{
		s1.push(i);		//入棧
		s2.push(i);
	}
	cout<<"s1:";
	printStack(s1);
	cout<<"s2:";
	printStack(s2);
	return 0;
}

 

2.queue:

隊列是一種先進先出容器,可以選擇deque或list來構造一個queue對象。默認情況下,queue用deque實現。

隊列支持的函數:

push(): 將元素插入到隊尾

pop(): 刪除隊首元素

front():  返回隊首元素,但不刪除它

back():  返回隊尾元素,但不刪除它

size():  返回隊列的大小

empty(): 若隊列空則返回真

一個使用queue的例子:

#include <iostream>
#include <queue>
#include <list>
using namespace std;

template<typename T>
void printQueue(T &q)
{
	while(!q.empty())
	{
		cout<<q.front()<<" ";
		q.pop();
	}
	cout<<"\n";
}

int main()
{
	queue<int> q1;
	queue<int, list<int> > q2;
	for(int i = 0; i < 8; i++)
	{
		q1.push(i);
		q2.push(i);
	}
	cout<<"q1:";
	printQueue(q1);
	cout<<"q2:";
	printQueue(q2);
	return 0;
}

 

3.priority_queue:

在優先隊列中,每個元素都被賦予一個優先級,優先級最高的元素首先被訪問/刪除,業就是說,優先隊列是最高優先級最先出的。

可以選擇vector或deque來構造一個priority_queue,默認是用vector來實現的,priority_queue類支持的函數與stack類相同。

priority_queue類支持的函數與stack類相同。

一個使用priority_queue的例子:

#include <iostream>
#include <queue>
#include <deque>
using namespace std;

template<typename T>
void printPQueue(T &pq)
{
	while(!pq.empty())
	{
		cout<<pq.top()<<" ";
		pq.pop();
	}
	cout<<"\n";
}

int main()
{
	priority_queue<int> pq1;
	priority_queue<int, deque<int> > pq2;

	for(int i = 0; i < 8; i++)
	{
		pq1.push(i);
		pq2.push(i);
	}
	cout<<"pq1:";
	printPQueue(pq1);
	cout<<"pq2:";
	printPQueue(pq2);

	return 0;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章