IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> list介绍和基本使用 -> 正文阅读

[数据结构与算法]list介绍和基本使用

一. list介绍

list文档介绍

1). list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
2). list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
3). list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝后迭代,已让其更简单高效。
4).与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
5). 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)

二. list使用

constructor

1).构造一个空容器

list<int> lt;

2).构造一个含有n个值为val的容器

list<int> lt(10,5);

3).拷贝构造

list<int> lt2(lt);

4). 迭代器区间构造

	int a[] = { 16,2,77,29 };
	list<int> lt2(a,a + 4);
	/*  while(first != last)
	*  {
	*		push_back(*first);
	*		++first;
	*  }
	*/
	print(lt2);
	// swap,find,reverse,sort 常用的算法 <algorithm>
	// 原生指针可以看作天然的迭代器
	sort(a,a + 4);
	sort(a, a + 4, greater<int>());
	// sort排序底层是快速排序,迭代器类型只能是随机迭代器
	// 比如三数取中优化,lt不支持随机访问
	sort(lt.begin(),lt.end());

在这里插入图片描述

list迭代器是双向迭代器,不支持 - 操作,因此报错

这里顺便介绍一下迭代器的类型 :
单向迭代器 : 只能向后依次遍历(只支持++操作) (如 forward_list)
双向迭代器 : 可以向前向后依次遍历(支持++和–操作) (如 list)
随机迭代器 : 可以向前向后随机遍历(支持++ /- - / + / - / += / -= 操作) (如 vector/string)

在这里插入图片描述

iterator

在这里插入图片描述

iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt(10, 5);
	//正向迭代器遍历容器
	list<int>::iterator it = lt.begin();
	while (it != lt.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
	// 反向迭代器遍历容器
	list<int>::reverse_iterator rit = lt.rbegin();
	while (rit != lt.rend())
	{
		cout << *rit << " ";
		rit++;
	}
	cout << endl;
	return 0;
}

capacity

empty

判断容器是否为空

#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt; 
	cout << lt.empty() << endl; //1
	return 0;
}

size

获取容器中的元素个数

#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	cout << lt.size() << endl; //4
	return 0;
}

Element access

front/back

front函数用于获取list容器当中的第一个元素的引用,back函数用于获取list容器当中的最后一个元素的引用

#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	cout << lt.front() << endl; //1
	cout << lt.back() << endl; //4
	return 0;
}

Modifiers

assign

将新内容赋值给list容器,替换其当前内容,并相应地修改其大小

1). 将n个值为val的数据分配给容器。
2). 将所给迭代器区间当中的内容分配给容器。

// list::assign
#include <iostream>
#include <list>
using namespace std;
int main ()
{
  	list<int> first;
  	list<int> second;
  	first.assign (7,100);                      // 7 ints with value 100
  	second.assign (first.begin(),first.end()); // a copy of first

  	int myints[]={1776,7,4};
  	first.assign (myints,myints+3);            // assigning from array

  	cout << "Size of first: " << int (first.size()) << endl; // 3
  	cout << "Size of second: " << int (second.size()) << endl; // 7
  	return 0;
}

push_front/pop_front

头插,头删容器中的数据

#include <iostream>
#include <list>
using namespace std;
int main ()
{
  	list<int> mylist (2,100);         // two ints with a value of 100
  	mylist.push_front (200);
  	mylist.push_front (300);

 	cout << "mylist contains:";
  for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
    	cout << ' ' << *it;
  cout << endl;
  return 0;
  // output 
  // 300 200 100 100
}
#include <iostream>
#include <list>
using namespace std;
int main ()
{
  	list<int> mylist;
  	mylist.push_back (100);
  	mylist.push_back (200);
  	mylist.push_back (300);

  cout << "Popping out the elements in mylist:";
  while (!mylist.empty())
  {
    	cout << ' ' << mylist.front();
    	mylist.pop_front();
  }

  cout << "\nFinal size of mylist is " << mylist.size() << endl;

  return 0;
  // output
  // Popping out the elements in mylist: 100 200 300
  // Final size of mylist is 0
}

push_back/pop_back

尾插,尾删容器中的数据

// list::push_back
#include <iostream>
#include <list>
int main ()
{
  std::list<int> mylist;
  int myint;

  std::cout << "Please enter some integers (enter 0 to end):\n";

  do {
    std::cin >> myint;
    mylist.push_back (myint);
  } while (myint);

  std::cout << "mylist stores " << mylist.size() << " numbers.\n";

  return 0;
}
// list::pop_back
#include <iostream>
#include <list>
int main ()
{
  std::list<int> mylist;
  int sum (0);
  mylist.push_back (100);
  mylist.push_back (200);
  mylist.push_back (300);

  while (!mylist.empty())
  {
    sum+=mylist.back();
    mylist.pop_back();
  }

  std::cout << "The elements of mylist summed " << sum << '\n';

  return 0;
  // output
  // The elements of mylist summed 600
}

insert

1).在指定迭代器位置插入一个数。
2). 在指定迭代器位置插入n个值为val的数。
3).在指定迭代器位置插入一段迭代器区间(左闭右开)。

// inserting into a list
#include <iostream>
#include <list>
#include <vector>
int main ()
{
  std::list<int> mylist;
  std::list<int>::iterator it;

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

  it = mylist.begin();
  ++it;       // it points now to number 2           ^

  mylist.insert (it,10);                        // 1 10 2 3 4 5

  // "it" still points to number 2                      ^
  mylist.insert (it,2,20);                      // 1 10 20 20 2 3 4 5

  --it;       // it points now to the second 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;
  // output
  // mylist contains: 1 10 20 30 30 20 2 3 4 5
}
#include <iostream>
#include <list>
int main()
{
	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);

	list<int>::iterator pos = find(lt.begin(),lt.end(),3);
	lt.insert(pos,30);
	print(lt);
	cout << *pos << endl; // 3
}

insert 不会导致迭代器失效,因为链表的插入并不会影响 it/pos 所指向的位置

erase

1).删除指定迭代器位置的元素。
2). 删除指定迭代器区间(左闭右开)的所有元素。

// erasing from list
#include <iostream>
#include <list>
int main ()
{
  std::list<int> mylist;
  std::list<int>::iterator it1,it2;

  // set some values:
  for (int i=1; i<10; ++i) mylist.push_back(i*10);

                              // 10 20 30 40 50 60 70 80 90
  it1 = it2 = mylist.begin(); // ^^
  advance (it2,6);            // ^                 ^
  ++it1;                      //    ^              ^

  it1 = mylist.erase (it1);   // 10 30 40 50 60 70 80 90
                              //    ^           ^

  it2 = mylist.erase (it2);   // 10 30 40 50 60 80 90
                              //    ^           ^

  ++it1;                      //       ^        ^
  --it2;                      //       ^     ^

  mylist.erase (it1,it2);     // 10 30 60 80 90
                             //        ^
// it1 已经失效
  std::cout << "mylist contains:";
  for (it1=mylist.begin(); it1!=mylist.end(); ++it1)
    std::cout << ' ' << *it1;
  std::cout << '\n';

  return 0;
 // Output:
//  mylist contains: 10 30 60 80 90
}
#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);

	list<int>::iterator pos = find(lt.begin(), lt.end(), 3);
	// pos迭代器失效
	lt.erase(pos);
	print(lt);
	cout << *pos << endl;
}

erase 会导致迭代器失效,因为链表的删除会使 pos 所指向的位置被释放,从而 pos 成为野指针

swap

swap用于交换两个容器的内容

// swap lists
#include <iostream>
#include <list>
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;
//  Output:

//	first contains: 200 200 200 200 200 
//	second contains: 100 100 100 
}

resize

1). 若 n 小于当前容器的 size ,size 减少到 n
2). 若 n 大于当前容器的 size,尾插入数据直到 n,值用 val 来填充

// resizing list
#include <iostream>
#include <list>
int main ()
{
  std::list<int> mylist;

  // set some initial content:
  for (int i=1; i<10; ++i) mylist.push_back(i);

  mylist.resize(5);
  mylist.resize(8,100);
  mylist.resize(12);

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

  std::cout << '\n';

  return 0;
  // output
  // mylist contains: 1 2 3 4 5 100 100 100 0 0 0 0
}

clear

清空容器,使容器的 size 成为 0

// clearing lists
#include <iostream>
#include <list>
int main ()
{
  std::list<int> mylist;
  std::list<int>::iterator it;

  mylist.push_back (100);
  mylist.push_back (200);
  mylist.push_back (300);

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

  mylist.clear();
  mylist.push_back (1101);
  mylist.push_back (2202);

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

  return 0;
  // output
  // mylist contains: 100 200 300 
 //  mylist contains: 1101 2202
}

operations

splice

splice函数用于两个list容器数据之间的转移,其有三种拼接方式:

1).将整个容器拼接到另一个容器的指定迭代器位置。
2).将容器当中的某一个数据拼接到另一个容器的指定迭代器位置。
3).将容器指定迭代器区间的数据拼接到另一个容器的指定迭代器位置。

// splicing lists
#include <iostream>
#include <list>
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

  mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4
                                // mylist2 (empty)
                                // "it" still points to 2 (the 5th element)
                                          
  mylist2.splice (mylist2.begin(),mylist1, it);
                                // mylist1: 1 10 20 30 3 4
                                // mylist2: 2
                                // "it" is now invalid.
  it = mylist1.begin();
  std::advance(it,3);           // "it" points now to 30

  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;
  // output
  // mylist1 contains: 30 3 4 1 10 20
  // mylist2 contains: 2
}

remove

remove函数用于删除容器当中被指定的元素,和erase不同,erase是删除迭代器位置的值

// remove from list
#include <iostream>
#include <list>
int main ()
{
  int myints[] = {17,89,7,14};
  std::list<int> mylist (myints,myints+4);

  mylist.remove(89);

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

  return 0;
  // Output:
  // mylist contains: 17 7 14
}

remove_if

remove_if函数用于删除容器当中满足条件的元素。

// list::remove_if
#include <iostream>
#include <list>

// a predicate implemented as a function:
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

  mylist.remove_if (single_digit);           // 15 36 17 20 39

  mylist.remove_if (is_odd());               // 36 20

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

  return 0;
 // Output:
 // mylist contains: 36 20
}

unique

unique函数用于删除容器当中连续的重复元素(配合sort使用)。

// list::unique
#include <iostream>
#include <cmath>
#include <list>

// a binary predicate implemented as a function:
bool same_integral_part (double first, double second)
{ return ( int(first)==int(second) ); }

// a binary predicate implemented as a class:
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();           //  2.72,  3.14, 12.15, 12.77
                             // 15.3,  72.25, 73.0,  73.35

  mylist.unique (same_integral_part);  //  2.72,  3.14, 12.15
                                       // 15.3,  72.25, 73.0

  mylist.unique (is_near());           //  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
}

sort

sort 默认将容器中的数据排成升序,排降序可以用 greater<>

// list::sort
#include <iostream>
#include <list>
#include <string>
#include <cctype>

// comparison, not case sensitive.
bool compare_nocase (const std::string& first, const std::string& second)
{
  unsigned int i=0;
  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
}

reverse

reverse函数用于将容器当中元素的位置进行逆置。

// reversing list
#include <iostream>
#include <list>

int main ()
{
  std::list<int> mylist;

  for (int i=1; i<10; ++i) mylist.push_back(i);

  mylist.reverse();

  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: 9 8 7 6 5 4 3 2 1
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-15 15:50:18  更:2021-08-15 15:50:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:33:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码