C++队列和优先权队列的使用---应用:带时限作业排序

Posted blackrose_li

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++队列和优先权队列的使用---应用:带时限作业排序相关的知识,希望对你有一定的参考价值。

C++队列和优先权队列的使用—应用:带时限作业排序


C++队列的使用

首先包含头文件

include

队列可以用线性表(list)或双向队列(deque)来实现(注意vector container 不能用来实现queue,因为vector 没有成员函数pop_front!):
queue<list<int>> q1;
queue<deque<int>> q2;
其成员函数有“判空(empty)” 、“尺寸(Size)” 、“首元(front)” 、“尾元(backt)” 、“加入队列(push)” 、“弹出队列(pop)”等操作。

1.back() 返回一个引用,指向最后一个元素
2.empty() 如果队列空则返回真
3.front() 返回第一个元素
4.pop() 删除第一个元素
5.push() 在末尾加入一个元素
6.size() 返回队列中元素的个数

例如,队列在带时限作业排序中的应用

#include<iostream>
`#include<queue>`
using namespace std;
struct Node         //状态空间树结点结构
{
    Node(Node *par, int k, int num)
    {
        parent = par; j = k; NodeNum = num;
    }
    Node *parent;    //指向该结点的双亲结点
    int j;           //该结点代表的解分量x[i]=j
    int NodeNum;     //该结点的编号,增加的变量,可以不要
};

template<class T>
struct qNode       //活结点表中的活结点结构
{
    qNode(){}
    qNode(T p, T los, int sd, int k, Node *pt)
    {
        prof = p; loss = los; d = sd; ptr = pt; j = k;
    }
    T prof, loss;   //当前结点X的下界函数c(X)=loss,上界函数u(X)=24-prof
    int j, d;        //当前活结点所代表的分量x[j]=j, d是迄今为止的时间
    Node *ptr;      //指向状态空间树中相应的结点
};

template<class T>
class JS
{
public:
    JS(T *prof, int *de, int *time, int size);
    T JSFIFOBB();                              //构造状态空间树,求最优解值
    void GenerateAns(int *x, int &k);          //一维数组x为最优解向量,k中返回x的分量解
private:
    T *p, total;                                //p为收益数组,total初始为n个作业收益之和
    int *t, *d, n;                             //t为作业处理时间数组,d为按非减次序排列的作业时间数组
    Node *ans, *root;                           //root指向状态空间树的根,ans指向最优解答案结点
};

template<class T>
JS<T>::JS(T *prof, int *de, int *time, int size)
{
    n = size;
    p = new T[n];  d = new int[n];   t = new int[n];
    total = 0;
    for (int i = 0; i<n; i++)
    {
        p[i] = prof[i];   total += p[i];
        d[i] = de[i];     t[i] = time[i];
    }
}

`#define mSize 20`

template<class T>
T JS<T>::JSFIFOBB()
{
    Node *E, *child;

    queue< qNode<T> > q; //生成一个FIFO队列实例q

    int num = 1;                     //结点编号num
    E = root = new Node(NULL, -1, num);  //构造状态空间树的根结点root
    cout << " root->NodeNum=" << root->NodeNum << "  root->parent=" << root->j << endl;
    qNode<T> ep(0, 0, 0, -1, root);    //ep为扩展结点
    qNode<T> ec;                   //ec为活结点(入队的结点)
    T U = total;                     //上界变量U赋初值,total为作业收益和
    while (1)
    {
        T loss = ep.loss, prof = ep.prof;  E = ep.ptr;  //loss为已造成的损失,prof为已获收益
        for (int j = ep.j + 1; j<n; j++)     //考察所有孩子
        {
            num++;
            if (ep.d + t[j] <= d[j] && loss<U)
            {
                child = new Node(E, j, num); //构造E的孩子结点
                cout << " child->NodeNum=" << child->NodeNum << "  child->parent=" << E->NodeNum << endl;
                ec.prof = prof + p[j];     ec.d = ep.d + t[j];
                ec.ptr = child;          ec.loss = loss;        ec.j = j;
                q.push(ec);            //活结点进队列
                /*
                cout<<"ec.prof="<<ec.prof;
                cout<<"  ec.d="<<ec.d;
                cout<<"  ec.loss="<<ec.loss;
                cout<<"  ec.j="<<ec.j;
                cout<<endl;
                */
                T cost = total - ec.prof;    //计算上界函数值
                if (cost<U)
                {
                    U = cost;  ans = child;   //修改上界变量U,置child为当前的答案结点,
                }                        //当函数返回时,ans指向答案结点
            }
            loss = loss + p[j];
        }
        //cout<<endl;
        do
        {
            if (q.empty())
                return total = U;           //若队列为空,则返回最小损失值,隐含着返回ans结点
            ep=q.front();                 //选择下一个扩展结点
            q.pop();
        } while (ep.loss >= U);
    }
}

