Stack&Queue——C++

文章目录

  • 容器适配器:
  • stack
  • queue
  • deque
  • priority_queue
  • 反向迭代器

容器适配器:

适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口

不需要空间配置器
栈和队列都是适配器,是由容器转换过来的

 
 

stack

template<class T, class Container = deque<T>> class stack;

stack其实就是vector的简单封装

namespace haha
{
template<class T>
class stack
{
public:
//尽可能去复用
void push(const T& x)
{
_con.push_back(x);
}

void pop()
{
_con.pop_back();
}

T& top()
{
return _con.back();//back 访问尾部数据
}

const T& top() const
{
return _con.back();//back 访问尾部数据
}

bool empty() const
{
return _con.empty();
}

size_t size() const
{
return _con.size();
}



private:
vector<T> _con;
};
}

现在这个栈是不是一个适配器呢?
严格来说,不是。顶多是吧vector封装了一下。
适配器:只要可以满足我的功能可以无限转换,非常灵活
写死的都不是适配器(以上这个列表写死成vector了)
底层差别很大,上层都一样,都是一个栈

 

Stack.h

#include 

namespace haha
{
template<class T, class Container = deque<T>>
class stack
{
public:
//尽可能去复用
void push(const T& x)
{
_con.push_back(x);
}

void pop()
{
_con.pop_back();
}

T& top()
{
return _con.back();//back 访问尾部数据
}

const T& top() const
{
return _con.back();//back 访问尾部数据
}

bool empty() const
{
return _con.empty();
}

size_t size() const
{
return _con.size();
}



private:
/*vector _con;*/
Container _con;
};
}

void test_stack()
{
//haha::stack> st;
//haha::stack> st;
haha::stack<int> st;

st.push(1);
st.push(2);
st.push(3);
st.push(4);

while (!st.empty())
{
cout << st.top() << endl;
st.pop();
}
}

 

 

queue

queue底层不支持用vector
vector没有pop_front

Queue.h

#pragma once

#include 

namespace haha
{
template<class T, class Container = deque<T>>
class queue
{
public:
//尽可能去复用
void push(const T& x)
{
_con.push_back(x);
}

void pop()
{
_con.pop_front();
}

T& back()
{
return _con.back();//back 访问尾部数据
}

T& front()
{
return _con.front();//back 访问尾部数据
}

const T& back() const
{
return _con.back();//back 访问尾部数据
}

const T& front() const 
{
return _con.front();//back 访问尾部数据
}

bool empty() const
{
return _con.empty();
}

size_t size() const
{
return _con.size();
}



private:
Container _con;
};
}




void test_queue()
{
//haha::queue q;
haha::queue<int, list<int>> q;

// 不支持 vector没有pop_front
//haha::queue> q;
q.push(1);
q.push(2);
q.push(3);
q.push(4);

while (!q.empty())
{
cout << q.front() << endl;
q.pop();
}
}

 

deque

是一种双开口的"连续"空间的数据结构
双开口的含义是:
可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高

deque 缺省参数
deque是一个容器 双端队列

优势
1.支持任意位置的插入删除
2.支持随机访问
3.相当于vector和list的合体

deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组

小数组 buffer
数组只要有一个指针指向它就可以管理了

中控数组(指针数组):每个位置都存有一个指针
先从中间插入 头插、尾插
空间不够不是扩容而是开一个新的buffer

还支持[ ]下标访问
operator[](size_t i)
8是每个buffer的总大小
(i - 第一个buffer中的个数)/ 8 算第几个buffer
(i - 第一个buffer中的个数)% 8 算它在buffer中是第几个

设计缺陷
1.operator[]计算稍显复杂,大量使用性能下降(相比vector的operator[]的来说)
2.中间插入删除效率不高
3.从底层角度,迭代器会很复杂

结论
1.deque的头尾的插入删除非常合适,相比vector和list而言,很适合去做stack和queue的默认适配容器
2.中间插入删除多用list
3.随机访问多用vector

 

 

priority_queue

优先级队列,也是一个容器适配器
堆(二叉树)
底层数据结构是vector
默认是个大堆:因为大的优先级就高

#pragma once

