1. 程式人生 > >VC++中list::list的使用方法總結

VC++中list::list的使用方法總結

本文主題

       這幾天在做影象處理方面的研究,其中有一部分是關於影象分割方面的,影象目標在分割出來之後要做進一步的處理,因此有必要將目標影象的資訊儲存在一個變數裡面,一開始想到的是陣列,但是馬上就發現使用陣列的缺點:陣列長度固定,動態分配記憶體很容易導致錯誤發生。最重要的一點是我要儲存目標影象的每一點的座標值,使用陣列就有點無能為力了。因此到百度、Google大神上面找思路,終於被我發現在c++的標準庫裡面還有這麼一個模板類:list,下面就是對找到的資料的彙總和加工。

vc6自帶的msdn幫助文件的解釋

以下是引自msdn幫助文件(中文是我自己翻譯的,錯誤之處請包涵。):

     The template class describes an object that controls a varying-length sequence of elements of type T. The sequence is stored as a bidirectional linked list of elements, each containing a member of type T.

    本模板類描述了一個物件,這個物件是型別為T的可變長度的序列元素。這個序列採用雙向連結串列的方式儲存每一個元素,其中每一個元素的資料流行都是T。

     The object allocates and frees storage for the sequence it controls through a protected object named allocator, of class A. Such an allocator object must have the same external interface as an object of template class allocator. Note that allocator

is not copied when the object is assigned.

     對序列物件的分配和釋放操作通過一個受保護的物件allocator進行。這樣一個allocator物件必須有相同的外部介面作為一個模板類分配器的物件。注意:當物件被分配之後allocator不能被複制。

    List reallocation occurs when a member function must insert or erase elements of the controlled sequence. In all such cases, only iterators or references that point at erased portions of the controlled sequence become invalid.

    當一個成員要進行insert或者erase操作時,列表的重新分配操作發生。在這種情況下,只有迭代器或者引用所指向的要刪除的物件的指標變為無效。

msdn幫助文件自帶的例子

下面為msdn幫助文件中自帶的一個例子,該例展示瞭如何使用迭代器讀取列表中的元素和進行插入操作。

#include <list>
#include <iostream>
 
using namespace std ;
 
typedef list<int> LISTINT;
 
void main()
{
    int rgTest1[] = {5,6,7};
    int rgTest2[] = {10,11,12};
 
    LISTINT listInt;
    LISTINT listAnother;
    LISTINT::iterator i;
 
    // Insert one at a time
    listInt.insert (listInt.begin(), 2);
    listInt.insert (listInt.begin(), 1);
    listInt.insert (listInt.end(), 3);
 
    // 1 2 3
    for (i = listInt.begin(); i != listInt.end(); ++i)
        cout << *i << " ";
    cout << endl;
 
    // Insert 3 fours
    listInt.insert (listInt.end(), 3, 4);
 
    // 1 2 3 4 4 4
    for (i = listInt.begin(); i != listInt.end(); ++i)
        cout << *i << " ";
    cout << endl;
 
    // Insert an array in there
    listInt.insert (listInt.end(), rgTest1, rgTest1 + 3);
 
    // 1 2 3 4 4 4 5 6 7
    for (i = listInt.begin(); i != listInt.end(); ++i)
        cout << *i << " ";
    cout << endl;
 
    // Insert another LISTINT
    listAnother.insert (listAnother.begin(), rgTest2, rgTest2+3);
    listInt.insert (listInt.end(), listAnother.begin(), listAnother.end());
 
    // 1 2 3 4 4 4 5 6 7 10 11 12
    for (i = listInt.begin(); i != listInt.end(); ++i)
        cout << *i << " ";
    cout << endl;
}
 
 
Program Output is:
 
1 2 3
1 2 3 4 4 4
1 2 3 4 4 4 5 6 7
1 2 3 4 4 4 5 6 7 10 11 12

list::list模板類的主要函式介紹

assign()  //給list賦值
back() //返回最後一個元素
begin() //返回指向第一個元素的迭代器
clear() //刪除所有元素
empty() //如果list是空的則返回true 
end() //返回末尾的迭代器
erase() //刪除一個元素
front() //返回第一個元素
get_allocator() //返回list的配置器
insert() //插入一個元素到list中
max_size() //返回list能容納的最大元素數量
merge() //合併兩個list 
pop_back() //刪除最後一個元素
pop_front() //刪除第一個元素
push_back() //在list的末尾新增一個元素
push_front() //在list的頭部新增一個元素
rbegin() //返回指向第一個元素的逆向迭代器
remove_if() //按指定條件刪除元素
remove() //從list刪除元素
rend() //指向list末尾的逆向迭代器
resize() //改變list的大小
reverse() //把list的元素倒轉
size() //返回list中的元素個數
sort() //給list排序
splice() //合併兩個list 
swap() //交換兩個list 
unique() //刪除list中重複的元素

常用的操作主要是有插入操作、刪除操作。list為實現頭尾高效的插入和刪除操作而提供了大多數的支援函式,而對於隨機訪問函式,則只能從頭部或者尾部進行遍歷操作。

關於remove和erase函式

上面的介紹中關於插入等等操作都有幫助的例子,但是對於刪除函式,這個需要有一些注意的地方。下面請看例子:

#include <iostream>
#include <list>
#include <numeric>
#include <algorithm>
using namespace std;
//建立一個list容器的例項LISTINT
typedef list<int> TESTINT;
 
void main()
{
  //使用TESTINT建立一個list型別的物件
  TESTINT test;
  //使用TESTINT建立一個迭代器物件
  TESTINT:iterator i; 
   //從前面向listOne容器中新增資料
  test.push_front (2);
  test.push_front (1);
  //從後面向listOne容器中新增資料
  test.push_back (3);
  test.push_back (4);
  //從列表中刪除一個元素
  i = test.begin();
  while(i != test.end())
  {
    int tmp = *i;
    if(tmp == 2){
      test.erase(i++);//在這裡要是指標前進1個,否則迭代器失效
    }else{
      i++;
    }  
  }
}

 

總結

      在使用list的時候不能使用隨機訪問的方式,只能按照迭代的方式進行訪問,這樣的話在進行刪除操作的時候就可能會出現某一次刪除操作之後指標沒有指向下一個有效的元素而導致迭代器失效。因此,在進行刪除操作時候最好使用while的方式,使用for迴圈如果控制不好,可能會導致迭代器失效。

     使用模版類可以極大的提高程式設計的效率,想想之前為了實現每個目標區域畫素點的存取操作而使用這個方法都沒有很好的解決問題,真後悔沒有足夠的知識積累,在此記錄下來,共勉之。

附件

下面的資料是在學習list模版類中找到的,以下內容均來自網際網路。

C++ Lists(連結串列)

Lists將元素按順序儲存在連結串列中. 與 向量(vectors)相比, 它允許快速的插入和刪除,但是隨機訪問卻比較慢.

assign() 給list賦值
back() 返回最後一個元素
begin() 返回指向第一個元素的迭代器
clear() 刪除所有元素
empty() 如果list是空的則返回true 
end() 返回末尾的迭代器
erase() 刪除一個元素
front() 返回第一個元素
get_allocator() 返回list的配置器
insert() 插入一個元素到list中
max_size() 返回list能容納的最大元素數量
merge() 合併兩個list 
pop_back() 刪除最後一個元素
pop_front() 刪除第一個元素
push_back() 在list的末尾新增一個元素
push_front() 在list的頭部新增一個元素
rbegin() 返回指向第一個元素的逆向迭代器
remove() 從list刪除元素
remove_if() 按指定條件刪除元素
rend() 指向list末尾的逆向迭代器
resize() 改變list的大小
reverse() 把list的元素倒轉
size() 返回list中的元素個數
sort() 給list排序
splice() 合併兩個list 
swap() 交換兩個list 
unique() 刪除list中重複的元素

List用法例項:

#include <iostream>
#include <list>
#include <numeric>
#include <algorithm>

using namespace std;

//建立一個list容器的例項LISTINT
typedef list<int> LISTINT;

//建立一個list容器的例項LISTCHAR
typedef list<char> LISTCHAR;

