包含头文件 <list> 

list<int> iNum;    //创建一个list对象,存放整型数据
  • 模板类型:存储数据类型:int 

  • 自己写链表需要写释放内存,对于标准库的 list 内存不需要你去处理,最后会自动释放(便捷之处)

  • 用到链表的地方,都可以使用 list 去替换 

处理基本数据类型

插入

void testList() {
	list<string> strNum;
	strNum.push_back("string1");	//尾插法    放入的数据当作函数参数
	strNum.push_back("string2");
	strNum.push_front("string3");   //头插法
}
int main() {
    testList();
}
//string3  string1  string2

遍历 

  • 不删除的方式遍历

  • 删除的方式遍历

void testlist() {

//不删除的方式遍历-> 用迭代器去做遍历-> 内置的iterator去遍历
	list<string>::iterator iter;
	for (iter = strNum.begin(); iter != strNum.end(); iter++)
	{
		cout << *iter << " ";
	}
	cout << endl;
	cout << "是否为空:" << boolalpha << strNum.empty() << endl;
	cout << "元素个数:" << strNum.size() << endl;

//删除的方式遍历(会把原数据删掉)-> 打印头后,删掉,再打印头,再删掉,直到打印为空的时候结束
	while (!strNum.empty())				//当前链表不为空
	{
		cout << strNum.front() << " ";	//获取头部.front()     获取尾部.back() 
		strNum.pop_front();				//头部删除.pop_front() 尾部删除.pop_back()
	}
	cout << endl;                       //boolalpha打印true和false
	cout << "是否为空:" << boolalpha << strNum.empty() << endl; 
	cout << "元素个数:" << strNum.size() << endl;
}
/*输出*/

string3 string1 string2                 
是否为空:false
元素个数:3
string3 string1 string2                 //string2 string1 string3
是否为空:true
元素个数:0

指定位置操作

(删除 | 插入)→  先查找

find算法→  用于查找,有3个参数

find 函数查找的数据里面有相同数据,怎么把数据的位置返回?改迭代器的位置,下一次开始的位置从上一次找到的位置开始找,直到找不到→ 再搞一个容器,找到的 result 存到新容器中

 list<list<MM>::iterator> resultlist; //存放 MM 的 result
 resultlist.push_back(result);        //然后遍历这个容器即可

自己实现find函数

函数返回值是一个迭代器(类中对象模仿指针的行为) 

list<int>::iterator myFind(list<int>& iNum,int data)     //返回迭代器
{
	for (list<int>::iterator iter = iNum.begin(); iter != iNum.end(); iter++) 
	{
		if (*iter == data) 
		{
            //返回当前迭代器
			return iter;    
		}
	}
    //没找到返回迭代器结束的位置
	return iNum.end();
}
void testlist() {
	//指定位置操作 删除、查找
	list<int> iNum;
	for (int i = 0; i < 3; i++)
	{
        //插入数据
		iNum.push_back(i);    
	}
    //从容器开始位置到容器结束的位置找一个整数 2 
	auto result = myFind(iNum,2);
    //list<int>::iterator  result = myFind(iNum, 2);
	//没找到返回是迭代器结束的位置
	if (result == iNum.end())
	{
		cout << "未找到指定位置" << endl;
	}	
//遍历
    for (auto v : iNum)
	{
		cout << v << "\t";
	}
    cout << endl;
}
int main() {
	testlist();
}
/*输出*/
0       1       2

调用标准库中的 find 函数

  • insert:在指定的迭代器前插入,返回指向插入数据的迭代器

  • erase:使作为参数的迭代器失效,并返回指向该迭代器下一参数的迭代器

指定位置插入

//先找到位置再做插入-> 指定一个位置(迭代器)  插入元素(插在指定位置前面)
iNum.insert(result, 100); 

/*输出*/
0    1    100    2

 指定位置删除

//删除函数-> 根据迭代器去做删除
iNum.erase(result);        
for(auto v : iNum) {
    cout << v << "\t";
}
/* 输出 */
0    1    100       

想把当前容器中所有相同的元素删掉

错误用法 I

引发中断

错误用法 II

正确用法 I

void testDelete() {
    int array[4] = {1,2,2,3};
    list<int>data;
    //初始化list-> 把数据拷贝到 data 中,把 2 全部删除
    data.assign(array,array + 4);       
    //相同元素的删除
	for (list<int>::iterator iter = data.begin(); iter != data.end();)
	{
        //如果当前数据等于 2,就把 2 全部删除 
		if (*iter == 2)
		{
            //当前迭代器已经被删除掉了 没办法做++运算 函数会返回下一个迭代器
			iter = data.erase(iter);  
		}
		else
		{
			iter++;
		}
	}
	for (auto v : data)
	{
		cout << v << "\t";
	}
	cout << endl;
}
int main() {
    testDelete();
}
/* 输出 */
1       3

其他操作 

排序准则

//less 和 greator 头文件
​#include <functional> 
void testlist() {
    list<int> iNumI;
//插入数据
	for (int i = 0; i < 3; i++) 
	{
		iNumI.push_back(i);      
	}
//链表反转
	iNumI.reverse();				
	for (auto v : iNumI)
	{
		cout << v << "\t";
	}
	cout << endl;
//内置排序 默认从小到大
	iNumI.sort(/*less<int>()*/);		
	for (auto v : iNumI)
	{
		cout << v << "\t";
	}
	cout << endl;
//从大到小排序
    iNumI.sort(greator<int>());		
}
int main() {
    testlist();
}

/* 输出 */
2       1       0
0       1       2
2       1       0

交换两个链表中的值

//交换两个容器中的元素 前提是元素类型相同
void testlist() {
	list<int>  iNumI{ 1,2,3,4,5 };
	list<int> iNumII{ 6,6,6,6,6,6 };
	iNumI.swap(iNumII);
	cout << "iNumI = ";
	for (auto iter = iNumI.begin(); iter != iNumI.end(); iter++)
		cout <<" " << *iter;
		cout << endl;
		cout << "iNumII= ";
	for (auto iter = iNumII.begin(); iter != iNumII.end(); iter++)
		cout << " " << *iter;
}
int main() {
	testlist();
}
/* 输出 */
iNumI  = 6 6 6 6 6 6
iNumII = 1 2 3 4 5 

操作自定义类型数据 

关键点在于重载

class MM 
{
public:
	MM(string name, int age, int num) :name(name), age(age), num(num) {}
	void print() 
	{
		cout << name << "\t" << age << "\t" << num << endl;
	}
protected:
	string name;
	int age;
	int num;
};
void testUserData() 
{
//把所有 MM 的数据存到对象中去,不可以初始化长度 只有无参构造方式 没有带参构造方式
	list<MM> mmData;
	string name;
	int age;
	int num;
	while (1)                 //插入
	{
		cout << "input MM:" << endl;
		cin >> name >> age >> num;
		mmData.push_back(MM(name, age, num));  //构造一个无名对象,尾插法插入到链表中
		cout << "是否继续输入?" << endl;
		while (cin.get() != '\n');             //清空输入缓冲区
		if (cin.get() == 'n')
			break;           //退出
	}
	cout << "姓名\t年龄\t编号" << endl;
//遍历
	for (MM/* auto */ v : mmData) 
	{
		v.print();          //每个 v 都是一个对象,容器中存的数据是 MM 类型的数据
	}
}
int main() 
{
	testUserData();
	return 0;
}
/* cin.get() 用来从指定输入流提取一个字符(包括空白字符),函数的返回值就是读入的字符 */

查找 - - - 返回一个迭代器

重载 - - - 只能按一种方式去比较,同一个运算符,参数类型相同,只能被重载一次 (弊端)

自定义类型重载: 想按什么方式比较,就重载这个运算符

class MM 
{
public:
	MM(string name, int age, int num) :name(name), age(age), num(num) {}
	void print() 
	{
		cout << name << "\t" << age << "\t" << num << endl;
	}
//比较的不是对象,对比的是对象里面的数据和name比较
	bool operator==(const string& name) const //重载==运算符
	{
		return this->name == name; 
	}
	bool operator<(const MM& object) const 
	{
		return this->name < object.name;
	}
protected:
	string name;
	int age;
	int num;
};
void testUserData() 
{
	list<MM> mmData;
//二进制“==”: 没有找到接受“MM”类型的左操作数的运算符(或没有可接受的转换)
	auto result = find(mmData.begin(), mmData.end(), string("name1")); 
//重载方式   一定要构造成string---按姓名的方式去找
	mmData.sort(less<MM>());		//重载<  排序不能直接写 需要重载
	//mmData.sort(greater<MM>());	//重载>
}
int main() 
{
	testUserData();
	return 0;
}
/* find函数决定了通过什么方式去做比较 */

不采用重载的方式,需要自己写比较准则→ 比较多样化

  • 按年龄方式比

  • 按姓名方式比

这种方式的比较,想按什么比就按什么比,都用统一的方法,只要重写函数、改函数指针即可

class MM 
{
public:
	MM(string name, int age, int num) :name(name), age(age), num(num) {}
	void print() 
	{
		cout << name << "\t" << age << "\t" << num << endl;
	}
//提供访问接口
	string getName() const
	{
		return name;                //不能返回引用,返回引用意味着类外可以修改
	}
	int getAge() const
	{
		return age;
	}
protected:
	string name;
	int age;
	int num;
};
//通过姓名的方式去比,比较的是两个对象
bool compareByName(const MM& object1, const MM& object2) //const满足常量的使用
{
	return object1.getName() < object2.getName();        //需要提供访问接口
}
//一定是返回 bool 类型
bool compareByAge(const MM& object1, const MM& object2)
{
	return object1.getAge() < object2.getAge();
}
void testData()
{
//不采用重载方式,需要自己写比较准则
    list<MM> mmData;
	mmData.sort(compareByName);    //传入函数指针
	mmData.sort(compareByAge);
}

/* tip: 1.要的函数指针是两个参数 2.bool类型的返回值 */
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