本章将会讲解容器适配器的底层逻辑实现,是我学到的主流写法。当作是我学习理解的笔记。
基本上这个思维导图,就是所有相关的内容。
1.stack
栈,先进后出,只有栈顶的元素也就是_con.back()。实现代码如下:
#pragma once
#include <iostream>
#include <vector>
#include <list>
#include<deque>
namespace djx
{
template<class T, class Container = deque<T>>
class stack
{
public:
void push(T x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_back();
}
size_t size()
{
return _con.size();
}
const T& top()//设计为栈顶元素
{
return _con.back();
}
bool empty()
{
return _con.empty();
}
private:
Container _con;
};
}
2. 队列
先进先出,有队首、尾的数据之分。适配器就是去调用别的容器的内容。
#pragma once
#include <iostream>
#include <vector>
#include <list>
#include <deque>
//queue 是一种适配器,直接使用其他容器的模板就可以
namespace djx
{
template<class T, class Container = deque<T>>
class queue
{
public:
//队列具有:先进先出、队首,尾的值
void push(const T& x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_front();
}
const T& back()
{
return _con.back();
}
const T& front()
{
return _con.front();
}
size_t size()
{
return _con.size();
}
bool empty()
{
return _con.empty();
}
private:
Container _con;//就是去使用默认的 deque 的结构
};
}
3.优先级队列
本质上就是堆的实现。(由于库 swap 函数总是报错,所以我自己又定义了一个函数)
#pragma once
#include <iostream>
#include <vector>
#include <list>
#include <deque>
//优先级队列在默认的时候,本质上就是一个大堆
//在打印输出的时候(默认)大的先输出
namespace djx
{
template<class T>
class less
{
public:
bool operator()(const T& x1, const T& x2)
{
return x1 < x2;//如果是 x1 小于 x2 就是ture
}
};
template<class T>
class greater
{
public:
bool operator()(const T& x1, const T& x2)
{
return x1 > x2;
}
};
template<class T, class Container = vector<T>, class Comper = less<T>>
class priority_queue
{
public:
void swap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp;
}
void push(const T x)
{
//进行插入操作的时候先建立一个大堆,放到最后面,然后需要使用向上调整算法进行排序
_con.push_back(x);
adjust_up(_con.size() - 1);
}
//void adjust_up(int n)
//{
// int child = n;
// int parent = (n - 1) / 2;
// while (child > 0)
// {
// //之前的就一直是大堆,所以在放入的时候就是判断 孩子 与 父亲的大小
// if (_con[child] > _con[parent])
// {
// swap(_con[child], _con[parent]);
// child = parent;
// parent = (child - 1) / 2;
// }
// else break;
// }
//}
//对上面的进行优化,使用 less 函数
void adjust_up(int n)
{
Comper _cmp;
int child = n;
int parent = (n - 1) / 2;
while (child > 0)
{
//之前的就一直是大堆,所以在放入的时候就是判断 孩子 与 父亲的大小
if(_cmp(_con[parent], _con[child]))
//if (_con[child] > _con[parent])
{
swap(_con[child], _con[parent]);
child = parent;
parent = (child - 1) / 2;
}
else break;
}
}
void adjust_down(int n)
{
int parent = n;
int child = parent * 2 + 1;
while (child < _con.size())
{
//找到左孩子与右孩子的最大值
Comper _cmp;
if (child + 1 < _con.size() && _cmp(_con[child], _con[child + 1]))
//if (child + 1 < _con.size() && _con[child] < _con[child + 1])//还需要确保一定有右孩子
{
child++;
}
if(_cmp(_con[parent], _con[child]))
//if (_con[child] > _con[parent])
{
swap(_con[child], _con[parent]);
parent = child;
child = parent * 2 + 1;
}
else break;
}
}
void pop()
{
//首先先将第一个位置的值给交换下来
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
adjust_down(0);
}
int size()
{
return _con.size();
}
bool empty()
{
return _con.empty();
}
const T& top()
{
return _con[0];
}
private:
Container _con;
};
}
结尾
以上是对于STL中适配器简单实现,如果是日常使用直接使用库函数即可。这是我的调试代码存放在了gitee之中Practice: 日常的练习。这个文章用于我的学习记录,如果是有其他的错误还请批评指正。如果对你有帮助还请给我点个赞👍👍👍。