c++ list总结.

  • 重点总结
  • List使用非连续的内存空间进行存储,具有双链表结构,不支持根据下标随机存取元素。
  • List中每个元素中都有一个指针指向后一个元素,也有一个指针指向前一个元素,且由于需要额外维护指针 ,开销也比较大。。
  • 优点: 与vector、deque等容器相比,list在将元素进行插入、删除表现的更好,插入操作如图2所示。
  • 缺点: 不能进行内部的随机访问,即不支持[ ]操作符和at() ,如需访问list中的第六个元素,则必须从已知位置(如开始或结束)迭代到该位置
    在这里插入图片描述


std::list 全部函数

	assign			修改容器中内容
	back 			返回指向容器尾元素的迭代器
	begin 			返回指向容器头的迭代器
	capacity  		返回容器分配的空间大小
	cbegin			返回指向容器头的迭代器-const
	cend			返回指向容器尾元素后一个位置的迭代器 - const
	clear 			清空容器
	crbegin			返回指向容器最后一个元素的 逆序 迭代器 - const
	crend			返回指向容器头元素前一个位置的 逆序 迭代器 - const
	
	emplace 		通过迭代器在指定位置插入新元素,move
	emplace_back	在容器尾处插入元素新元素,move
	emplace_front	在容器头处插入元素新元素,move
	empty			判断容器是否为空
	end				返回指向容器尾的迭代器
	erase 			删除元素
	front			返回容器头元素的引用
	get_allocator	返回与列表容器关联的分配器对象的副本
	insert			插入元素
	max_size		返回容器可以容纳的最大元素数
	pop_back 		删除容器的最后一个元素
	pop_front 		删除容器的第一个元素
	push_back		在容器尾处插入元素,copy
	push_front 		在容器头处插入元素,copy
	rbegin			返回指向容器最后一个元素的 逆序 迭代器
	remove() 		从list删除元素
	remove_if() 	按指定条件删除元素
	rend			返回指向容器头元素前一个位置的 逆序 迭代器
	reserve 		改变容器所分配空间的大小
	resize 			改变容器的大小,如果new_size大于当前容量,则填充默认值
	size 			返回容器中元素个数
	sort			按严格弱排序对容器内元素进行排序,可使用自定义compare函数
	splice			将容器x中的元素传输至当前容器,删除容器x中对应元素
	swap 			当前vector与作为参数的vector交换元素
	unique			对于容器中重复元素,删除除第一个元素外的所有元素

1、构造函数、assign()

  • 头文件 #include <list>
  • <1>. 构造函数,函数原型如下:
explicit list (const allocator_type& alloc = allocator_type());		// 1. default 空的容器
explicit list (size_type n);
         list (size_type n, const value_type& val,
                const allocator_type& alloc = allocator_type());	// 2. fill

template <class InputIterator>
  list (InputIterator first, InputIterator last,
         const allocator_type& alloc = allocator_type());			// 3. range
         
list (const list& x);												// 4. copy
list (const list& x, const allocator_type& alloc);		
			
list (list&& x);													// 5. MOVE
list (list&& x, const allocator_type& alloc);	

list (initializer_list<value_type> il,
       const allocator_type& alloc = allocator_type());				// 6. initializer list

例子: 注释中序号与上述顺序相同

int main () {
    
    
    // constructors used in the same order as described above:
    std::list<int> first;                                // [1]
    std::list<int> second(4,100);                        // [2]
    std::list<int> third(second.begin(),second.end());   // [3]
    std::list<int> fourth(third);                        // [4] copy

    // the iterator constructor can also be used to construct from arrays:
    int myints[] = {
    
    16,2,77,29};
    std::list<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );      // [6] initializer

    std::cout << "The contents of fifth are: ";
    for (std::list<int>::iterator it = fifth.begin(); it != fifth.end(); it++)
        std::cout << *it << ' ';

    return 0;
}

The contents of fifth are: 16 2 77 29

  • <2>. assign(),函数原型如下:
template <class InputIterator>
  void assign(InputIterator first, InputIterator last);		// 1. range
void assign(size_type n, const value_type& val);			// 2. fill
void assign(initializer_list<value_type> il);				// 3. initializer list

例子: 注释中序号与上述顺序相同

int main () {
    
    
    std::list<int> first;
    std::list<int> second;

    first.assign(7,100);                            // [1]. 7 ints with value 100
    std::cout << "Size of first: " << int (first.size()) << '\n';

    second.assign(first.begin(),first.end());       // [2]. a copy of first
    std::cout << "Size of second: " << int (second.size()) << '\n';

    int myints[]={
    
    1776,7,4};
    first.assign(myints,myints+3);                  // [3]. first已有元素,assign清空容器,添加新元素,改变size

    std::cout << "Size of first: " << int (first.size()) << '\n';
    
    return 0;
}