namespace haha
{
// 默认大堆

template<class T, class Container = vector<T>, class Compare = std::less<T>>
class priority_queue
{
public:
 priority_queue()
{}

//迭代器区间的构造
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last)
{
while (first != last)
{
_con.push_back(*first);
++first;
}

// 建堆
for (int i = (_con.size() - 1 - 1) / 2; i >= 0; --i)
{
adjust_down(i);
}
}




// logN
void adjust_up(size_t child)
{
Compare com;
size_t parent = (child - 1) / 2;

//孩子等于大于0就结束
while (child > 0)
{
if (_con[child] > _con[parent])
//if (_con[parent] < _con[child])

//孩子大于父亲就交换

{
std::swap(_con[child], _con[parent]);
//向上走
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}

//我们push一个数据之前,数据就是堆
void push(const T& x)
{
_con.push_back(x);
//向上调整
adjust_up(_con.size() - 1);
}

// logN
void adjust_down(size_t parent)
{
Compare com;
size_t child = parent * 2 + 1;

while (child < _con.size())
{
// 选出左右孩子中大的那一个
if (child+1 < _con.size() && _con[child+1] > _con[child])
//if (child + 1 < _con.size() && _con[child] < _con[child + 1])

//默认指向左孩子,如果右>左

{
++child;
}

if (_con[child] > _con[parent])
//if (_con[parent] < _con[child])

{
std::swap(_con[child], _con[parent]);
//向下走
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}

//删除堆顶的数据
void pop()
{
std::swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();

//向下调整
adjust_down(0);
}



private:
Container _con;
};
}

 

灵活控制
C语言用函数指针
C++用仿函数

// 仿函数/函数对象  -- 类,重载operator()
// 类对象可以像函数一样去使用
namespace haha
{
/*class less
{
public:
bool operator()(const int& l, const int& r) const
{
return l < r;
}
};*/

//写成模板
 template<class T>
class less
{
public:
bool operator()(const T& l, const T& r) const
{
return l < r;
}
};

template<class T>
class greater
{
public:
bool operator()(const T& l, const T& r) const
{
return l > r;
}
};
}

int main()
{
haha::less<int> lsFunc;

cout << lsFunc(1, 2) << endl;
// 等价于下面
//cout << lsFunc.operator()(1, 2) << endl;

haha::greater<int> gtFunc;

cout << gtFunc(1, 2) << endl;


return 0;
}

PriorityQueue.h
#pragma once

namespace haha
{
// 默认大堆
// Compare进行比较的仿函数 less越来越小->大堆
// Compare进行比较的仿函数 greater越来越大->小堆
template<class T, class Container = vector<T>, class Compare = std::less<T>>
class priority_queue
{
public:
priority_queue()
{}

//迭代器区间的构造
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last)
{
while (first != last)
{
_con.push_back(*first);
++first;
}

// 建堆
for (int i = (_con.size() - 1 - 1) / 2; i >= 0; --i)
{
adjust_down(i);
}
}

// logN
void adjust_up(size_t child)
{
Compare com;
size_t parent = (child - 1) / 2;

//孩子等于大于0就结束
while (child > 0)
{
//if (_con[child] > _con[parent])
//if (_con[parent] < _con[child])

//孩子大于父亲就交换
if (com(_con[parent], _con[child]))
{
std::swap(_con[child], _con[parent]);
//向上走
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}

//我们push一个数据之前,数据就是堆
void push(const T& x)
{
_con.push_back(x);
//向上调整
adjust_up(_con.size() - 1);
}

// logN
void adjust_down(size_t parent)
{
Compare com;
size_t child = parent * 2 + 1;

while (child < _con.size())
{
// 选出左右孩子中大的那一个
//if (child+1 < _con.size() && _con[child+1] > _con[child])
//if (child + 1 < _con.size() && _con[child] < _con[child + 1])

//默认指向左孩子,如果右>左
if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
{
++child;
}

//if (_con[child] > _con[parent])
//if (_con[parent] < _con[child])
if (com(_con[parent], _con[child]))
{
std::swap(_con[child], _con[parent]);
//向下走
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}

//删除堆顶的数据
void pop()
{
std::swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();

//向下调整
adjust_down(0);
}

const T& top()
{
return _con[0];
}

bool empty()  const
{
return _con.empty();
}

size_t size() const
{
return _con.size();
}

private:
Container _con;
};
}

 
 

反向迭代器

迭代器特点

  1. 在不暴露底层实现细节的情况下,提供了统一的方式去访问容器,屏蔽了底层实现的细节,体现了封装价值的力量
  2. 是算法和容器的粘合剂

反向正向的区别:
正向++向右边走
反向++向左边走

如何实现反向迭代器呢?
普通思维:拷贝一份正向迭代器,修改一下

  1. list可以,但是vector的反向迭代器怎么办?
    (vector的正向迭代器是原生指针)
  2. 复用

reverse_iterator.h

#pragma once

namespace haha
{
// 复用 迭代器适配器
template<class Iterator, class Ref, class Ptr>
struct __reverse_iterator
{
Iterator _cur;
typedef __reverse_iterator<Iterator, Ref, Ptr> RIterator;

__reverse_iterator(Iterator it)
:_cur(it)
{}
  
   //前置

RIterator operator++()
{
--_cur;
return *this;
}

RIterator operator--()
{
++_cur;
return *this;
}

Ref operator*()
{
//return *_cur;
auto tmp = _cur;
--tmp;
return *tmp;
}

Ptr operator->()
{
//return _cur.operator->();
return &(operator*());
}

bool operator!=(const RIterator& it)
{
return _cur != it._cur;
}
};
}

 

vector

typedef T* iterator;
typedef const T* const_iterator;

typedef __reverse_iterator<iterator, T&, T*> reverse_iterator;
typedef __reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;

reverse_iterator rbegin()
{
return reverse_iterator(end());
}

reverse_iterator rend()
{
return reverse_iterator(begin());
}

iterator begin()
{
return _start;
}

iterator end()
{
return _finish;
}

const_iterator begin() const
{
return _start;
}

const_iterator end() const
{
return _finish;
}

 

list

typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;

typedef __reverse_iterator<iterator, T&, T*> reverse_iterator;
typedef __reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;


const_iterator begin() const
{
return const_iterator(_head->_next);
}

const_iterator end() const
{
return const_iterator(_head);
}

iterator begin()
{
return iterator(_head->_next);
}

iterator end()
{
return iterator(_head);
}

reverse_iterator rbegin()
{
return reverse_iterator(end());
}

reverse_iterator rend()
{
return reverse_iterator(begin());
}

你可能感兴趣的:(C++,c++,开发语言)