目录
1.stack
#pragma once
#include<vector>
#include<list>
#include<deque>
namespace bit//将实现的栈封装到bit中
{
// 常规实现数据结构的思路
//template<class T>
//class stack
//{
//public:
// // ....
//private:
// T* _a;
// size_t _size;
// size_t _capacity;
//};
// 容器适配器
//template<class T, class Container = std::vector<T>>
//template<class T, class Container = std::list<T>>
template<class T, class Container = std::deque<T>>
class stack
{
public:
void push(const T& x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_back();
}
/*T top()
{
return _con.back();
}*/
const T& back()
{
return _con.back();
}
size_t size()
{
return _con.size();
}
bool empty()
{
return _con.empty();
}
private:
Container _con;
};
}
stl源码中的实现
测试:使用string类型数据时容易出现溢出或者截断,存入数据300测试
void test_stack()
{
//stack<int> s;
stack<int, vector<int>> s;
//stack<int, list<int>> s;
//stack<int, string> s; // ????
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.push(300);
while (!s.empty())
{
cout << s.top() << " ";
s.pop();
}
cout << endl;
}
300转换为44 ,故stack<int,string>s存在截断数据丢失的风险
2.queue
#pragma once
namespace bit
{
// list
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 front()
{
return _con.front();
}*/
const T& front()
{
return _con.front();
}
/*T back()
{
return _con.back();
}*/
const T& back()
{
return _con.back();
}
size_t size()
{
return _con.size();
}
bool empty()
{
return _con.empty();
}
private:
Container _con;
};
}
注:队列不能使用vector适配,因为vector不支持pop_front()的接口
3.优先级队列priority_queue
#pragma once
namespace bit
{
template<class T>
//仿函数/函数对象 -- 对象可以像调用函数一样去使用
struct less
{
bool operator()(const T& l, const T& r)//仿函数重载运算符
{
return l < r;
}
};
template<class T>
struct greater
{
bool operator()(const T& l, const T& r)
{
return l > r;
}
};
template<class T, class Container = vector<T>, class Compare = std::less<T>>
class priority_queue
{
public:
//typedef typename Container::value_type VT;
void AdjustUp(size_t child)
{
Compare com;//compare是一个仿函数
size_t parent = (child - 1) / 2;
while (child > 0)
{
//if (_con[parent] > _con[child])
if (com(_con[parent], _con[child]))//使用仿函数比较
{
swap(_con[parent], _con[child]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
void push(const T& x)
{
_con.push_back(x);
AdjustUp(_con.size() - 1);
}
void AdjustDwon(size_t parent)
{
Compare com;
size_t child = parent * 2 + 1;
while (child < _con.size())
{
//if (child+1 < _con.size() && _con[child] > _con[child+1])
if (child+1 < _con.size() && com(_con[child], _con[child+1]))//使用仿函数比较
{
++child;
}
//if (_con[parent] > _con[child])
if (com(_con[parent], _con[child]))
{
swap(_con[parent], _con[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void pop()
{
assert(!_con.empty());
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
AdjustDwon(0);
}
T top()
{
return _con[0];
}
size_t size()
{
return _con.size();
}
bool empty()
{
return _con.empty();
}
private:
Container _con;
};
}
对于插入函数接口,使用向上调整使之为堆
void push(const T& x)
{
_con.push_back(x);
AdjustUp(_con.size() - 1);
}
测试
void test_priority_queue()
{
/*less<int> LessCom;
cout << LessCom(1, 2) << endl;
greater<int> GreaterCom;
cout << GreaterCom(1, 2) << endl;*/
//priority_queue<int> pq;
priority_queue<int, vector<int>, greater<int>> pq;
pq.push(2);
pq.push(5);
pq.push(1);
pq.push(6);
pq.push(8);
while (!pq.empty())
{
cout << pq.top() << " ";
pq.pop();
}
cout << endl;
}
优先级队列额外的构造函数(通过区间构造)
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last,
const Compare& comFunc = Compare())
: _comFunc(comFunc)
{
while (first != last)
{
_con.push_back(*first);
}
//建堆
for (int i = (_con.size() - 1 - 1) / 2; i >= 0; --i)
{
AdjustDown(i);
}
}
解决TopK问题:建立大堆
void test_priotity_queue2()
{
int a[] = { 1,4,2,7,8,9 };
priority_queue<int>pq(a,a+6);
}
4.仿函数
仿函数与函数指针
template<class T>
struct less
{
bool operator()(const T& x, const T& y) const
{
return x < y;
}
};
template<class T>
struct greater
{
bool operator()(const T& x, const T& y) const
{
return x > y;
}
};
// 优先级队列 -- 大堆 < 小堆 >
template<class T, class Container = vector<T>, class Compare = less<T>>
class priority_queue
{
public:
priority_queue(const Compare& comFunc = Compare())
:_comFunc(comFunc)
{}
void AdjustUp(int child)
{
//Compare comFunc;
int parent = (child - 1) / 2;
while (child > 0)
{
//if (_con[parent] < _con[child])
if (comFunc(_con[parent], _con[child]))
{
swap(_con[parent], _con[child]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
void push(const T& x)
{
_con.push_back(x);
AdjustUp(_con.size() - 1);
}
void AdjustDown(int parent)
{
//Compare comFunc;
size_t child = parent * 2 + 1;
while (child < _con.size())
{
//if (child+1 < _con.size() && _con[child] < _con[child+1])
if (child + 1 < _con.size() && _comFunc(_con[child], _con[child + 1]))
{
++child;
}
//if (_con[parent] < _con[child])
if (comFunc(_con[parent], _con[child]))
{
swap(_con[parent], _con[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void pop()
{
assert(!_con.empty());
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
AdjustDown(0);
}
const T& top()
{
return _con[0];
}
size_t size()
{
return _con.size();
}
bool empty()
{
return _con.empty();
}
private:
Compare _comFunc;
Container _con;
};
void test_priority_queue()
{
/*less<int> LessCom;
cout << LessCom(1, 2) << endl;
greater<int> GreaterCom;
cout << GreaterCom(1, 2) << endl;*/
//priority_queue<int> pq; //使用缺省的 大堆
//priority_queue<int, vector<int>, greater<int>> pq; //传仿函数 小堆
priority_queue<int, vector<int>, bool(*)(int, int)>pq; //传函数指针
pq.push(2);
pq.push(5);
pq.push(1);
pq.push(6);
pq.push(8);
while (!pq.empty())
{
cout << pq.top() << " ";
pq.pop();
}
cout << endl;
}
}
调用默认构造函数初始化后,测试样例中传函数指针出现崩溃。传入函数指针时,compare就为函数指针,用函数指针定义了一个缺省的对象
此处显式地传了一个参数,其类型就没有用less,用的函数指针(内置类型)。用函数指针定义一个缺省的对象就是空指针,空指针此处调用不了东西
程序运行的思路
不用默认构造函数初始化,函数指针作为内置类型的成员,我们不初始化时为随机值
使传入函数指针后可成功运行的调整:在构造函数时把函数指针传递过去(函数名即为函数指针)
显式地写greater和less
默认情况下使用库里面的greater和less即可,某些情况下需要显式实现greater和less
void test_Functional()
{
vector<int>v;
v.push_back(2);
v.push_back(1);
v.push_back(4);
v.push_back(5);
v.push_back(3);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
//less
sort(v.begin(),v.end());//传迭代器区间,默认按升序排序
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
}
若想实现降序。此处传的是greater的对象
//greater
sort(v.begin(), v.end(), greater<int>());
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
对数组进行排序
//指向数组的原生指针本省就是天然的迭代器
int a[6] = { 1,2,5,2,5,7 };
sort(a, a + 6);
sort(a, a + 6, greater<int>());
若存在自定义类型的数组或者vector里面存储的是自定义类型,则需要写仿函数
struct Goods
{
string _name;
double _price;
size_t _saleNum;
//...
bool operator<(const Goods& g1, const Goods& g2)const
{
return _price < g.price;
}
};
Goods gds[4] = { { "苹果", 2.1, 1000}, { "香蕉", 3.0, 200}, { "橙子", 2.2,300}, { "菠萝", 1.5,50} };
sort(gds, gds + 4);
若想按价格,可写一个仿函数按价格排序
struct LessPrice
{
bool operator<(const Goods& g1, const Goods& g2)const
{
return g1._price < g2._price;
}
};
struct GreaterPrice
{
bool operator<(const Goods& g1, const Goods& g2)const
{
return g1._price > g2._price;
}
};
按销量来比较
struct LessSaleNum
{
bool operator<(const Goods& g1, const Goods& g2)const
{
return g1._saleNum < g2._saleNum;
}
};
struct GreaterSaleNum
{
bool operator<(const Goods& g1, const Goods& g2)const
{
return g1._salNum > g2._salNum;
}
};