1. 程式人生 > >STL list連結串列的用法詳細解析

STL list連結串列的用法詳細解析

本文以List容器為例子,介紹了STL的基本內容,從容器到迭代器,再到普通函式,而且例子豐富,通俗易懂。不失為STL的入門文章,新手不容錯過!

0 前言
1 定義一個list
2 使用list的成員函式push_back和push_front插入一個元素到list中
3 list的成員函式empty()
4 用for迴圈來處理list中的元素
5 用STL的通用演算法for_each來處理list中的元素
6 用STL的通用演算法count_if()來統計list中的元素個數
7 使用count_if()的一個更加複雜的函式物件。
8 使用STL通用演算法find()在list中查詢物件
9 使用STL通用演算法find_if()在list中搜索物件
10 使用STL通用演算法search在list中找一個序列
11 使用list的成員函式sort()排序一個list。
12 用list的成員函式插入元素到list中
13 List 建構函式
14 使用list成員函式從list中刪除元素
15 用list成員函式remove()從list中刪除元素。
16 使用STL通用演算法remove()從list中刪除元素
17 使用STL通用演算法stable_partition()和list成員函式splice()來劃分一個list
18 結論:在field中使用STL
19 參考書目



 
0 前言
 
這篇文章是關於C++語言的一個新的擴充套件——標準模板庫的(Standard Template Library),也叫STL。

當我第一次打算寫一篇關於STL的文章的時候,我不得不承認我當時低估了這個話題的深度和廣度。有很多內容要含蓋,也有很多詳細描述STL的書。因此我重新考慮了一下我原來的想法。我為什麼要寫這篇文章,又為什麼要投稿呢?這會有什麼用呢?有再來一篇關於STL的文章的必要嗎?

當我翻開Musser and Saini的頁時,我看到了程式設計時代在我面前消融。我能看到深夜消失了,目標軟體工程出現了。我看到了可維護的程式碼。一年過去了,我使用STL寫的軟體仍然很容易維護。讓人吃驚的是其他人可以沒有我而維護的很好!

然而,我也記得在一開始的時候很難弄懂那些技術術語。一次,我買了Musser&Saini,每件事都依次出現,但是在那以前我最渴望得到的東西是一些好的例子。

當我開始的時候,作為C++一部分的Stroustrup還沒出來,它覆蓋了STL。
因此我想寫一篇關於一個STL程式設計師的真實生活的文章可能會有用。如果我手上有一些好的例子的話,特別是象這樣的新題目,我會學的更快。

另外一件事是STL應該很好用。因此,理論上說,我們應該可以馬上開始使用STL。
什麼是STL呢?STL就是Standard Template Library,標準模板庫。這可能是一個歷史上最令人興奮的工具的最無聊的術語。從根本上說,STL是一些“容器”的集合,這些“容器”有list,vector,set,map等,STL也是演算法和其他一些元件的集合。這裡的“容器”和演算法的集合指的是世界上很多聰明人很多年的傑作。

STL的目的是標準化元件,這樣你就不用重新開發它們了。你可以僅僅使用這些現成的元件。STL現在是C++的一部分,因此不用額外安裝什麼。它被內建在你的編譯器之內。因為STL的list是一個簡單的容器,所以我打算從它開始介紹STL如何使用。如果你懂得了這個概念,其他的就都沒有問題了。另外,list容器是相當簡單的,我們會看到這一點。

這篇文章中我們將會看到如何定義和初始化一個list,計算它的元素的數量,從一個list裡查詢元素,刪除元素,和一些其他的操作。要作到這些,我們將會討論兩個不同的演算法,STL通用演算法都是可以操作不止一個容器的,而list的成員函式是list容器專有的操作。

這是三類主要的STL元件的簡明綱要。STL容器可以儲存物件,內建物件和類物件。它們會安全的儲存物件,並定義我們能夠操作的這個物件的介面。放在蛋架上的雞蛋不會滾到桌上。它們很安全。因此,在STL容器中的物件也很安全。我知道這個比喻聽起來很老土,但是它很正確。

STL演算法是標準演算法,我們可以把它們應用在那些容器中的物件上。這些演算法都有很著名的執行特性。它們可以給物件排序,刪除它們,給它們記數,比較,找出特殊的物件,把它們合併到另一個容器中,以及執行其他有用的操作。

