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

原创 2016年06月02日 09:18:55

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;
}

相关文章推荐

带有期限的作业排序贪心算法

问题的描述: 带有期限的作业排序要解决的是操作系统中单机、无资源约束且每个作业可在等量的时间内完成的作业调度问题。把这个问题形式化描述为: ①要在一台机器上处理n个作业,每个作业可以在单位时间内完...

带时限的作业排序

/*用贪心法求解作业排序问题。设有一个单机系统、无其他资源限制并且每个作业运行时间相等 ,不妨设每个作业运行1个单位时间。现有n个作业,每个作业都有一个截止时间di>0。如果作业 能够在截止时间内...

贪心方法-带有限期和收益的单位时间的作业排序贪心算法和背包问题

参考《计算机算法基础》华中科技大学版1. 带有限期和收益的单位时间的作业排序贪心算法/* 带有限期和收益的单位时间的作业排序贪心算法 */ #include /*算法1,复杂度O(n*n)...

C++的STL中队列(queue)的使用说明

文章转载自http://www.cnblogs.com/yaoyueduzhen/p/4456430.html基本操作:push(x) 将x压入队列的末端pop() 弹出队列的第一个元素(队顶元素),...

【C++】优先队列priority_queue

优先队列是队列的一种,允许用户对队列中存储的元素设置优先级。按照数据的优先级来对队列中的数据进行动态的排序。每次的push和pop操作,队列都会动态的调整。 所以我们无论按照什么顺序...

C++ 顺序队列与循环队列

很好理解,队列就是把数据排成队,先到的排在前面,后到的排在后面,走的时候,在前面的先出去。(不许插队!) 先是顺序队列,也就是基本的排成一队。 实现如下:#include #include u...

队列(顺序存储)C++模板实现

队列:一端进行插入,另一端进行删除的sh

顺序队列模板--c++实现

//顺序队列类的实现 #include "iostream" #include "cstdio" #include "cstring" #include "algorithm" using names...

Redis学习笔记(3)-Redis事务,过期时间,队列

事务 MULTI表示开启事务 然后执行了2个语句 在执行的过程中,他们并没有真正执行,而是挂起。 等到输入EXEC的时候才会真正的执行。 这样保证了事务的特性,要么都执行,要么都不执行。...

c++STL中优先队列的使用

说到队列,我们首先想到就是先进先出,后进后出;那么何为优先队列呢,在优先队列中,元素被赋予优先级,当访问元素时,具有最高级优先级的元素先被访问。即优先队列具有最高级先出的行为特征。 优先队列在头文件...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++队列和优先权队列的使用---应用:带时限作业排序
举报原因:
原因补充:

(最多只允许输入30个字)