C++之list(链表)

list

基本概念及结构

功能:将数据进行链式存储

链表由一个个结点组成 结点由数据域和指针域组成 数据域存放当前位置的数据 指针域维护下一个结点数据域的地址

在这里插入图片描述

链表的优缺点

优点

采用动态储存分配,不会造成内存浪费和溢出

可以对任意位置进行快速插入或删除元素

插入时 将新结点的指针域指向下一结点的数据域地址,其前一节点的指针域指向新结点的数据域地址即可,不用移动其他位置上的数据

缺点

容器遍历速度没有数组快,需要找指针域进行遍历,且占用的空间大于数组

list有一个重要的特性,插入操作和删除操作都不会造成原有list迭代器失效,这在vector是不成立的

STL中的链表结构

STL中的链表是一个双向循环链表 指针域存放的指针有两个,为前一结点的指针域和后一节点的指针域

在这里插入图片描述

图中并没有进行循环 第一个结点指针域中prev指针指向最后一个结点的数据域 而最后一个结点的next指针指向第一关结点的数据域

由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器

默认构造

list<T> lst; //list采用采用模板类实现,对象的默认构造形式:
list(beg,end); //构造函数将[beg, end)区间中的元素拷贝给本身。
list(n,elem); //构造函数将n个elem拷贝给本身。
list(const list &lst); //拷贝构造函数。
示例
//list容器的构造函数
void test01() {
    list<int>L1;//创建list容器
    L1.push_back(10);//添加数据
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);

    list<int>L2(L1.begin(), L1.end());//区域方式构造
    list<int>L3(L2);//拷贝构造
    list<int>L4(4,100);//n个elem构造
}

赋值和交换操作

assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem); //将n个elem拷贝赋值给本身。
list& operator=(const list &lst); //重载等号操作符
swap(lst); //将lst与本身的元素互换。
示例
void test01() {
    list<int>L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
    
    list<int>L2;
    L2 = L1;

    list<int>L3;
    L3.assign(L2.begin(), L2.end());

    list<int>L4;
    L4.assign(10, 100);

    list<int>L5;
    L1.swap(L5);
}

大小操作

size(); //返回容器中元素的个数
empty(); //判断容器是否为空

resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。

resize(num, elem);重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
如果容器变短,则末尾超出容器长度的元素被删除。
示例
void test01()
{
	list<int>L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);

	if (L1.empty())
	{
		cout << "L1为空" << endl;
	}
	else
	{
		cout << "L1不为空" << endl;
		cout << "L1的大小为: " << L1.size() << endl;
	}

	//重新指定大小
	L1.resize(10);
	
	L1.resize(15,100);
}

插入和删除

push_back(elem);//在容器尾部加入一个元素
pop_back();//删除容器中最后一个元素
push_front(elem);//在容器开头插入一个元素
pop_front();//从容器开头移除第一个元素
insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除pos位置的数据,返回下一个数据的位置。
remove(elem);//删除容器中所有与elem值匹配的元素。
示例
void test01()
{
	list<int> L;
	//尾插
	L.push_back(10);
	L.push_back(20);
	L.push_back(30);
	//头插
	L.push_front(100);
	L.push_front(200);
	L.push_front(300);


	//尾删
	L.pop_back();

	//头删
	L.pop_front();

	//插入
	list<int>::iterator it = L.begin();
	L.insert(++it, 1000);

	//删除
	it = L.begin();
	L.erase(++it);

	//移除
	L.push_back(10000);
	L.remove(10000);//会将链表里所有10000移除
    
    //清空
	L.clear();
	printList(L);
}

尾插 — push_back 尾删 — pop_back 头插 — push_front 头删 — pop_front

插入 — insert 删除 — erase 移除 — remove 清空 — clear

数据存取

front(); //返回第一个元素
back();	//返回最后一个元素

list不支持[]和at的访问原因:

list本质是链表,不是连续的线性空间存储数据,迭代器也不支持随机访问

list<int>::iterator it = L.begin();
it = it + 2; //错误,不可以随机访问
it ++ ; //正确,支持双向

反转和排序

reverse();//反转
sort();//排序
bool myCompare(int val1 , int val2)
{
	return val1 > val2;
}

//反转和排序
void test01()
{
	list<int> L;
	L.push_back(90);
	L.push_back(30);
	L.push_back(20);
	L.push_back(70);
	printList(L);

	//反转容器的元素
	L.reverse();//倒序输出
	printList(L);

	//排序
	L.sort(); //默认的排序规则 从小到大
	printList(L);

	L.sort(myCompare); //指定规则,从大到小
	printList(L);
}

排序的案例

#include<iostream>
#include<cstring>
#include<algorithm>
#include<list>
using namespace std;


class player {
public:
    player(string name, int age, int high) {
        this->name = name;
        this->age = age;
        this->high = high;
    }
    string name;
    int age;
    int high;

    void printff() {
        cout << "姓名:" << this->name << "年纪:" << this->age << "身高:" << this->high << endl;
    }
};

void print(list<player>& L) {
    for (list<player>::iterator it = L.begin(); it != L.end(); it++) {
        it->printff();
    }
}

//自己写的 麻烦了
//bool antt(const player& p1, const player& p2) {
//    if (p1.age <  p2.age) {
//        return true;
//    }
//    else if (p1.age > p2.age) {
//        return false;
//    }
//    else {
//        if (p1.high < p2.high)
//            return true;
//        else
//            return false;
//    }
//}
bool antt(const player& p1, const player& p2) {
    if (p1.age == p2.age) {
        return p1.high < p2.high;
    }
    return p1.age < p2.age;
}

void test01() {
    player p1("小赵", 18, 180);
    player p2("大牛", 27, 170);
    player p3("林五", 19, 181);
    player p4("赵武", 18, 167);
    player p5("马九", 16, 178);
    list<player>L;
    L.push_back(p1);
    L.push_back(p2);
    L.push_back(p3);
    L.push_back(p4);
    L.push_back(p5);

    cout << "排序前:" << endl;
    print(L);
    L.sort(antt);
    cout << "------------------------------------------------------" << endl;
    cout << "排序后:" << endl;
    print(L);
}

int main() {
    test01();
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值