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