C++STL——stack与queue

简介: C++STL——stack与queue

stack与queue

这两个就是之前数据结构学过的栈和队列,只不过多了几个接口。

stack:

queue:

这两个容器没有迭代器,这是因为怕我们更改导致顺序错误。

#include<iostream>
#include<stack>
#include<queue>
int main()
{
  stack<int> a;
  a.push(1);
  a.push(2);
  a.push(3);
  a.push(4);
  a.push(5);
  queue<int> b;
  b.push(6);
  b.push(7);
  b.push(8);
  b.push(9);
  b.push(0);
  while (!a.empty())
  {
    cout << a.top() << ' ';
    a.pop();
  }
  cout << endl;
  while (!b.empty())
  {
    cout << b.front() << ' ';
    b.pop();
  }
  return 0;
}

priority_queue

这个容器是优先级队列,看起来是队列,其实内部结构并不是队列,而是一个堆。

#include<iostream>
#include<queue>
int main()
{
  priority_queue<int> a;//大堆
  priority_queue<int, vector<int>, greater<int>> b;//小堆
  a.push(3);
  a.push(0);
  a.push(9);
  a.push(5);
  a.push(6);
  while (!a.empty())
  {
    cout << a.top() << ' ';
    a.pop();
  }
  cout << endl;
  b.push(3);
  b.push(0);
  b.push(9);
  b.push(5);
  b.push(6);
  while (!b.empty())
  {
    cout << b.top() << ' ';
    b.pop();
  }
  return 0;
}

容器适配器

什么是适配器呢?生活中我们用的充电器就是,一个充电器可以给好几种手机使用。

适配器是一种设计模式:该种模式是将一个类的接口转换成客户希望的另外一个接口。

vector与list的反向迭代器模拟实现

实现的目的主要是要求无论是list还是vector都可以用这个反向迭代器。

反向迭代器其实是迭代器位置变了而已,反向迭代器的begin与正向的end,反向迭代器的end与正向的begin指向同一个位置。

namespace baiye
{
  template<class Iterator, class Ref, class Ptr>
  struct Reverse_iterator
  {
    typedef Reverse_iterator<class Iterator, class Ref, class Ptr> self;
    Reverse_iterator(Iterator it)
      :_it(it)
    {}
    Ref operator*()//区别是否有const
    {
      Iterator tmp = _it;
      return *(--tmp);//因为begin是指向正向迭代器end的原因,所以需要--
    }
    self operator++()
    {
      _it--;
      return *this;
    }
    self operator--()
    {
      _it++;
      return *this;
    }
    bool operator!=(const Iterator it)const
    {
      return it != _it;
    }
    Ref operator->()
    {
      return &(operator*());
    }
    Iterator _it;//反向迭代器的本质
  };
}

仿函数

#include<iostream>
using namespace std;
namespace baiye
{
  template<class T>
  struct greater_than
  {
    bool operator()(const T& a, const T& b)
    {
      return a > b;
    }
  };
  template<class T>
  struct less_than
  {
    bool operator()(const T& a, const T& b)
    {
      return a < b;
    }
  };
}
int main()
{
  int a = 4;
  int b = 0;
  int c = 5;
  baiye::greater_than<int> compare;
  baiye::less_than<int> contrast;
  int sum = compare(a, b);
  cout << sum << endl;
  sum = compare(a, c);
  cout << sum << endl;
  sum = contrast(a, b);
  cout << sum << endl;
  sum = contrast(a, c);
  cout << sum << endl;
  return 0;
}

仿函数其实是一个类,在函数回调他用起来比函数地址好用,如果在某一段代码需要用到函数回调,这个函数的参数特别多,写出来之后会破坏代码看起来的美感。

deque(了解)

这是一个双端队列。他是vector与list的结合体,但是又没有vector与list在某一方面好用。

链接:https://legacy.cplusplus.com/reference/deque/deque/?kw=deque

大概的结构是这样的:

图片出自侯捷老师的《STL源码剖析》。

在开辟一个deque类的时候会有一个指针数组,里面的指针指向了模板的类型,

cur是指向数组当前访问的位置,first是指向第一个位置,last指向末尾,node不是和他们三个一个层次的,而是指向指针数组的指针。

在如果一个fairse指向的空间满了,头插就会在node指向元素的下一个位置开辟空间,在第一个位置进行插入,如果想头插就会在node指向的前一个元素进行空间开辟,然后再末尾的位置进行数据写入。

cur是用来遍历node指向的内容的,他是用来实现++,- -的。

stack与queue模拟实现

stack

namespace baiye
{
    template<class T, class Con = deque<T>>//这里也可以用list或者vector
    class stack
    {
    public:
        stack()
        {}
        void push(const T& x)
        {
            _c.push_back(x);
        }
        void pop()
        {
            _c.pop_back();
        }
        T& top()
        {
            return _c.back();
        }
        const T& top()const
        {
            return _c.back();
        }
        size_t size()const
        {
            return _c.size();
        }
        bool empty()const
        {
            return _c.empty();
        }
    private:
        Con _c;
    };
}

queue

namespace baiye
{
    template<class T, class Con = deque<T>>
    class queue
    {
    public:
        queue()
        {}
        void push(const T& x)
        {
            _c.push_back(x);
        }
        void pop()
        {
            _c.pop_front();
        }
        T& back()
        {
            return _c.back();
        }
        const T& back()const
        {
            return _c.back();
        }
        T& front()
        {
            return _c.front();
        }
        const T& front()const
        {
            return _c.front();
        }
        size_t size()const
        {
            return _c.size();
        }
        bool empty()const
        {
            return _c.empty();
        }
    private:
        Con _c;
    };
}

priority_queue模拟实现

priority_queue

#include<iostream>
#include<stack>
#include<queue>
#include<deque>
#include<list>
#include<vector>
#include<algorithm>
using namespace std;
namespace baiye
{
    template<class T>
    struct less
    {
        bool operator()(const T& a, const T& b)
        {
            return a < b;
        }
    };
    template <class T, class Container = vector<T>, class Compare = less<T> >
    class priority_queue
    {
    public:
        void adjust_up(size_t child)//向上调整
        {
            Compare com;//仿函数
            while (child > 0)
            {
                if(com(c[(child - 1) / 2], c[child]))
                {
                    swap(c[child], c[(child - 1) / 2]);
                    child = (child - 1) / 2;
                }
                else
                {
                    break;
                }
            }
        }
        void adjust_down(size_t parent)//向下调整
        {
            size_t left = parent * 2 + 1;//左孩子
            Compare com;//仿函数
            while (left < c.size())
            {
                if (left + 1 < c.size() && com(c[left], c[left + 1]))
                {
                    left++;
                }
                if (com(c[parent], c[left]))
                {
                    swap(c[left], c[parent]);
                    parent = left;
                    left = parent * 2 + 1;
                }
                else
                {
                    break;
                }
            }
        }
        priority_queue()
        {}
        template <class InputIterator>
        priority_queue(InputIterator first, InputIterator last)
            :c(first,last)
        {
            for (int i = (c.size() - 2) / 2; i >= 0; i--)//建堆
            {
                adjust_down(i);
            }
        }
        bool empty() const
        {
            return c.empty();
        }
        size_t size() const
        {
            return c.size();
        }
        const T& top() const
        {          
            return c[0];
        }
        void push(const T& x)
        {
            c.push_back(x);
            adjust_up(c.size()-1);
        }
        void pop()
        {
            swap(c[0], c[c.size() - 1]);
            c.pop_back();
            adjust_down(0);
        }
    private:
        Container c;
    };
}


相关文章
|
17天前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
44 4
|
19天前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
44 5
|
19天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
29 2
|
24天前
|
存储 算法 Linux
【c++】STL简介
本文介绍了C++标准模板库(STL)的基本概念、组成部分及学习方法,强调了STL在提高编程效率和代码复用性方面的重要性。文章详细解析了STL的六大组件:容器、算法、迭代器、仿函数、配接器和空间配置器,并提出了学习STL的三个层次,旨在帮助读者深入理解和掌握STL。
40 0
|
3天前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
13 0
|
25天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
59 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
65 4
|
1月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
74 4
|
2月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
30 4
|
2月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
26 4