template<class T>
void JS<T>::GenerateAns(int *x, int &k)
{
    Node *ans1 = ans;
    k = 0;
    while (ans1->j>0)
    {
        k++;
        ans1 = ans1->parent;
    }
    ans1 = ans;
    for (int i = k - 1; i >= 0; i--)
    {
        x[i] = ans1->j;
        ans1 = ans1->parent;
    }
}

‘#define SIZE 5    //4‘

void main()
{
    float prof[SIZE] = { 3, 8, 6, 4, 5 };   //{5,3,6,10};
    int de[SIZE] = { 1, 2, 3, 4, 4 };       //{1,1,2,3};
    int time[SIZE] = { 1, 1, 2, 2, 1 };     //{1,1,1,2};
    float total = 0, U;
    int x[10];
    int k;

    JS<float> work(prof, de, time, SIZE);
    U = work.JSFIFOBB();      cout << endl;
    for (int i = 0; i<SIZE; i++) total += prof[i];

    cout << endl;
    cout << "total=" << total << endl;

    cout << endl;
    cout << "U=" << U << endl;

    cout << endl;
    cout << "最优解的值=" << total - U << endl;

    cout << "最优解X[]:";
    work.GenerateAns(x, k);
    for (int i = 0; i<k; i++) cout << " " << x[i];
    cout << endl;

    for (int i = 0; i<k; i++)
        cout << "作业" << x[i] << ":(" << prof[x[i]] << "," << de[x[i]] << "," << time[x[i]] << ")" << endl;
}

C++优先权队列的使用

首先引入头文件

#include<queue>

包含的方法

C++优先队列类似队列,但是在这个数据结构中的元素按照一定的断言排列有序。
1.empty() 如果优先队列为空,则返回真
2.pop() 删除第一个元素
3.push() 加入一个元素
4.size() 返回优先队列中拥有的元素的个数
5.top() 返回优先队列中有最高优先级的元素

实例为带时限的作业排序LCBB算法,例如:

#include<iostream>
#include <queue>
using namespace std;
struct Node         //状态空间树结点结构
{
    Node(Node *par, int k, int num)
    {
        parent = par; j = k; NodeNum = num;
    }
    Node *parent;    //指向该结点的双亲结点
    int j;           //该结点代表的解分量x[i]=j
    int NodeNum;     //该结点的编号,增加的变量,可以不要
};

template<class T>
struct qNode       //活结点表中的活结点结构
{
    operator T()const{ return loss; }
    qNode(){}
    qNode(T p, T los, int sd, int k, Node *pt)
    {
        prof = p; loss = los; d = sd; ptr = pt; j = k;
    }
    T prof, loss;   //当前结点X的下界函数c(X)=loss,上界函数u(X)=24-prof
    int j, d;        //当前活结点所代表的分量x[j]=j, d是迄今为止的时间
    Node *ptr;      //指向状态空间树中相应的结点
};

template<class T>
class JS
{
public:
    JS(T *prof, int *de, int *time, int size);
    T JSLCBB();                                //构造状态空间树,求最优解值
    void GenerateAns(int *x, int &k);          //一维数组x为最优解向量,k中返回x的分量解
private:
    T *p, total;                                //p为收益数组,total初始为n个作业收益之和
    int *t, *d, n;                             //t为作业处理时间数组,d为按非减次序排列的作业时间数组
    Node *ans, *root;                           //root指向状态空间树的根,ans指向最优解答案结点
};