Size of first: 7
Size of second: 7
Size of first: 3


2、插入 insert, push(pop), emplace

2.1 push_*()pop_*()

  • push_front()、push_back(),在容器头、尾通过copy添加元素;
  • pop_front()、pop_back(),在容器头、尾删除元素,函数原型如下。
void push_back(const value_type& val);
void push_back(value_type&& val);			// push_back

void push_front(const value_type& val);
void push_front(value_type&& val);			// push_front

void pop_back();							// pop_back
void pop_front();							// pop_front
int main () {
    
    
	std::list<int> mylist(2,200);         // two ints with a value of 100
	mylist.push_front(100);
	mylist.push_back(300);
	
	// push 
	std::cout << "push:";
	for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
		std::cout << ' ' << *it;
	
	
	mylist.pop_front();
	mylist.pop_back();
	std::cout << "\npop:";
	for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
		std::cout << ' ' << *it;
	
	std::cout << '\n';
	return 0;
}

push: 100 200 200 300
pop: 200 200

2.2 insert

  • insert(): 在容器内部添加元素。使用方法与其他序列容器相似,函数原型如下。
// [1] 在迭代器指定位置插入新的元素val. 迭代器指向的元素及后续元素-后移
iterator insert(const_iterator position, const value_type& val);

// [2] 在迭代器指定位置插入几个相同元素val.
iterator insert(const_iterator position, size_type n, const value_type& val);

// [3] 在迭代器指定位置前插入 另一个容器的 Iterator.first 至 Iterator.last 的元素.
template <class InputIterator>
iterator insert(const_iterator position, InputIterator first, InputIterator last);

// 右值
iterator insert(const_iterator position, value_type&& val);
// list
iterator insert(const_iterator position, initializer_list<value_type> il);

例子:

int main () {
    
    
	std::list<int> mylist{
    
    1,2,3,4,5};
	std::list<int>::iterator it;


	it = ++mylist.begin(); 						// it 指向元素2, 用 ^ 表示
	
	mylist.insert(it, 10);               		// 1 10 2 3 4 5
	// 													^
	mylist.insert(it,2,20);             		// 1 10 20 20 2 3 4 5
	// 													      ^
	std::cout << "*it-value:" << *it << std::endl;
	
	--it;       								// it 指向元素20

	std::vector<int> myvector(2,30);
	mylist.insert (it, myvector.begin(), myvector.end());
	// 1 10 20 30 30 20 2 3 4 5  
	//               ^			 	
	std::cout << "mylist contains:";
	for (it=mylist.begin(); it!=mylist.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';

	return 0;
}

*it-value:2
mylist contains: 1 10 20 30 30 20 2 3 4 5

  • 重点: 可以看出,通过参数iterator 进行insert操作,插入结束时,作为参数的迭代器iterator指向的元素保存不变,说明函数内部在进行插入时,作为参数的迭代器随插入元素的个数后移。
  • insert 函数返回的迭代器,指向新插入元素中的第一个的元素的位置。测试代码如下:
int main () {
    
    
	std::list<int> mylist{
    
    1,2,3,4,5};


	std::list<int>::iterator it = mylist.begin(); 
	auto iter = mylist.insert(it, 2, 10);    	// 10 10 1 2 3 4 5
	
	std::cout << "参数迭代器指向元素:" << *it   << std::endl;	
	std::cout << "返回迭代器指向元素:" << *iter << std::endl;
	
	return 0;
}

参数迭代器指向元素:1
返回迭代器指向元素:10

2.3 emplace_*()

  • emplace_*()方法通过move插入元素,提高效率,其函数原型如下:
template <class... Args>
  void emplace_back(Args&&... args);		// 1. emplace_back
  
template <class... Args>
  void emplace_front(Args&&... args);		// 2. emplace_front


template <class... Args>					// 3. 在指定的位置进行操作
  iterator emplace(const_iterator position, Args&&... args);

例子:

int main () {
    
    
	std::list<std:: string> listOne {
    
    "B", "C", "D", "E"};
	
	listOne.emplace_front("A");					// 1. A B C D E
	listOne.emplace_back("100"); 				// 2. A B C D E Z			
	
	listOne.emplace(begin(listOne), "Name");	// 3. Name A B C D E Z 200
	
	for (auto& i:listOne)
		std::cout << i << " ";
	return 0;
}

Name A B C D E 100


3、删除 erase、remove、remove_if

  • clear()删除list中所有元素,使用后list.size()为0;

3.1 erase

  • erase()方法可以删除容器中元素,返回一个迭代器,该迭代器指向被删除位置后的一个元素。
  • erase()删除了List中最后一个元素,则返回List.end()。函数原型如下:
iterator erase(const_iterator position);	
iterator erase(const_iterator first, const_iterator last);

通过迭代器删除所有元素

int main() {
    
    
	list<int> listOne{
    
    1,2,4,4,5,6};
	
	// 错误试列
	// erase()之后对应位置的迭代器已经失效,这时 iter++ 将无法找到下一个元素。
	for (list<int>::iterator iter=listOne.begin(); iter!=listOne.end(); ++iter)
		listOne.erase(iter);
	
	// 正确示例
	for (list<int>::iterator iter=listOne.begin(); iter!=listOne.end(); ){
    
    
	    iter = listOne.erase(iter);  // 或:  listOne.erase(iter++); 
	}
	
	return 0;
}

3.2 remove

  • remove(): 从列表容器中删除与 val 值相等的元素,减小容器的大小,其减小的长度等于被删除的元素的个数,原型如下:
void remove (const value_type& val);

例子:

int main () {
    
    
	
	std::list<int> listOne{
    
    1,2,3,4,5,6};
	
	std::cout << "listOne: ";			
	for (auto& iter:listOne)
		std::cout << iter << " ";	// .size() = 6
	
	
	listOne.remove(2);
	std::cout << "\nlistOne: ";
	for (auto& iter:listOne)			
		std::cout << iter << " ";	// .size() = 5
	
	return 0;
}

listOne: 1 2 3 4 5 6
listOne: 1 3 4 5 6

3.4 remove_if

  • remove_if(): 删除容器中所有满足条件的元素,原型如下:
template <class Predicate>
  void remove_if(Predicate pred);
  • 使用方式
  • www.cplusplus.com : 从容器中移除谓词pred 返回 true 的所有元素。这将调用这些对象的析构函数,并通过移除的元素数减少容器大小。
  • 该函数为每个元素调用 pred(*iter),其中iter是该元素对应的迭代器。列表中返回true的元素都将从容器中移除。
  • 例子如下
// list::remove_if
#include <iostream>
#include <list>

// ### 方法一对应函数 ###
bool single_digit(const int& value) {
    
     
	return (value<10);
}

// ### 方法二对应对象 ###
// a predicate implemented as a class:
struct is_odd {
    
    
	bool operator()(const int& value) {
    
     
		return (value%2)==1; 
	}
};

int main ()
{
    
    
	int myints[]= {
    
    15,36,7,17,20,39,4,1};
	std::list<int> mylist(myints,myints+8);   // 15 36 7 17 20 39 4 1
	
	// 方法一,返回true的元素被删除
	mylist.remove_if(single_digit);			// 15 36 17 20 39
	
	// 方法二,参数为is_odd::operator()函数
	mylist.remove_if(is_odd());				// 36 20
	
	// list 打印函数
	std::cout << "mylist contains:";
	for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
	  std::cout << ' ' << *it;
	std::cout << '\n';
	
	return 0;
}

mylist contains: 36 20


4、特殊函数 swap、sort、splice、unique

  • 这几个函数里swap最易理解,当前容器与参数容器中元素相交换。
  • 函数原型为:
void swap (list& x);
int main () {
    
    
	std::list<int> first(3,100);   // three ints with a value of 100
	std::list<int> second(5,200);  // five ints with a value of 200

	first.swap(second);

	std::cout << "first contains:";
	for (std::list<int>::iterator it=first.begin(); it!=first.end(); it++)
		std::cout << ' ' << *it;
	std::cout << '\n';

	std::cout << "second contains:";
	for (std::list<int>::iterator it=second.begin(); it!=second.end(); it++)
		std::cout << ' ' << *it;
	std::cout << '\n';

	return 0;
}

first contains: 200 200 200 200 200
second contains: 100 100 100

4.1 sort

  • sort(): 比较容器中的元素大小(严格的元素弱排序),更改其在容器中的位置。
  • 参数comp:第一个参数严格弱于第二个参数,返回true,否则返回false
  • ps: “<”操作符是一个严格弱序,而“<=”就不是一个严格弱序。
void sort();				// 使用operator < 比较元素,执行排序

template <class Compare>
  void sort(Compare comp);	// 使用comp 函数比较元素,执行排序
bool compare_nocase (const std::string& first, const std::string& second) {
    
    
    unsigned int i=0;

    // tolower是<ctype.h>中函数: 把给定的字母转换为小写字母
    while ( (i<first.length()) && (i<second.length()) ){
    
    
        if (tolower(first[i])<tolower(second[i]))		
            return true;
        else if (tolower(first[i])>tolower(second[i]))
            return false;
        ++i;
    }
    return ( first.length() < second.length() );
}

int main () {
    
    
	std::list<std::string> mylist;
	std::list<std::string>::iterator it;
	mylist.push_back("one");
	mylist.push_back("two");
	mylist.push_back("Three");

	mylist.sort();						// 元素默认比较大小

	std::cout << "mylist contains:";
	for (it=mylist.begin(); it!=mylist.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';

	mylist.sort(compare_nocase);		// 自定义函数-比较元素大小

	std::cout << "mylist contains:";
	for (it=mylist.begin(); it!=mylist.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';

	return 0;
}

mylist contains: Three one two
mylist contains: one Three two       //  ASCII: A-65, a-97

4.2 splice

  • splice():将元素从x中传输到当前容器中,按位置位置插元素。
  • 元素插入当前容器后,x中对应元素将被删除,两个容器的.size()将会改变。
  • 容器x无论是左值or右值,splice()函数都将支持元素传递。
// 1. 将x的所有元素都转移到 当前容器中。
void splice(const_iterator position, list& x);
void splice(const_iterator position, list&& x);

// 2. 仅将i指向的元素从x传输到 当前容器中。
void splice(const_iterator position, list& x, const_iterator i);
void splice(const_iterator position, list&& x, const_iterator i);

// 3. 将范围[first,last)的元素从x传输到 当前容器中。
void splice(const_iterator position, list& x,
            const_iterator first, const_iterator last);		
void splice(const_iterator position, list&& x,
            const_iterator first, const_iterator last);
int main () {
    
    
	std::list<int> mylist1, mylist2;
	std::list<int>::iterator it;

	// set some initial values:
	for (int i=1; i<=4; ++i)
		mylist1.push_back(i);     // mylist1: 1 2 3 4

	for (int i=1; i<=3; ++i)
		mylist2.push_back(i*10);  // mylist2: 10 20 30

	it = mylist1.begin();
	++it;                         // points to 2
	
	// [1] 
	mylist1.splice(it, mylist2);  // mylist1: 1 10 20 30 2 3 4
								  // mylist2.size() = 0
								  // "it" still points to 2 (the 5th element)
	
	// [2]
	mylist2.splice(mylist2.begin(), mylist1, it);
								 // mylist1: 1 10 20 30 3 4
								 // mylist2: 2
								 // "it" 现在是无效的了

	it = mylist1.begin();
	std::advance(it, 3);           // "it" points now to 30,函数功能: 将 it 迭代器前进或后退 n 个位置。

	// [3]. 
	mylist1.splice ( mylist1.begin(), mylist1, it, mylist1.end());
	// mylist1: 30 3 4 1 10 20

	std::cout << "mylist1 contains:";
	for (it=mylist1.begin(); it!=mylist1.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';

	std::cout << "mylist2 contains:";
	for (it=mylist2.begin(); it!=mylist2.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';

	return 0;
}

mylist1 contains: 30 3 4 1 10 20
mylist2 contains: 2

4.3 unique

  • unique(): 对于容器中重复元素,删除除第一个元素外的所有元素。
  • 对于自定义二元谓词(Binary Predicate)函数,作为传入参数的两个值,返回true则删除第一个参数,否则返回false
void unique();

template <class BinaryPredicate>
  void unique (BinaryPredicate binary_pred);
// 函数1-BinaryPredicate
bool same_integral_part(double first, double second){
    
     
	return ( int(first)==int(second) ); 
}

// 作为对象实现的-BinaryPredicate
struct is_near{
    
    
  bool operator() (double first, double second){
    
     
  	return (fabs(first-second)<5.0); 
  }
};

int main () {
    
    
	double mydoubles[]={
    
     12.15,  2.72, 73.0,  12.77,  3.14,
	                     12.77, 73.35, 72.25, 15.3,  72.25 };
	std::list<double> mylist (mydoubles,mydoubles+10);
	
	mylist.sort();             //  2.72,  3.14, 12.15, 12.77, 12.77,
	                           // 15.3,  72.25, 72.25, 73.0,  73.35
	
	mylist.unique();           				//  1. 默认版本
	// 2.72,  3.14, 12.15, 12.77, 15.3,  72.25, 73.0,  73.35
	
	mylist.unique(same_integral_part);   	//  2. int(element) 比较元素是否相等 
	// 2.72,  3.14, 12.15, 15.3,  72.25, 73.0
	
	mylist.unique(is_near());           	// 3. 两元素差<5, 则认为相等
	//  2.72, 12.15, 72.25
	
	std::cout << "mylist contains:";
	for (std::list<double>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
	  std::cout << ' ' << *it;
	std::cout << '\n';
	
	return 0;
}

mylist contains: 2.72 12.15 72.25

猜你喜欢

转载自blog.csdn.net/u013271656/article/details/110239520