void main(void)
{
    //--------------------------
    //用list容器處理整型資料
    //--------------------------
    //用LISTINT建立一個名為listOne的list物件
    LISTINT listOne;
    //宣告i為迭代器
    LISTINT::iterator i;

    //從前面向listOne容器中新增資料
    listOne.push_front (2);
    listOne.push_front (1);

    //從後面向listOne容器中新增資料
    listOne.push_back (3);
    listOne.push_back (4);

    //從前向後顯示listOne中的資料
    cout<<"listOne.begin()--- listOne.end():"<<endl;
    for (i = listOne.begin(); i != listOne.end(); ++i)
        cout << *i << " ";
    cout << endl;

    //從後向後顯示listOne中的資料
LISTINT::reverse_iterator ir;
    cout<<"listOne.rbegin()---listOne.rend():"<<endl;
    for (ir =listOne.rbegin(); ir!=listOne.rend();ir++) {
        cout << *ir << " ";
    }
    cout << endl;

    //使用STL的accumulate(累加)演算法
    int result = accumulate(listOne.begin(), listOne.end(),0);
    cout<<"Sum="<<result<<endl;
    cout<<"------------------"<<endl;

    //--------------------------
    //用list容器處理字元型資料
    //--------------------------

    //用LISTCHAR建立一個名為listOne的list物件
    LISTCHAR listTwo;
    //宣告i為迭代器
    LISTCHAR::iterator j;

    //從前面向listTwo容器中新增資料
    listTwo.push_front ('A');
    listTwo.push_front ('B');

    //從後面向listTwo容器中新增資料
    listTwo.push_back ('x');
    listTwo.push_back ('y');

    //從前向後顯示listTwo中的資料
    cout<<"listTwo.begin()---listTwo.end():"<<endl;
    for (j = listTwo.begin(); j != listTwo.end(); ++j)
        cout << char(*j) << " ";
    cout << endl;

    //使用STL的max_element演算法求listTwo中的最大元素並顯示
    j=max_element(listTwo.begin(),listTwo.end());
    cout << "The maximum element in listTwo is: "<<char(*j)<<endl;
}

#include <iostream>
#include <list>

using namespace std;
typedef list<int> INTLIST;

//從前向後顯示list佇列的全部元素
void put_list(INTLIST list, char *name)
{
    INTLIST::iterator plist;

    cout << "The contents of " << name << " : ";
    for(plist = list.begin(); plist != list.end(); plist++)
        cout << *plist << " ";
    cout<<endl;
}

//測試list容器的功能
void main(void)
{
//list1物件初始為空
    INTLIST list1;   
    //list2物件最初有10個值為6的元素
    INTLIST list2(10,6); 
    //list3物件最初有3個值為6的元素
    INTLIST list3(list2.begin(),--list2.end());

    //宣告一個名為i的雙向迭代器
    INTLIST::iterator i;

    //從前向後顯示各list物件的元素
    put_list(list1,"list1");
    put_list(list2,"list2");
    put_list(list3,"list3");
//從list1序列後面新增兩個元素
list1.push_back(2);
list1.push_back(4);
cout<<"list1.push_back(2) and list1.push_back(4):"<<endl;
    put_list(list1,"list1");

//從list1序列前面新增兩個元素
list1.push_front(5);
list1.push_front(7);
cout<<"list1.push_front(5) and list1.push_front(7):"<<endl;
    put_list(list1,"list1");

//在list1序列中間插入資料
list1.insert(++list1.begin(),3,9);
cout<<"list1.insert(list1.begin()+1,3,9):"<<endl;
    put_list(list1,"list1");

//測試引用類函式
cout<<"list1.front()="<<list1.front()<<endl;
cout<<"list1.back()="<<list1.back()<<endl;

//從list1序列的前後各移去一個元素
list1.pop_front();
list1.pop_back();
cout<<"list1.pop_front() and list1.pop_back():"<<endl;
    put_list(list1,"list1");

//清除list1中的第2個元素
list1.erase(++list1.begin());
cout<<"list1.erase(++list1.begin()):"<<endl;
    put_list(list1,"list1");

//對list2賦值並顯示
list2.assign(8,1);
cout<<"list2.assign(8,1):"<<endl;
    put_list(list2,"list2");

//顯示序列的狀態資訊
cout<<"list1.max_size(): "<<list1.max_size()<<endl;
cout<<"list1.size(): "<<list1.size()<<endl;
cout<<"list1.empty(): "<<list1.empty()<<endl;

//list序列容器的運算
    put_list(list1,"list1");
    put_list(list3,"list3");
cout<<"list1>list3: "<<(list1>list3)<<endl;
cout<<"list1<list3: "<<(list1<list3)<<endl;

//對list1容器排序
list1.sort();
    put_list(list1,"list1");
//結合處理
list1.splice(++list1.begin(), list3);
    put_list(list1,"list1");
    put_list(list3,"list3"); 
}

補充:STL標準函式find進行vector list連結串列查詢

#include <vector>
#include <algorithm>
#include <iostream>

class example
{
public:
example(int val)
{
i = val;
}

bool operator==(example const & rhs)
{
return (i == rhs.i) ? true : false;
}

private:
int i;
};
using namespace std;
int main(void)
{
vector<example> ve;
ve.push_back(1);
vector<example>::iterator it;
example elem(1);
it = find(ve.begin(), ve.end(), elem);
cout<<boolalpha<<(*it == elem);
}

C++中的vector使用範例

一、概述

vector是C++標準模板庫中的部分內容,它是一個多功能的,能夠操作多種資料結構和演算法的模板類和函式庫。vector是一個容器,它能夠存放各種型別的物件,簡單地說,vector是一個能夠存放任意型別的動態陣列,可以動態改變大小。

例如:

// c語言風格

int myHouse[100] ;

// 採用vector

vector<int> vecMyHouse(100);

當如上定義後,vecMyHouse就可以存放100個int型的資料了。

1. 它可以像普通陣列一樣訪問

eg: vecMyHouse[50] = 1024;

2. 你可以順序地向容器中填充資料

eg:int i =0 ;

for( ;i< 25; i++ )

{

vecMyHouse.push_back(1);

}

3. 它還可以動態地改變它的大小,通過下面這條語句實現

// 將容器的大小改為400,這樣容器中就可以容納400個int型資料了

eg:vecMyHouse.resize(400);

4. 你也可以在容器中裝入自定義的資料型別

eg:

// 自定義一個class

class Cmyclass

{

};

// 定義一個存放class的容器

vector<Cmyclass> vecMyHouse;

5. 你可以在定義容器時為它賦初值

// 定義一個容納100個int型資料的容器,初值賦為0

vector<int> vecMyHouse(100,0);

6. 你可以把一個容器的物件賦值給另外一個容器

eg:

// 定義一個容納100個int型資料的容器,初值賦為0

vector<int> vecMyHouse(100,0);

// 定義一個新的容器,內容與上述容器一樣

vector<int> myVec ;

myVec = vecMyHouse;

二、 以上是vector容器的簡單介紹,下面將詳細介紹它的其他功能:

1. 為了使用vector,必須在你的標頭檔案中包含下面的程式碼:

#include <vector>

2. vector屬於std命名域的,因此需要通過命名限定,可以在檔案開頭加上

using std::vector;

或者

using namespace std;

或者直接在使用vector的程式碼前加字首

eg:

std::vector<int> myHouse;

3. vector提供如下函式或操作:

下面列舉了部分常用的功能

// 定義一個vector

std::vector<int> c;

// 可以使用的功能

c.clear() 移除容器中所有資料。

c.empty() 判斷容器是否為空。

c.erase(pos) 刪除pos位置的資料

c.erase(beg,end) 刪除[beg,end)區間的資料

c.front() 傳回第一個資料。

c.insert(pos,elem) 在pos位置插入一個elem拷貝

c.pop_back() 刪除最後一個數據。

c.push_back(elem) 在尾部加入一個數據。

c.resize(num) 重新設定該容器的大小

c.size() 回容器中實際資料的個數。

c.begin() 返回指向容器第一個元素的迭代器

c.end() 返回指向容器最後一個元素的迭代器

三、下面描述一下什麼是迭代器

迭代器相當於指標,例如:

// 對於變數而言,使用指標指向對應的變數

// 以後就可以使用 * 加指標來操作該變量了

int a = 10;

int *p;

p = &a;

// 使用指標操作該變數

eg: *p = 11; // 操作後a變為 11

// 對於容器,使用迭代器操作容器中對應位置的值

// 當迭代器指向了容器中的某位置,則可以使用 * 加迭代器操作該位置了

// 定義一個vector

std::vector<int> myVec;

//新增10個元素

for(int j =0 ; j<10 ; j++)

{

myVec.push_back(j);

}

// 定義一個迭代器

std::vector<int>::iterator p;

// 指向容器的首個元素

p = myVec.begin();

// 移動到下一個元素

p ++;

// 修改該元素賦值

*p = 20 ; //< 則myVec容器中的第二個值被修改為了20

// 迴圈掃描迭代器,改變所有的值

p = myVec.begin();

for( ; p!= myVec.end(); p++ )

{

*p = 50;

}

以上簡單講述了vector的用法,僅供入門之用,謝謝。

-------------------------------------------------------------------------------------

1.vector 的資料的存入和輸出:

#include<stdio.h>

#include<vector>

#include <iostream>

using namespace std;

void main()

{

int i = 0;

vector<int> v;

for( i = 0; i < 10; i++ )

{

v.push_back( i );//把元素一個一個存入到vector中

}

對存入的資料清空

for( i = 0; i < v.size(); i++ )//v.size() 表示vector存入元素的個數

{

cout << v[ i ] << " "; //把每個元素顯示出來

}

cont << endl;

}

注:你也可以用v.begin()和v.end() 來得到vector開始的和結束的元素地址的指標位置。你也可以這樣做:

vector<int>::iterator iter;

for( iter = v.begin(); iter != v.end(); iter++ )

{

cout << *iter << endl;

}

2. 對於二維vector的定義。

1)定義一個10個vector元素,並對每個vector符值1-10。

#include<stdio.h>

#include<vector>

#include <iostream>

using namespace std;

void main()

{

int i = 0, j = 0;

//定義一個二維的動態陣列,有10行,每一行是一個用一個vector儲存這一行的資料。

所以每一行的長度是可以變化的。之所以用到vector<int>(0)是對vector初始化,否則不能對vector存入元素。

vector< vector<int> > Array( 10, vector<int>(0) );

for( j = 0; j < 10; j++ )

{

for ( i = 0; i < 9; i++ )

{

Array[ j ].push_back( i );

}

}

for( j = 0; j < 10; j++ )

{

for( i = 0; i < Array[ j ].size(); i++ )

{

cout << Array[ j ][ i ] << " ";

}

cout<< endl;

}

}

2)定義一個行列都是變化的陣列。

#include<stdio.h>

#include<vector>

#include <iostream>

using namespace std;

void main()

{

int i = 0, j = 0;

vector< vector<int> > Array;

vector< int > line;

for( j = 0; j < 10; j++ )

{

Array.push_back( line );//要對每一個vector初始化,否則不能存入元素。

for ( i = 0; i < 9; i++ )

{

Array[ j ].push_back( i );

}

}

for( j = 0; j < 10; j++ )

{

for( i = 0; i < Array[ j ].size(); i++ )

{

cout << Array[ j ][ i ] << " ";

}

cout<< endl;

}

}

使用 vettor erase 指定元素

#include "iostream"

#include "vector"

using namespace std;

int main()

{

vector<int> arr;

arr.push_back(6);

arr.push_back(8);

arr.push_back(3);

arr.push_back(8);

for(vector<int>::iterator it=arr.begin(); it!=arr.end(); )

{

if(* it == 8)

{

it = arr.erase(it);

}

else

{

++it;

}

}

cout << "After remove 8:\n";

for(vector<int>::iterator it = arr.begin(); it < arr.end(); ++it)

{

cout << * it << " ";

}

cout << endl;

}


如果覺得本文好的話就分享給你的朋友把!