您的位置:首页 > 编程语言 > C语言/C++

VC++中list::list的使用方法总结

2013-12-09 13:57 309 查看
本文主题这几天在做图像处理方面的研究,其中有一部分是关于图像分割方面的,图像目标在分割出来之后要做进一步的处理,因此有必要将目标图像的信息保存在一个变量里面,一开始想到的是数组,但是马上就发现使用数组的缺点:数组长度固定,动态分配内存很容易导致错误发生。最重要的一点是我要保存目标图像的每一点的坐标值,使用数组就有点无能为力了。因此到百度、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
, ofclass
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 ofthe controlled sequence becomeinvalid.当一个成员要进行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是空的则返回trueend() 返回末尾的迭代器erase() 删除一个元素front() 返回第一个元素get_allocator() 返回list的配置器insert() 插入一个元素到list中max_size() 返回list能容纳的最大元素数量merge() 合并两个listpop_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() 合并两个listswap() 交换两个listunique() 删除list中重复的元素附List用法实例:#include <iostream>#include <list>#include <numeric>#include <algorithm>using namespace std;//创建一个list容器的实例LISTINTtypedef list<int> LISTINT;//创建一个list容器的实例LISTCHARtypedef 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] ;// 采用vectorvector<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:// 自定义一个classclass Cmyclass{};// 定义一个存放class的容器vector<Cmyclass> vecMyHouse;5. 你可以在定义容器时为它赋初值// 定义一个容纳100个int型数据的容器,初值赋为0vector<int> vecMyHouse(100,0);6. 你可以把一个容器的对象赋值给另外一个容器eg:// 定义一个容纳100个int型数据的容器,初值赋为0vector<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提供如下函数或操作:下面列举了部分常用的功能// 定义一个vectorstd::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// 对于容器,使用迭代器操作容器中对应位置的值// 当迭代器指向了容器中的某位置,则可以使用 * 加迭代器操作该位置了// 定义一个vectorstd::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;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: