一、栈模拟实现
适配器
1 容器适配器 :
容器适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现,主要有stack,queue,priority_queue。对于给定的适配器,其关联的容器必须满足一定的约束条件。stack适配器所关联的基础容器可以是任何一种顺序容器类型,stack栈可以建立在vector、list、deque容器之上。而queue适配器要求其关联的基础容器必须提供push_front运算,因此只能建立在list和deque容器上,而不能建立在vector容器上。priority_queue适配器要求提供随机访问功能,因此可建立vector或deque容器上,但不能建立在list容器上。默认情况下,stack和queue都基于deque容器实现,priority_queue在vector容器上实现。
2 函数适配器:
函数适配器是用来让一个函数对象表现出另外一种类型的函数对象的特征。因为,许多情况下,我们所持有的函数对象或普通函数的参数个数或是返回值类型并不是我们想要的,这时候就需要函数适配器来为我们的函数进行适配,函数适配器主要用于特化和扩展一元,二元函数对象,函数适配器主要有以下两类:
绑定器:该类适配器用于将二元函数适配成一元函数,将二元函数的一个参数绑定到一个特定的值上,将二元函数对象转换成一元函数对象。绑定器适配器有两种:bind1st bind2nd。每个绑定器接受一个函数对象和一个值。 bind1st将给定值绑定到二元函数对象的第一个实参 bind2nd将给定值绑定到二元函数对象的第二个实参。
取反器 将函数对象的结果真值求反。取反器有两种:not1和not2,not1是对一元函数对象求反的取反器,传递给函数对象的只有一个参数,则要使用这个not1,not2是对二元函数对象求反的取反器。
3 迭代器适配器:扩展迭代器的功能,主要有:插入迭代器,反向迭代器,流迭代器。
二、队列模拟实现
三、优先队列(堆)
仿函数
**仿函数,也被称为函数对象,是一种使得类的使用看上去像一个函数的编程技巧。其实现方式是在类中重载operator()方法**。
仿函数在C++编程中具有重要的地位和广泛的应用场景。它不仅能够提高代码的复用性和维护性,还可以通过状态存储、模板参数化以及提升运行效率等方式增强程序的功能性和灵活性。仿函数是C++程序员解决复杂问题的重要工具之一,通过合理应用仿函数,可以大大提升代码的质量和性能。
此处将仿函数进一步模板化以适应不同数据类型
默认构造与迭代器范围构造
建堆
向上调整建堆的效率通常要高于向下调整建堆。在构建堆结构时,向上调整和向下调整是两种不同的方法,这两种方法各有特点,但它们在时间复杂度上是相似的,主要区别在于具体的操作过程和效率。向上调整建堆通常更加直观且易于实现。可以通过以下几点来分析:
1. **时间复杂度**
- **向上调整**:对于包含n个元素的数组,建立小根堆的时间复杂度为O(n)。这是因为每个插入操作的时间复杂度为O(log n),而建堆过程中每个元素至多移动一次,所以总的时间复杂度是线性的。
- **向下调整**:虽然向下调整的时间复杂度也是O(n),但在实际操作中需要确保子树已经是堆结构才能进行向下调整,这可能在某些情况下导致额外的操作。
2. **操作便利性**
- **向上调整**:从叶子节点开始,逐个进行向上调整,无需其他前提条件,操作相对简单直接。
- **向下调整**:必须确保从根节点到进行调整的节点路径上的子树都是堆结构,否则不能正确调整,这使得操作相对复杂。
3. **适用场景**
- **向上调整**:适用于从无序数据开始建立堆的情况,如初始化建堆。
- **向下调整**:适用于部分更新堆的情况,例如删除或替换堆顶元素后的调整。
4. **实现难度**
- **向上调整**:代码实现比较简洁,逻辑清晰。
- **向下调整**:需要处理子树是堆的前提条件,实现较为复杂。
综上所述,向上调整在大多数情况下更为高效,特别是在从头开始建堆的情况下,其操作简便、代码简洁且易于理解。但在特定场合,如对堆顶元素进行替换后需要重新调整堆时,向下调整则可能是必要的步骤。因此,具体选择哪种方法取决于具体的应用场景和需求。
优先队列中的基本操作
操作均由适配器的成员函数完成,注意优先队列的操作后要维持堆结构