C++笔记打卡第19天(stack,queue,list)

1.stack容器

  • stack是一种先进后出的数据结构,只有一个出口
  • 栈中只有顶端元素才可以被外界访问,因此栈不允许有遍历行为
  • 栈中进入数据,称为入栈push
  • 栈中弹出数据,称为出栈pop

2.stack的常用接口

void test01()
{
    // 特点:符合先进后出的数据结构
    stack<int> s;
    s.push(10);
    s.push(20);
    s.push(30);
    s.push(40);
    s.push(50);

    // 只要栈不为空,就查看栈顶元素,并弹出栈
    while(!s.empty())
    {
        cout << "栈顶元素为:" << s.top() << endl;
        s.pop();
    }
    cout << "栈的大小:" << s.size() << endl;
}

3.queue容器

  • Queue是一种先进先出的数据结构,有两个出口
  • 队列允许从一端新增数据,从另一端移除数据
  • 队列中只有队头和队尾可以被外界使用,因此队列中不允许有遍历行为
  • 队列中进入数据,称为入队push
  • 队列中弹出数据,称为出队pop

4.queue常用接口

class Person
{
public:
    Person(string name, int age)
    {
        this->m_age = age;
        this->m_name = name;
    }
    int m_age;
    string m_name;
};

void test01()
{
    // 特点:符合先进先出的数据结构
    queue<Person> q;
    Person p1("唐僧",30);
    Person p2("孙悟空",1000);
    Person p3("猪八戒",900);
    Person p4("沙僧",800);

    q.push(p1);
    q.push(p2);
    q.push(p3);
    q.push(p4);

    while(!q.empty())
    {
        cout << "队头元素:" << q.front().m_name << " " << q.front().m_age << endl;
        cout << "队尾元素:" << q.back().m_name << " " << q.back().m_age << endl;
        q.pop();
    }
    cout << "队列大小:" << q.size() << endl;
}

5.list容器

  • 链表是一种物理存储单元上非连续的存储结构,数据元素的逻辑是通过链表中的指针连接实现的
  • 链表的组成:链表由一系列结点组成
  • 结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
  • STL中的链表是一个双向循环链表
  • 由于链表的存储方式并不是持续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器
  • 插入操作和删除操作都不会造成原有list迭代器的失效,这在vector里是不成立的

优点:

  • 采用动态存储分配,不会造成内存浪费和溢出
  • 链表执行插入和删除操作十分方便,修改指针即可,不需要大量移动元素

缺点:

  • 链表灵活,但是在空间(指针域)和时间(遍历)额外耗费较大

6.list构造函数

打印list中的元素:

#include <list>

void printList(const list<int> &L)
{
    for(list<int>::const_iterator it = L.begin() ; it != L.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

list构造:

void test01()
{
    list<int> L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
    printList(L1);
    
    // 以区间的方式构造
    list<int> L2(L1.begin(), L1.end());

    // 拷贝构造
    list<int> L3(L1);

    // n个elem
    list<int> L4(10, 1000);  // 10个1000
}

7.list赋值和交换

// 赋值
void test01()
{
    list<int> L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
    printList(L1);

    // operator=赋值
    list<int> L2;
    L2 = L1;

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

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

// 交换
void test02()
{
    list<int> L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);

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

    L1.swap(L2);
}

8.list 判断大小

void test01()
{
    list<int> L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
    printList(L1);

    if(L1.empty())
    {
        cout << "L1为空" << endl;
    }
    else
    {
        cout << "L1不为空" << endl;
        cout << "L1中元素个数:" << L1.size() << endl;
    }
    // 重新指定大小
    L1.resize(10);
    L1.resize(5);
}

9.list插入和删除

  • push_back(elem); 在容器尾部插入一个元素
  • pop_back(); 弹出容器中最后一个元素
  • push_front(elem):在容器开头插入一个元素
  • pop_front(); 移除容器中第一个元素
  • insert(pos, elem); 在pos位置插入elem元素的拷贝,返回新数据的位置
  • insert(pos,n,elem); 在pos位置插入n个elem数据,无返回值
  • insert(pos,begin, end); 在pos位置插入[begin,end]区间的数据,无返回值
  • clear(); 移除容器中的所有数据
  • erase(begin,end); 删除[begin,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.erase(++it)

    // 移除
    L.push_back(10000);
    L.push_back(10000);
    L.push_back(10000);
    L.remove(10000);  // 删除所有与elem值匹配的元素

    // 清空
    L.clear();
}

10.list数据存取

void test01()
{
    list<int> L;
    L.push_back(10);
    L.push_back(20);
    L.push_back(30);
    // 不可以用[]或者at的方式访问list中的元素
    // 因为list本身是一个链表,不是用连续线性空间存储数据,迭代器也是不支持随机访问的
    
    cout << "第一个元素:" << L.front() << endl;
    cout << "最后一个元素:" << L.back() << endl;

    // 验证迭代器是不支持随机访问的
    list<int>::iterator it = L.begin();
    it++;  // 正确,支持双向
    it--;  // 正确
    // it = it + 1; it = it + 2; 错误,不支持随机访问    
}

11.list反转和排序

  • reverse(); 反转链表
  • sort(); 排序
void test01()
{
    list<int> L;
    L.push_back(20);
    L.push_back(50);
    L.push_back(30);
    L.push_back(10);
    L.push_back(60);

    // 反转
    L.reverse();  // 60 10 30 50 20    
}

bool myCompare(int v1, int v2)
{
    // 降序 让第一个数大于第二个数
    return v1 > v2;
}

void test02()
{
    list<int> L;
    L.push_back(20);
    L.push_back(50);
    L.push_back(30);
    L.push_back(10);
    L.push_back(60);

    // 排序
    // sort(L.begin(), L.end()); 错误,所有不支持随机访问迭代器的容器,都不能用标准算法
    // 不支持随机访问迭代器的容器,内部会提供对应的一些算法
    L.sort();  // 默认排序规则:升序
    L.sort(myCompare);  // 指定规则:降序
}

12.排序案例

将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高。按照年龄进行升序,如果年龄相同按照身高进行降序。

class Person
{
public:
    Person(string name, int age, int height)
    {
        this->m_name = name;
        this->m_age = age;
        this->m_height = height;
    }
    string m_name;
    int m_age;
    int m_height;
};

bool myComparePerson(Person &p1, Person &p2)
{
    // 升序
    if(p1.m_age == p2.m_age)
    {
        // 年龄相同,按降序
        return p1.m_height > p2.m_height;
    }
    return p1.m_age < p2.m_age;
}

void test01()
{
    list<Person> L;
    Person p1("小王", 18, 160);
    Person p2("小绿", 24, 186);
    Person p3("小黑", 20, 177);
    Person p4("小紫", 20, 156);
    Person p5("小胡", 16, 188);

    L.push_back(p1);
    L.push_back(p2);
    L.push_back(p3);
    L.push_back(p4);
    L.push_back(p5);

    // 排序
    L.sort(myComparePerson);

    for(list<Person>::iterator it = L.begin(); it != L.end(); it++)
    {
        cout << "姓名:" << it->m_name << " 年龄:" << it->m_age << " 身高:" << it->m_height << endl; 
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值