STL iterator就象是容器中指向物件的指標。STL的演算法使用iterator在容器上進行操作。Iterator設定演算法的邊界,容器的長度,和其他一些事情。舉個例子,有些iterator僅讓演算法讀元素,有一些讓演算法寫元素,有一些則兩者都行。 Iterator也決定在容器中處理的方向。

你可以通過呼叫容器的成員函式begin()來得到一個指向一個容器起始位置的iterator。你可以呼叫一個容器的 end() 函式來得到過去的最後一個值(就是處理停在那的那個值)。

這就是STL所有的東西,容器、演算法、和允許演算法工作在容器中的元素上的iterator。演算法以合適、標準的方法操作物件,並可通過iterator得到容器精確的長度。一旦做了這些,它們就在也不會“跑出邊界”。還有一些其他的對這些核心元件型別有功能性增強的元件,例如函式物件。我們將會看到有關這些的例子,現在 ,我們先來看一看STL的list。

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

1 定義一個list

 
我們可以象這樣來定義一個STL的list:
#include <string>
#include <list>
int main (void)
{
list<string> Milkshakes;
return 0;
}
這就行了,你已經定義了一個list。簡單嗎?list<string> Milkshakes這句是你聲明瞭list<string>模板類的一個例項,然後就是例項化這個類的一個物件。但是我們別急著做這個。在這一步其實你只需要知道你定義了 一個字串的list。你需要包含提供STL list類的標頭檔案。我用gcc 2.7.2在我的Linux上編譯這個測試程式,例如:

g++ test1.cpp -o test1

注意iostream.h這個標頭檔案已經被STL的標頭檔案放棄了。這就是為什麼這個例子中沒有它的原因。

現在我們有了一個list,我們可以看實使用它來裝東西了。我們將把一個字串加到這個list裡。有一個非常 重要的東西叫做list的值型別。值型別就是list中的物件的型別。在這個例子中,這個list的值型別就是字串,string , 這是因為這個list用來放字串。

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

2 使用list的成員函式push_back和push_front插入一個元素到list中

複製程式碼程式碼如下:
#include <string>
#include <list>

int main (void)
{
list<string> Milkshakes;
Milkshakes.push_back("Chocolate");
Milkshakes.push_back("Strawberry");
Milkshakes.push_front("Lime");
Milkshakes.push_front("Vanilla");
return 0;
}

我們現在有個4個字串在list中。list的成員函式push_back()把一個物件放到一個list的後面,而 push_front()把物件放到前面。我通常把一些錯誤資訊push_back()到一個list中去,然後push_front()一個標題到list中, 這樣它就會在這個錯誤訊息以前列印它了。

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

3 list的成員函式empty()

知道一個list是否為空很重要。如果list為空,empty()這個成員函式返回真。 我通常會這樣使用它。通篇程式我都用push_back()來把錯誤訊息放到list中去。然後,通過呼叫empty() 我就可以說出這個程式是否報告了錯誤。如果我定義了一個list來放資訊,一個放警告,一個放嚴重錯誤, 我就可以通過使用empty()輕易的說出到底有那種型別的錯誤發生了。

