STL简单学习2

到现在为止,我们都学习了:

定义一个list
向list中加入元素
如何知道list是否为空
如何使用for循环来遍历一个list
如何使用STL的通用算法for_each来遍历list
list成员函数begin() 和 end() 以及它们的意义
iterator范围的概念和一个范围的最后一个位置实际上并不被处理这一事实
如何使用STL通用算法count()和count_if()来对一个list中的对象记数
如何定义一个函数对象
我选用这些例子来演示list的一般操作。如果你懂了这些基本原理,你就可以毫无疑问的使用STL了 建议你作一些练习。我们现在用一些
更加复杂的操作来扩展我们的知识,包括list成员函数和STL通用算法。



使用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

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()的值,要是找到了就返回一个指着找到的对象的iterator


使用STL通用算法find_if()在list中搜索对象
这是find()的一个更强大的版本。这个例子演示了find_if(),它接收一个函数对象的参数作为参数, 并使用它来做更复杂的评价对象是
否和给出的查找条件相付。
假设我们的list中有一些按年代排列的包含了事件和日期的记录。我们希望找出发生在1997年的事件。

|| How to find things in an STL list MkII

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 April1997  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



使用STL通用算法search在list中找一个序列
一些字符在STL容器中很好处理,让我们看一看一个难处理的字符序列。我们将定义一个list来放字符。
list 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() 只搜索单个的元素。

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()的值



使用list的成员函数sort()排序一个list。
要排序一个list,我们要用list的成员函数sort(),而不是通用算法sort()。所有我们用过的算法都是 通用算法。然而,在STL中有时容
器支持它自己对一个特殊算法的实现,这通常是为了提高性能。
在这个例子中,list容器有它自己的sort算法,这是因为通用算法仅能为那些提供随机存取里面元素 的容器排序,而由于list是作为一个
连接的链表实现的,它不支持对它里面的元素随机存取。所以就需要一个特殊的 sort()成员函数来排序list。

由于各种原因,容器在性能需要较高或有特殊效果需求的场合支持外部函数(extra functions), 这通过利用构造函数的结构特性可以作
到。

|| How to sort an STL list

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

用list的成员函数插入元素到list中
list的成员函数push_front()和push_back()分别把元素加入到list的前面和后面。你可以使用insert() 把对象插入到list中的任何地
方。
insert()可以加入一个对象,一个对象的若干份拷贝,或者一个范围以内的对象。这里是一些 插入对象到list中的例子:

/*
|| Using insert to insert elements into a 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指出的位置以前。



List 构造函数
我们已经象这样定义了list:
list Fred;
你也可以象这样定义一个list,并同时初始化它的元素:
// define a list of 10 elements and initialise them all to 0
list 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


使用list成员函数从list中删除元素
list成员函数pop_front()删掉list中的第一个元素,pop_back()删掉最后一个元素。 函数erase()删掉由一个iterator指出的元素。还有
另一个erase()函数可以删掉一个范围的元素。

|| Erasing objects from a 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;
}

输出是:
list contains 0 elements



用list成员函数remove()从list中删除元素。
list的成员函数remove()用来从list中删除元素。

|| Using the list member function remove to remove elements

#
PrintIt (const string& StringToPrint) {
  cout << StringToPrint << endl;
}
#
int main (void) {
  list<string> Birds;
#
  Birds.push_back("cockatoo");
  Birds.push_back("galah");
  Birds.push_back("cockatoo");
  Birds.push_back("rosella");
  Birds.push_back("corella");
#
  cout << "Original list with cockatoos" << endl;
  for_each(Birds.begin(), Birds.end(), PrintIt); 
 # 
  Birds.remove("cockatoo"); 
#
  cout << "Now no cockatoos" << endl;
  for_each(Birds.begin(), Birds.end(), PrintIt); 

}

输出是:

Original list with cockatoos
cockatoo
galah
cockatoo
rosella
corella
Now no cockatoos
galah
rosella
corella



使用STL通用算法remove()从list中删除元素
通用算法remove()使用和list的成员函数不同的方式工作。一般情况下不改变容器的大小。

|| Using the generic remove algorithm to remove list elements

#
PrintIt(string& AString) { cout << AString << endl; }
#
int main (void) {
list Birds;
list::iterator NewEnd;
#
Birds.push_back(“cockatoo”);
Birds.push_back(“galah”);
Birds.push_back(“cockatoo”);
Birds.push_back(“rosella”);
Birds.push_back(“king parrot”);
#
cout << “Original list” << endl;
for_each(Birds.begin(), Birds.end(), PrintIt);
#
NewEnd = remove(Birds.begin(), Birds.end(), “cockatoo”);
#
cout << endl << “List according to new past the end iterator” << endl;
for_each(Birds.begin(), NewEnd, PrintIt);
#
cout << endl << “Original list now. Care required!” << endl;
for_each(Birds.begin(), Birds.end(), PrintIt);
}
The output will be
Original list
cockatoo
galah
cockatoo
rosella
king parrot

List according to new past the end iterator
galah
rosella
king parrot

Original list now. Care required!
galah
rosella
king parrot
rosella
king parrot
通用remove()算法返回一个指向新的list的结尾的iterator。从开始到这个新的结尾(不含新结尾元素)的范围 包含了remove后剩下所有
元素。你可以用list成员函数erase函数来删除从新结尾到老结尾的部分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值