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

时间: 2024-10-23 22:03:07

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

POJ 2431 Expedition (STL 优先权队列)

Expedition Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8053   Accepted: 2359 Description A group of cows grabbed a truck and ventured on an expedition deep into the jungle. Being rather poor drivers, the cows unfortunately managed to

java最小堆实现优先权队列和求最大的n个数问题

堆在实现优先权队列和求最大最小的n个数问题上,有着莫大的优势! 对于最大堆和最小堆的定义此处不再赘述,课参考网上文章:http://blog.csdn.net/genios/article/details/8157031 本文主要是对最小堆进行实现和应用,仅供新手参考. 优先权队列 优先权队列是一种非常有用的数据结构,操作系统的进程调度就有优先权队列的应用,如果用最小值表示最高的优先权,则使用最小堆,否则使用最大堆. top-N值为问题: 对于求最大的n个数,可以用最小堆来实现,思路是:将n个数

NOJ 机器狗组装费用 (优先权队列)

机器狗组装费用 时间限制(普通/Java) : 1500 MS/ 4500 MS          运行内存限制 : 65536 KByte 总提交 : 490            测试通过 : 166 题目描述 sed同学最近迷上了制造机器狗,购置了大量所需零件,零件可以组装为一个组件,这些组件或零件又可以组装为一个大的组件.在制造机器狗中,组件或零件只能两两进行组装,组装的顺序任意.在机器狗中,每个零件都有一个组装成本,每次组装一个组件的费用为各个零件组装成本之和.给定各个零件组装成本(单

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型

import java.util.Stack; /**  * 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型.  * @author user  *  *思路:队列是先入先出,栈是先入后出,可以将数据压入第一个栈后,在弹出来压入第二个栈,弹得时候直接从第二个栈弹出,弹出后又将  *第二个栈中的所有数据弹出重新压入的一个栈  */ public class Solution {     Stack<Integer> stack1 = new Stack<

数据结构Java实现07----队列:顺序队列&amp;顺序循环队列、链式队列、顺序优先队列

数据结构Java实现07----队列:顺序队列&顺序循环队列.链式队列.顺序优先队列 一.队列的概念: 队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在其一端进行插入操作在其另一端进行删除操作. 队列中允许进行插入操作的一端称为队尾,允许进行删除操作的一端称为队头.队列的插入操作通常称作入队列,队列的删除操作通常称作出队列. 下图是一个依次向队列中插入数据元素a0,a1,...,an-

数据结构6_顺序队列(循环队列)

本文实现了顺序队列,与链队列不同的是,顺序队列需要考虑一个问题, 问题情况如下, 解决办法:循环队列,当rear到分配的数组空间末尾时,转到数组头 但是当q.rear==q.front时,又如何区分一种是空队列,一种是满队列的情况呢 这里有两种方案 本次代码实现了第一种方法,同时设置了一个技术变量length,稍加改动便可实现第二个方法 代码如下: #include<iostream>using namespace std;//该顺序队列为循环队列,解决队尾指针达到最大值,队列中有空闲单元,但

队列理论和队列网络模型 queueing theory and queueing network model

(学了大半个月,赶紧把脑袋里装的东西倒一点点出来,不然就忘记了.看别人的PPT都是顺理成章.一气呵成,看我能讲出多少东西) 1队列理论 队列在生活中随处可见,例如排队买票,排队打饭,排队做地铁等等.那将诸如此类的队列抽象一下,可归纳为一下3要术:排队能容纳的总人数(例如食堂空间只有那么大,最长的队伍只能容纳20人).服务率(例如食堂阿姨打菜的速度).等待时间.   我们通过数学公式以及生活常识可得到如下关系:排队总人数=服务率乘以等待时间. 将队列理论应用于服务器处理的排队,那么排队的要素增加一

09.循环队列与链队列

一.队列与循环队列 1.队列 (1)队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表.队列是一种先进先出(Fiirst In First Out)的线性表,简称FIFO.允许插入的一端称为队尾,允许删除的一端称为队头. 从队列的定义可知,队列的入队操作,其实就是在队尾追加一个元素,不需要移动任何元素,因此时间复杂度为O(1).队列的删除操作,与栈不同的是,队列元素的出列是在队头,即小标为0的位置,若要删除一个元素的话,需要移动队列的所有元素,因此事件复杂度为O(n).

IOS 主队列,全局队列的关系

同步,异步,串行,并发 同步和异步代表会不会开辟新的线程.串行和并发代表任务执行的方式. 同步串行和同步并发,任务执行的方式是一样的.没有区别,因为没有开辟新的线程,所有的任务都是在一条线程里面执行. 异步串行和异步并发,任务执行的方式是有区别的,异步串行会开辟一条新的线程,队列中所有任务按照添加的顺序一个一个执行,异步并发会开辟多条线程,至于具体开辟多少条线程,是由系统决定的,但是所有的任务好像就是同时执行的一样. 开辟队列的方法: dispatch_queue_t myQueue = dis