我可以整理這些list,然後在列印它們之前,用標題來整理它們,或者把它們排序成類。
複製程式碼程式碼如下:
/*
|| Using a list to track and report program messages and status
*/
#include <iostream.h>
#include <string>
#include <list>
int main (void)
{
#define OK 0
#define INFO 1
#define WARNING 2
int return_code;
list<string> InfoMessages;
list<string> WarningMessages;

// during a program these messages are loaded at various points
InfoMessages.push_back("Info: Program started");
// do work...
WarningMessages.push_back("Warning: No Customer records have been found");
// do work...

  return_code = OK;

if  (!InfoMessages.empty()) {  // there were info messages
   InfoMessages.push_front("Informational Messages:");
   // ... print the info messages list, we'll see how later
   return_code = INFO;
}

if  (!WarningMessages.empty()) {   // there were warning messages
   WarningMessages.push_front("Warning Messages:");
   // ... print the warning messages list, we'll see how later
   return_code = WARNING;
}

// If there were no messages say so.
if (InfoMessages.empty() && WarningMessages.empty()) {
   cout << "There were no messages " << endl;
}

return return_code;


4 用for迴圈來處理list中的元素

我們想要遍歷一個list,比如列印一箇中的所有物件來看看list上不同操作的結果。要一個元素一個元素的遍歷一個list, 我們可以這樣做:
複製程式碼程式碼如下:
/*
|| How to print the contents of a simple STL list. Whew!
*/
#include <iostream.h>
#include <string>
#include <list>

int main (void)
{
list<string> Milkshakes;
list<string>::iterator MilkshakeIterator;

Milkshakes.push_back("Chocolate");
Milkshakes.push_back("Strawberry");
Milkshakes.push_front("Lime");
Milkshakes.push_front("Vanilla");

// print the milkshakes
Milkshakes.push_front("The Milkshake Menu");
Milkshakes.push_back("*** Thats the end ***");
for (MilkshakeIterator=Milkshakes.begin();
   MilkshakeIterator!=Milkshakes.end();
++MilkshakeIterator)
{
  // dereference the iterator to get the element
  cout << *MilkshakeIterator << endl;
}


這個程式定義了一個iterator,MilkshakeIterator。我們把它指向了這個list的第一個元素。 這可以呼叫Milkshakes.begin()來作到,它會返回一個指向list開頭的iterator。然後我們把它和Milkshakes.end()的 返回值來做比較,當我們到了那兒的時候就停下來。

容器的end()函式會返回一個指向容器的最後一個位置的iterator。當我們到了那裡,就停止操作。 我們不能不理容器的end()函式的返回值。我們僅知道它意味著已經處理到了這個容器的末尾,應該停止處理了。 所有的STL容器都要這樣做。

在上面的例子中,每一次執行for迴圈,我們就重複引用iterator來得到我們列印的字串。

在STL程式設計中,我們在每個演算法中都使用一個或多個iterator。我們使用它們來存取容器中的物件。 要存取一個給定的物件,我們把一個iterator指向它,然後間接引用這個iterator。

這個list容器,就象你所想的,它不支援在iterator加一個數來指向隔一個的物件。 就是說,我們不能用Milkshakes.begin()+2來指向list中的第三個物件,因為STL的list是以雙鏈的list來實現的, 它不支援隨機存取。vector和deque(向量和雙端佇列)和一些其他的STL的容器可以支援隨機存取。

上面的程式打印出了list中的內容。任何人讀了它都能馬上明白它是怎麼工作的。它使用標準的iterator和標準 的list容器。沒有多少程式設計師依賴它裡面裝的東西, 僅僅是標準的C++。這是一個向前的重要步驟。這個例子使用STL使我們的軟體更加標準。

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

5 用STL的通用演算法for_each來處理list中的元素

使用STL list和 iterator,我們要初始化、比較和給iterator增量來遍歷這個容器。STL通用的for_each 演算法能夠減輕我們的工作。
複製程式碼程式碼如下:
/*
|| How to print a simple STL list MkII
*/
#include <iostream.h>
#include <string>
#include <list>
#include <algorithm>

PrintIt (string& StringToPrint)
{
cout << StringToPrint << endl;
}

int main (void)
{
list<string> FruitAndVegetables;
FruitAndVegetables.push_back("carrot");
FruitAndVegetables.push_back("pumpkin");
FruitAndVegetables.push_back("potato");
FruitAndVegetables.push_front("apple");
FruitAndVegetables.push_front("pineapple");

for_each  (FruitAndVegetables.begin(), FruitAndVegetables.end(), PrintIt);
}

在這個程式中我們使用STL的通用演算法for_each()來遍歷一個iterator的範圍,然後呼叫PrintIt()來處理每個物件。 我們不需要初始化、比較和給iterator增量。for_each()為我們漂亮的完成了這些工作。我們執行於物件上的 操作被很好的打包在這個函式以外了,我們不用再做那樣的迴圈了,我們的程式碼更加清晰了。

for_each演算法引用了iterator範圍的概念,這是一個由起始iterator和一個末尾iterator指出的範圍。 起始iterator指出操作由哪裡開始,末尾iterator指明到哪結束,但是它不包括在這個範圍內。用STL的通用演算法count()來統計list中的元素個數。

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

5.2用STL的通用演算法count()來統計list中的元素個數

STL的通用演算法count()和count_if()用來給容器中的物件記數。就象for_each()一樣,count()和count_if() 演算法也是在iterator範圍內來做的。

讓我們在一個學生測驗成績的list中來數一數滿分的個數。這是一個整型的List。
複製程式碼程式碼如下:
/*
|| How to count objects in an STL list
*/
#include <list>
#include <algorithm>
int main (void)
{
list<int> Scores;
Scores.push_back(100);
Scores.push_back(80);
Scores.push_back(45);
Scores.push_back(75);
Scores.push_back(99);
Scores.push_back(100);

int NumberOf100Scores(0);
//count (Scores.begin(), Scores.end(), 100, NumberOf100Scores);
NumberOf100Scores = count(Scores.begin(), Scores.end(), 100);
cout << "There were " << NumberOf100Scores << " scores of 100" << endl;
}

count()演算法統計等於某個值的物件的個數。上面的例子它檢查list中的每個整型物件是不是100。每次容器中的物件等於100,它就給NumberOf100Scores加1。這是程式的輸出:

程式的輸出:
There were 2 scores of 100

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

6.用STL的通用演算法count_if()來統計list中的元素個數
 
count_if()是count()的一個更有趣的版本。他採用了STL的一個新元件,函式物件。count_if() 帶一個函式物件的引數。函式物件是一個至少帶有一個operator()方法的類。有些STL演算法作為引數接收函式物件並呼叫這個函式物件的operator()方法。
函式物件被約定為STL演算法呼叫operator時返回true或false。它們根據這個來判定這個函式。舉個例子會說的更清楚些。
count_if()通過傳遞一個函式物件來作出比count()更加複雜的評估以確定一個物件是否應該被記數。

在這個例子裡我們將數一數牙刷的銷售數量。我們將提交包含四個字元的銷售碼和產品說明的銷售記錄。

複製程式碼程式碼如下:
/* || Using a function object to help count things */
#include <string>
#include <list>
#include <algorithm>

const string ToothbrushCode("0003");

class IsAToothbrush
{
public:
bool operator() ( string& SalesRecord )
{
return SalesRecord.substr(0,4)==ToothbrushCode;
}
};

int main (void)
{
list<string> SalesRecords;
SalesRecords.push_back("0001 Soap");
SalesRecords.push_back("0002 Shampoo");
SalesRecords.push_back("0003 Toothbrush");
SalesRecords.push_back("0004 Toothpaste");
SalesRecords.push_back("0003 Toothbrush");
int NumberOfToothbrushes(0);
count_if (SalesRecords.begin(), SalesRecords.end(), IsAToothbrush(), NumberOfToothbrushes);
cout << "There were " << NumberOfToothbrushes << " toothbrushes sold" << endl;
}

這是這個程式的輸出:
There were 2 toothbrushes sold

這個程式是這樣工作的:定義一個函式物件類IsAToothbrush,這個類的物件能判斷出賣出的是否是牙刷 。如果這個記錄是賣出牙刷的記錄的話,函式呼叫operator()返回一個true,否則返回false。

count_if()演算法由第一和第二兩個iterator引數指出的範圍來處理容器物件。它將對每個 IsAToothbrush()返回true的容器中的物件增加NumberOfToothbrushes的值。

最後的結果是NumberOfToothbrushes這個變數儲存了產品程式碼域為"0003"的記錄的個數,也就是牙刷的個數。

注意count_if()的第三個引數IsAToothbrush(),它是由它的建構函式臨時構造的一個物件。你可以把IsAToothbrush類的一個臨時物件 傳遞給count_if()函式。count_if()將對該容器的每個物件呼叫這個函式。

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

7 使用count_if()的一個更加複雜的函式物件。

使用count_if()的一個更加複雜的函式物件。
我們可以更進一步的研究一下函式物件。假設我們需要傳遞更多的資訊給一個函式物件。我們不能通過呼叫operator來作到這點,因為必須定義為一個list的中的物件的型別。 然而我們通過為IsAToothbrush指出一個非預設的建構函式就可以用任何我們所需要的資訊來初始化它了。 例如,我們可能需要每個牙刷有一個不定的程式碼。我們可以把這個資訊加到下面的函式物件中:
複製程式碼程式碼如下:
/*
|| Using a more complex function object
*/
#include <iostream.h>
#include <string>
#include <list>
#include <algorithm>

class IsAToothbrush
{
public:
IsAToothbrush(string& InToothbrushCode) : ToothbrushCode(InToothbrushCode) {}
bool operator() (string& SalesRecord)
{
return SalesRecord.substr(0,4)==ToothbrushCode;
}
private:
string ToothbrushCode;
};

int main (void)
{
list<string> SalesRecords;

SalesRecords.push_back("0001 Soap");
SalesRecords.push_back("0002 Shampoo");
SalesRecords.push_back("0003 Toothbrush");
SalesRecords.push_back("0004 Toothpaste");
SalesRecords.push_back("0003 Toothbrush");

string VariableToothbrushCode("0003");

int NumberOfToothbrushes(0);
count_if (SalesRecords.begin(), SalesRecords.end(), IsAToothbrush(VariableToothbrushCode), NumberOfToothbrushes);
cout << "There were  "
 << NumberOfToothbrushes
 << " toothbrushes matching code "
 << VariableToothbrushCode
 << " sold"
 << endl;
}

程式的輸出是:
There were 2 toothbrushes matching code 0003 sold

這個例子演示瞭如何向函式物件傳遞資訊。你可以定義任意你想要的建構函式,你可以再函式物件中做任何你 想做的處理,都可以合法編譯通過。

你可以看到函式物件真的擴充套件了基本記數演算法。

到現在為止,我們都學習了:

定義一個list
向list中加入元素
如何知道list是否為空
如何使用for迴圈來遍歷一個list
如何使用STL的通用演算法for_each來遍歷list
list成員函式begin() 和 end() 以及它們的意義
iterator範圍的概念和一個範圍的最後一個位置實際上並不被處理這一事實
如何使用STL通用演算法count()和count_if()來對一個list中的物件記數
如何定義一個函式物件
我選用這些例子來演示list的一般操作。如果你懂了這些基本原理,你就可以毫無疑問的使用STL了 建議你作一些練習。我們現在用一些更加複雜的操作來擴充套件我們的知識,包括list成員函式和STL通用演算法。

輸出是:
Pineapple

如果沒有找到指出的物件,就會返回Fruit.end()的值,要是找到了就返回一個指著找到的物件的iterator

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

8.使用STL通用演算法find()在list中查詢物件

我們如何在list中查詢東西呢?
STL的通用演算法find()和find_if()可以做這些。
就象for_each(), count(), count_if() 一樣,這些演算法也使用iterator範圍,這個範圍指出一個list或任意其他容器中的一部分來處理。通常首iterator指著開始的位置,次iterator指著停止處理的地方。由次iterator指出的元素不被處理。
這是find()如何工作:
複製程式碼程式碼如下:
/*
|| How to find things in an STL list
*/
#include <string>
#include <list>
#include <algorithm>

int main (void)
{
list<string> Fruit;
list<string>::iterator FruitIterator;

Fruit.push_back("Apple");
Fruit.push_back("Pineapple");
Fruit.push_back("Star Apple");

FruitIterator = find (Fruit.begin(), Fruit.end(), "Pineapple");

if (FruitIterator == Fruit.end())
{
cout << "Fruit not found in list" << endl;
}
else
{
cout << *FruitIterator << endl;
}
}

輸出是:
Pineapple
如果沒有找到指出的物件,就會返回Fruit.end()的值,要是找到了就返回一個指著找到的物件i

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

9.使用STL通用演算法find_if()在list中搜索物件

這是find()的一個更強大的版本。這個例子演示了find_if(),它接收一個函式物件的引數作為引數,並使用它來做更復雜的評價物件是否和給出的查詢條件相付。
假設我們的list中有一些按年代排列的包含了事件和日期的記錄。我們希望找出發生在1997年的事件。

這是find()的一個更強大的版本。這個例子演示了find_if(),它接收一個函式物件的引數作為引數, 並使用它來做更復雜的評價物件是否和給出的查詢條件相付。假設我們的list中有一些按年代排列的包含了事件和日期的記錄。我們希望找出發生在1997年的事件。
複製程式碼程式碼如下:
/*
|| How to find things in an STL list MkII
*/
#include <string>
#include <list>
#include <algorithm>

class EventIsIn1997
{
public:
bool operator () (string& EventRecord)
{
// year field is at position 12 for 4 characters in EventRecord
return EventRecord.substr(12,4)=="1997";
}
};

int main (void)
{
list<string> Events;

// string positions 0123456789012345678901234567890123456789012345
Events.push_back("07 January 1995 Draft plan of house prepared");
Events.push_back("07 February 1996 Detailed plan of house prepared");
Events.push_back("10 January 1997 Client agrees to job");
Events.push_back("15 January 1997 Builder starts work on bedroom");
Events.push_back("30 April 1997 Builder finishes work");

list<string>::iterator EventIterator = find_if (Events.begin(), Events.end(), EventIsIn1997());

// find_if completes the first time EventIsIn1997()() returns true
// for any object. It returns an iterator to that object which we
// can dereference to get the object, or if EventIsIn1997()() never
// returned true, find_if returns end()
if (EventIterator==Events.end())
{
cout << "Event not found in list" << endl;
}
else
{
cout << *EventIterator << endl;
}
}

這是程式的輸出:
10 January 1997 Client agrees to job

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

10.使用STL通用演算法search在list中找一個序列

一些字元在STL容器中很好處理,讓我們看一看一個難處理的字元序列。我們將定義一個list來放字元。
list<char> Characters;

現在我們有了一個字元序列,它不用任何幫助就知道然後管理記憶體。它知道它是從哪裡開始、到哪裡結束。 它非常有用。我不知道我是否說過以null結尾的字元陣列。

讓我們加入一些我們喜歡的字元到這個list中:

Characters.push_back('\0');
Characters.push_back('\0');
Characters.push_back('1');
Characters.push_back('2');

我們將得到多少個空字元呢?
int NumberOfNullCharacters(0);
count(Characters.begin(), Characters.end(), '\0', NumberOfNullCharacters);
cout << "We have " << NumberOfNullCharacters << endl;

讓我們找字元'1'
list<char>::iterator Iter;
Iter = find(Characters.begin(), Characters.end(), '1');
cout << "We found " << *Iter << endl;

這個例子演示了STL容器允許你以更標準的方法來處理空字元。現在讓我們用STL的search演算法來搜尋容器中 的兩個null。就象你猜的一樣,STL通用演算法search()用來搜尋一個容器,但是是搜尋一個元素串,不象find()和find_if() 只搜尋單個的元素。

複製程式碼程式碼如下:
/*
|| How to use the search algorithm in an STL list
*/
#include <string>
#include <list>
#include <algorithm>

int main ( void)
{
list<char> TargetCharacters;
list<char> ListOfCharacters;

TargetCharacters.push_back('\0');
TargetCharacters.push_back('\0');

ListOfCharacters.push_back('1');
ListOfCharacters.push_back('2');
ListOfCharacters.push_back('\0');
ListOfCharacters.push_back('\0');

list<char>::iterator PositionOfNulls = search(ListOfCharacters.begin(), ListOfCharacters.end(), TargetCharacters.begin(), TargetCharacters.end());

if (PositionOfNulls!=ListOfCharacters.end())
cout << "We found the nulls" << endl;
}
The output of the program will be 這是程式的輸出:
We found the nulls

search演算法在一個序列中找另一個序列的第一次出現的位置。在這個例子裡我們在ListOfCharacters中 找TargetCharacters這個序列的第一次出現,TargetCharacters是包含兩個null字元的序列。 search的引數是兩個指著查詢目標的iterator和兩個指著搜尋範圍的iterators。 因此我們我們在整個的ListOfCharacters的範圍內查詢TargetCharacters這個list的整個序列。

如果TargetCharacters被發現,search就會返回一個指著ListOfCharacters中序列匹配的第一個 字元的iterator。如果沒有找到匹配項,search返回ListOfCharacters.end()的值。

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

11 使用list的成員函式sort()排序一個list。

要排序一個list,我們要用list的成員函式sort(),而不是通用演算法sort()。所有我們用過的演算法都是通用演算法。然而,在STL中有時容器支援它自己對一個特殊演算法的實現,這通常是為了提高效能。

在這個例子中,list容器有它自己的sort演算法,這是因為通用演算法僅能為那些提供隨機存取裡面元素的容器排序,而由於list是作為一個連線的連結串列實現的,它不支援對它裡面的元素隨機存取。所以就需要一個特殊的 sort()成員函式來排序list。

由於各種原因,容器在效能需要較高或有特殊效果需求的場合支援外部函式(extra functions), 這通過利用建構函式的結構特性可以作到。
複製程式碼程式碼如下:
/* || How to sort an STL list */
#include <string>
#include <list>
#include <algorithm>
PrintIt (string& StringToPrint)
{
cout << StringToPrint << endl;
}

int main (void)
{
list<string> Staff;
list<string>::iterator PeopleIterator;
Staff.push_back("John");
Staff.push_back("Bill");
Staff.push_back("Tony");
Staff.push_back("Fidel");
Staff.push_back("Nelson");
cout << "The unsorted list " << endl;
for_each(Staff.begin(), Staff.end(), PrintIt );
Staff.sort();
cout << "The sorted list " << endl;
for_each(Staff.begin(), Staff.end(), PrintIt);


輸出是:
The unsorted list  John Bill Tony Fidel Nelson The sorted list  Bill Fidel John Nelson Tony

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

12.用list的成員函式插入元素到list中

list的成員函式push_front()和push_back()分別把元素加入到list的前面和後面。你可以使用insert() 把物件插入到list中的任何地方。

insert()可以加入一個物件,一個物件的若干份拷貝,或者一個範圍以內的物件。這裡是一些插入物件到list中的例子:
複製程式碼程式碼如下:
/*
|| Using insert to insert elements into a list.
*/
#include <list>

int main (void)
{
list<int> list1;

/*
|| Put integers 0 to 9 in the list
*/
for (int i = 0; i < 10; ++i) list1.push_back(i);

/*
|| Insert -1 using the insert member function
|| Our list will contain -1,0,1,2,3,4,5,6,7,8,9
*/
list1.insert(list1.begin(), -1);

/*
|| Insert an element at the end using insert
|| Our list will contain -1,0,1,2,3,4,5,6,7,8,9,10
*/
list1.insert(list1.end(), 10);

/*
|| Inserting a range from another container
|| Our list will contain -1,0,1,2,3,4,5,6,7,8,9,10,11,12
*/
int IntArray[2] = {11,12};
list1.insert(list1.end(), &IntArray[0], &IntArray[2]);

/*
|| As an exercise put the code in here to print the lists!
|| Hint: use PrintIt and accept an interger
*/
}

注意,insert()函式把一個或若干個元素插入到你指出的iterator的位置。你的元素將出現在 iterator指出的位置以前。

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

13.List 建構函式

我們已經象這樣定義了list:
list<int> Fred;

你也可以象這樣定義一個list,並同時初始化它的元素:
// define a list of 10 elements and initialise them all to 0
list<int> Fred(10, 0);
// list now contains 0,0,0,0,0,0,0,0,0,0

或者你可以定義一個list並用另一個STL容器的一個範圍來初始化它,這個STL容器不一定是一個list, 僅僅需要是元素型別相同的的容器就可以。
vector<int> Harry;
Harry.push_back(1);
Harry.push_back(2);
#
// define a list and initialise it with the elements in Harry
list<int> Bill(Harry.begin(), Harry.end());
// Bill now contains 1,2

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

14.使用list成員函式從list中刪除元素
 
list成員函式pop_front()刪掉list中的第一個元素,pop_back()刪掉最後一個元素。函式erase()刪掉由一個iterator指出的元素。還有另一個erase()函式可以刪掉一個範圍的元素。

複製程式碼程式碼如下:
/* || Erasing objects from a list */
#include <list>
int main (void)
{
list<int> list1;// define a list of integers

/* || Put some numbers in the list || It now contains 0,1,2,3,4,5,6,7,8,9 */
for (int i = 0; i < 10; ++i)
list1.push_back(i);

list1.pop_front();// erase the first element 0

list1.pop_back(); // erase the last element 9

list1.erase(list1.begin());
// erase the first element (1) using an iterator

list1.erase(list1.begin(), list1.end());
// erase all the remaining elements

cout << "list contains " << list1.size() << " elements" << endl;


輸出是: