c++ STL容器 --- 双向链表list
包含头文件<list>list<int> iNum;//创建一个list对象,存放整型数据模板类型:存储数据类型:int自己写链表需要写释放内存,对于标准库的list内存不需要你去处理,最后会自动释放(便捷)用到链表的地方,都可以使用list去替换处理基本数据类型插入void testList(){list<string> strNum;strNum.push_
·
包含头文件 <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类型的返回值 */
更多推荐
已为社区贡献1条内容
所有评论(0)