template<class T>
JS<T>::JS(T *prof, int *de, int *time, int size)
{
    n = size;
    p = new T[n];  d = new int[n];   t = new int[n];
    total = 0;
    for (int i = 0; i<n; i++)
    {
        p[i] = prof[i];   total += p[i];
        d[i] = de[i];     t[i] = time[i];
    }
}

#define mSize 20

template<class T>
T JS<T>::JSLCBB()
{
    Node *E, *child;
    priority_queue< qNode<T> > q; //生成一个优先权队列实例q
    int num = 1;                      //结点编号num
    E = root = new Node(NULL, -1, num);   //构造状态空间树的根结点root
    cout << " root->NodeNum=" << root->NodeNum << "  root->parent=" << root->j << endl;
    qNode<T> ep(0, 0, 0, -1, root);     //ep为扩展结点
    qNode<T> ec;                    //ec为活结点(入队的结点)
    T U = total;                      //上界变量U赋初值,total为作业收益和
    while (1)
    {
        T loss = ep.loss, prof = ep.prof;  E = ep.ptr;  //loss为已造成的损失,prof为已获收益
        for (int j = ep.j + 1; j<n; j++)     //考察所有孩子
        {
            num++;
            if (ep.d + t[j] <= d[j] && loss<U)
            {
                child = new Node(E, j, num); //构造E的孩子结点
                cout << " child->NodeNum=" << child->NodeNum << "  child->parent=" << E->NodeNum << endl;
                ec.prof = prof + p[j];     ec.d = ep.d + t[j];
                ec.ptr = child;          ec.loss = loss;        ec.j = j;
                q.push(ec);            //活结点进队列
                /*
                cout<<"ec.prof="<<ec.prof;
                cout<<"  ec.d="<<ec.d;
                cout<<"  ec.loss="<<ec.loss;
                cout<<"  ec.j="<<ec.j;
                cout<<endl;
                */
                T cost = total - ec.prof;    //计算上界函数值
                if (cost<U)
                {
                    U = cost;  ans = child;   //修改上界变量U,置child为当前的答案结点,
                }                        //当函数返回时,ans指向答案结点
            }
            loss = loss + p[j];
        }
        //cout<<endl;
        if (!q.empty())
        {
            ep=q.top();                  //选择下一个扩展结点 
            q.pop();
            if (ep.loss >= U)
                return total = U;
        }
        else return total = U;                 //若队列为空,则返回最小损失值,隐含着返回ans结点
    }
}

template<class T>
void JS<T>::GenerateAns(int *x, int &k)
{
    Node *ans1 = ans;
    k = 0;
    while (ans1->j>0)
    {
        k++;
        ans1 = ans1->parent;
    }
    ans1 = ans;
    for (int i = k - 1; i >= 0; i--)
    {
        x[i] = ans1->j;
        ans1 = ans1->parent;
    }
}

#define SIZE 5

void main()
{
    float prof[SIZE] = { 3, 8, 6, 4, 5 };   //{5,3,6,10};
    int de[SIZE] = { 1, 2, 3, 4, 4 };       //{1,1,2,3};
    int time[SIZE] = { 1, 1, 2, 2, 1 };     //{1,1,1,2};
    float total = 0, U;
    int x[10];
    int k;

    JS<float> work(prof, de, time, SIZE);
    U = work.JSLCBB();      cout << endl;
    for (int i = 0; i<SIZE; i++) total += prof[i];

    cout << endl;
    cout << "total=" << total << endl;

    cout << endl;
    cout << "U=" << U << endl;

    cout << endl;
    cout << "最优解的值=" << total - U << endl;

    cout << "最优解X[]:" << endl;
    work.GenerateAns(x, k);
    for (int i = 0; i<k; i++) cout << " " << x[i];
    cout << endl;

    for (int i = 0; i<k; i++)
        cout << "(" << prof[x[i]] << "," << de[x[i]] << "," << time[x[i]] << ")" << endl;
}

以上是关于C++队列和优先权队列的使用---应用:带时限作业排序的主要内容,如果未能解决你的问题,请参考以下文章

优先队列原理与实现

优先队列(PriorityQueue)

[YARN-1963] 支持同一个队列内作业按优先级调度

iOS 作业队列类似于 Path 的 android 优先级作业队列

C++:STL——栈队列和优先级队列的模拟实现

优先级队列基本使用及用C++模拟实现