天天看點

STL學習--vector的學習

版權聲明:您好,轉載請留下本人部落格的位址,謝謝 https://blog.csdn.net/hongbochen1223/article/details/45069675

(一):學習目标:

1:模闆,包括函數模闆和類模闆

2:容器及其分類,以容器中的資料結構

3:容器vector和疊代器的具體用法

(二):學習

1:函數模闆

/**
 * 學習模闆函數
 */
int max(int a,int b){
 return a > b?a:b;
}

float max(float a,float b){
 return a > b?a:b;
}

char max(char a,char b){
 return a > b?a : b;
}           

但是類型是比較多的,是以每一個類型都要寫一個這樣的函數的話,肯定是不行的。是以就有了模闆函數。

下面就是模闆函數:

/**
 * 上面函數的模闆函數
 */
template<typename T>  //或者是 template<class T>
T max(T a,T b){
 return a > b?a : b;
}           

T代表傳入的類型

那麼如何調用模闆函數呢?

下面就是調用的代碼:

注意:由于在STL裡面max已經被定義了,是以在這裡換一個名稱

下面就是這個的定義和調用的過程

/*
 * test.cpp
 *
 *  Created on: 2015年4月15日
 *      Author: hongb_000
 */
#include <iostream>

using namespace std;

///**
// * 學習模闆函數
// */
//int UIP_Max(int a,int b){
//  return a > b?a:b;
//}
//
//float UIP_Max(float a,float b){
//  return a > b?a:b;
//}
//
//char UIP_Max(char a,char b){
//  return a > b?a : b;
//}

/**
 * 上面函數的模闆函數
 */

template<typename T>  //或者是 template<class T>
T UIP_Max(T a,T b){
 return a > b?a : b;
}

int main(void)
{
//注意這裡的<int>是不能省略的,這裡表示指定輸入的類型
 int m = UIP_Max<int>(10,20);
 cout << m << endl;

char a = UIP_Max<char>('a','b');
 cout << a << endl;

 return 0;
}
           

模闆函數會在運作過程中根據傳入的類型進行替換相應的類型。是以這就實作了模闆函數的功能。

2:模闆類

現在假設我們有兩個個類:

class IMax{
public:
 IMax(int _a,int _b){
  a = _a;
  b = _b;
 }

 int GetMax(){
  return a>b?a:b;
 }

private:
 int a;
 int b;
};

class FMax{
public:
 FMax(float _a,float _b){
  a = _a;
  b = _b;
 }

 int GetMax(){
  return a>b?a:b;
 }

private:
 float a;
 float b;
};           

這樣遇到的問題和上面遇到的函數的問題是一樣的,這樣就引入了類模闆。

下面我們寫一下類模闆

template <class T> //或者是 template<typename T>
class CMax{
public:
 CMax(T _a,T _b){
  a = _a;
  b = _b;
 }

 T GetMax(){
  return a > b ? a : b;
 }

private:
 T a;
 T b;

};
           

與函數模闆的定義差不多,凡是遇到類型的地方全部用T去替代。

那麼如何使用這個類模闆呢?下面我們來試一下:

//這樣這個地方的<int>也是不能省略的,為了指定類型
 CMax<int> cMax(10,20);
 int p = cMax.GetMax();

 cout << p << endl;           

類模闆就是建立一個通用的類。

注意:

類模闆可以定義多種類型:

template<typename T1,typename T2>           

3:容器的學習

容器是用來存放,管理一組元素的資料集合。

容器的資料結構如下面的圖所示:

容器有序列式的容器和關聯式的容器。

序列式的容器有vector,deque,list

關聯式的容器元素的位置取決于特定的排序的準則,

關聯式的容器有set,multiset等

4:vector的學習

1):vector的簡介

vector是将元素置于一個動态的容器中進行管理,相當于一個動态的數組。

vector可以随機通路内部的資料。

vector尾部的插入和移除元素是比較簡單的,但是在中間是比較複雜的。

2):使用前的準備

#include <vector>
using namespace std;           

3):預設的構造

vector<T> vec;           

例如:

vector<int> vec;  //一個存放int類型的vector容器
vector<float> vec; //一個存放float類型的vector

class CA{};
vector<CA*> vecCA;  //用于存放CA的指針
vector<CA> vec;  //用于存放CA的對象,不過這裡一定要提供拷貝構造函數           

4):vector末尾的添加和移除操作

vector:push_back(ele); //在容器尾部加入一個元素

vector:pop_back(); //移除容器中的最後一個元素

下面是一個測試的例子:

vector<int> vec;
 vec.push_back(1);
  //在vector後面插入一個元素
 vec.push_back(2);
 vec.push_back(3);
 vec.push_back(4);
 vec.push_back(5);
  //将vector的最後一個元素移除

 vec.pop_back();

 for(size_t i = 0;i < vec.size();i++){
  cout << vec.at(i) << "    ";
 }
           

輸出結果為:

1 2 3 4

5):vector資料的存取

vector擷取元素有兩種方式:

1:vec.at(i); //但是i越界的話,會跑出out_of_range一場

2:vec[i] //i越界的話沒有異常抛出,直接報錯

6):對元素的修改

vector可以直接對某一個位置的元素進行修改。

例如:

vce.at(2) = 18;

下面是在剛剛那個例子的基礎上進行調整:

//位置3的元素現在是3,我們把她改成19

vec.at(2) = 19;
 for(size_t i = 0;i < vec.size();i++){
   cout << vec.at(i) << "   ";
 }

 cout << endl;           

則輸出結果為:

1 2 3 4

1 2 19 4

7):通路vector的第一個值和最後一個值

int mFront = vec.front(); //第一個值

int mBack - vec.back(); //最後一個值

同時還可以使用這兩個函數對其中的數值進行修改

例如:

我們想把第一個元素改成88:

vec.front() = 88; //這樣就修改成功了

5:疊代器的學習

疊代器相當于一個指向,指向vector中的元素。

疊代器用來周遊容器中的内容,就像是一個指針,指向容器中的某一個位置。

1):疊代器的類别

第一種:輸入疊代器,隻支援一次周遊

第二種:輸出疊代器,隻支援一遍輸入

第三種:正向疊代器,可以進行多次讀寫

第四種:雙向疊代器:就可以往前多次讀寫,又可以往後多次讀寫

第四種:随機通路疊代器:可以除了讀寫之外,還能讀取和輸入任意位置的内容

2):雙向疊代器支援的操作

it++,++it,it–,–it,*it,itA=itB,itA==itB,itA!=itB

其中list.set,multiset,map,multimap支援雙向疊代器

3):随機通路存儲器

在雙向疊代器的操作基礎上添加加了随機功能

it+=i;it = i;it+i;it[i],itA

vector<int> vecA;
vecA.push_back(1);
vecA.push_back(3);
vecA.push_back(5);
vecA.push_back(7);
vecA.push_back(9);

//注意疊代器的寫法
vector<int>::iterator it = vecA.begin();
cout << *it << endl; //輸出應該就是第一個元素的值1

 ++it;  //但是前++要比後++的效率高,因為前++傳回的是一個引用,後++傳回的是一個值
  cout << *it << endl; //輸出的應該就是3了

it += 3;
cout << *it << endl; //輸出應該就是9了           

當it==vecA.end()的時候,就不能操作*it了,因為現在是最後一個元素的下一個位置

5):使用疊代器進行vector的周遊

/**
  * 使用疊代器進行vector的周遊
  */
 vector<int>::iterator itA = vecA.begin();

 for(;itA != vecA.end();itA++){
  cout << *itA << " ";
 }
           

6):反向疊代器

/**
  * 反向疊代器,逆序輸出
  *
  * 其中的vec.rbegin()指向vector指向最後一個元素
  * vec.rbegin()指向vector的第一個元素的上一個位置
  */
 vector<int>::reverse_iterator rit = vecA.rbegin();

 for(;rit != vecA.rend();rit++){
  cout << *rit << " ";
 }           

7):還有兩個

//第一個:vector<T>::const_iterator
 //第二個:vector<T>::const_reverse_iterator           

是前面講的兩種的隻讀形式。

6:vector帶參數的構造

1):帶疊代器開始和結束的構造

例子:

//參數為疊代器的開始和結束

vector<int> vecB(array,array+5);
 vector<int> vecC(vecA.begin(),vecA.end());           

2):

vector<int> vecD(3,9);  //vector有3個元素,每個元素都是9           

7:vector的指派

1):vector:assign(beg,end); //将(beg,end)區間的資料拷貝給本身。左閉右開

2):vector:assign(n,ele); //n個ele元素

3):vector:swap(vec); //将vec與本身進行互換

8:vector的大小

1):vector:size(); //傳回容器元素的個數,傳回 size_z

2):vector:empty(); //傳回容器是否為空

3):vector:resize(num); //重新指定容器的長度為num

4):vector:resize(num,ele); //重新指定容器的長度,超過部分用ele填充,少的部分删除

例如:

vector<int> vecE;
 vecE.push_back(1);
 vecE.push_back(2);
 vecE.push_back(3);
 //目前vecE有元素1,2,3

 vecE.resize(5);  //現在的元素應該為1,2,3,0,0

 vecE.resize(8,3); //現在的元素應該為1,2,3,0,0,3,3,3

 vecE.resize(2); //現在的元素應該為1,2           

8:vector的插入

1):vector:insert(pos,ele); //在pos位置插入一個ele元素的拷貝,傳回新資料的位址

2):vector:insert(pos,n,ele); //在pos位置插入n個ele元素

3):vector:insert(pos,beg,end): //在pos插入[beg,end)區間的元素

例子:

/**
  * 插入測試
  */
 vector<int> vecF;
 vecF.push_back(1);
 vecF.push_back(3);
 vecF.push_back(5);
 vecF.push_back(9);

 vector<int> vecG;
 vecG.push_back(2);
 vecG.push_back(4);
 vecG.push_back(6);
 vecG.push_back(8);

 vecF.insert(vecF.begin(),11); //現在vecF中的元素應該是11,1,3,5,7,9
 vecF.insert(vecF.begin()+1,2,33); //現在vecF中的元素應該是 11,33,33,1,3,5,9

 //執行之後的元素應該是2,4,6,8,11,33,33,1,3,5,9
 vecF.insert(vecF.begin(),vecG.begin(),vecG.end());           

9:vector的元素删除

1):vec.clear(); //移除容器中的所有的元素

2):vec.erase(beg,end): //删除[beg,end)區間的元素

3):vec.erase(pos); //删除pos位置的元素,傳回下一個資料的位置

總結:

通過對小節的學習,基本上了解了vector中的資料結構以及其适用方法,不過還是需要多加練習。

繼續閱讀