《程序设计实习》之【容器适配器】

容器适配器

  • 可以用某种顺序容器来实现(让已有的顺序容器以栈/队列的方式工作)
  • 1) stack: 头文件<stack>
    • 栈 – 后进先出
  • 2) queue: 头文件<queue>
    • 队列 – 先进先出
  • 3) priority_queue: 头文件<queue>
    • 优先级队列 – 最高优先级元素总是第一个出列
  • 都有3个成员函数:
    • push: 添加一个元素
    • top: 返回栈顶部或队头元素的引用
    • pop: 删除一个元素
  • 容器适配器上没有迭代器 ->STL中各种排序,查找,,变序等算法都不适合容器适配器

stack

  • stack是后进先出的数据结构
  • 只能插入,删除,访问栈顶的元素
  • 可用 vector, list, deque来实现
    • 缺省情况下, 用deque实现
    • 用 vector和deque实现, 比用list实现性能好
template<class T, class Cont = deque<T> >
class stack {
    …
};
  • stack 中主要的三个成员函数:
    • void push(const T & x);将x压入栈顶
  • void pop();弹出(即删除)栈顶元素
  • T & top();返回栈顶元素的引用,通过该函数, 可以读取栈顶元素的值, 也可以修改栈顶元素

queue

  • 和stack 基本类似, 可以用 list和deque实现
  • 缺省情况下用deque实现
template<class T, class Cont = deque<T> >
class queue { 
    ……
};
  • 同样也有push, pop, top函数
    • push发生在队尾
    • pop, top发生在队头, 先进先出

priority_queue

  • 和 queue类似, 可以用vector和deque实现
  • 缺省情况下用vector实现
  • priority_queue 通常用堆排序技术实现, 保证最大的元素总是在最前面
    • 执行pop操作时, 删除的是最大的元素
    • 执行top操作时, 返回的是最大元素的引用
  • 默认的元素比较器是 less

基本数据类型的优先级设置

此处指的基本数据类型就是 int 型,double 型,char 型等可以直接使用的数据类型,优先队列对他们的优先级设置一般是数字大的优先级高,因此队首元素就是优先队列内元素最大的那个(如果是 char 型,则是字典序最大的)。

//下面两种优先队列的定义是等价的
 priority_queue<int> q;
 priority_queue<int, vector<int>, less<int> >; //后面有一个空格

  其中第二个参数( vector ),是来承载底层数据结构堆的容器,第三个参数( less ),则是一个比较类,less 表示数字大的优先级高,而 greater 表示数字小的优先级高

如果想让优先队列总是把最小的元素放在队首,只需进行如下的定义:

priority_queue<int, vector<int>, greater<int> >q;

示例代码:

#include <iostream>
#include <queue>
using namespace std;

int main() {
    priority_queue<double> priorities;
    //priority_queue<double, vector<double>, greater<double> > priorities;
    priorities.push(3.2);
    priorities.push(9.8);
    priorities.push(5.4);
    while (!priorities.empty()) {
        cout << priorities.top() << " ";
        priorities.pop();
    }
    cout << endl;
}

输出结果:

9.8 5.4 3.2

若定义队列为注释中的形式,则输出结果:

3.2 5.4 9.8 

结论:假设比较函数为op,priority_queue保证对于队头元素和队列中其余的元素有关系op(x, y) == false

#include <iostream>
#include <queue>
using namespace std;

struct cmp {
    bool operator() (int a, int b) {
        return (a % 10) > (b % 10);
    }
};

int main() {
    // priority_queue<double> priorities;
    priority_queue<int, vector<int>, cmp > priorities;
    priorities.push(30);
    priorities.push(29);
    priorities.push(12);
    while (!priorities.empty()) {
        cout << priorities.top() << " ";
        priorities.pop();
    }
    cout << endl;
}

结构体的优先级设置

方式一:重载运算符 <
可以在结构体内部重载 <,改变小于号的功能(例如把它重载为大于号)

struct student{
    int grade;
    string name;

    //重载运算符,grade 值高的优先级大
    friend operator < (student s1, student s2) {
        return s1.grade < s2.grade;
    }
};
void test2(){
    priority_queue<student> q;
    student s1,s2,s3;
    s1.grade = 90;
    s1.name = "Tom";

    s2.grade = 80;
    s2.name = "Jerry";

    s3.grade = 100;
    s3.name = "Kevin";

    q.push(s1);
    q.push(s2);
    q.push(s3);

    while(!q.empty()){
        cout << q.top().name << ":" << q.top().grade << endl;
        q.pop();
    } 
}
/*
    结果:
    Kevin:100
    Tom:90
    Jerry:80
*/

方式二:把重载的函数写在结构体外面

将比较函数写在结构体外面,作为参数传给优先队列。

struct fruit {
    string name;
    int price;
};
struct cmp{
    // "<" 表示 price 大的优先级高
    bool operator() (fruit f1, fruit f2){
        return f1.price < f2.price;
    }
};
void test3() {
    priority_queue< fruit, vector<fruit>, cmp > q;
    fruit f1,f2,f3;

    f1.name = "apple";
    f1.price = 5;

    f2.name = "banana";
    f2.price = 6;

    f3.name = "pear";
    f3.price = 7;

    q.push(f1);
    q.push(f2);
    q.push(f3);

    while(!q.empty()){
        cout<<q.top().name<<":"<<q.top().price<<endl;
        q.pop();
    }
}

/*
     结果:
     pear:7
     banana:6
     apple:5
*/

部分转载自:https://blog.csdn.net/pzhu_cg_csdn/article/details/79166858

猜你喜欢

转载自blog.csdn.net/beashaper_/article/details/80711705