题目描述:
给定一个队列,请用一系列合法的队列操作函数,包括:
(1) int IsEmptyQ(Queue Q)
(2) void AddQ(Queue Q, ElementType item)
(3) ElementType DeleteQ(Queue Q)
将队列中的元素从小到大排序。
注意:不能直接通过数组下标直接访问队列(数组)中的元素。可以使用一个辅助队列。排序后的结果应存放在原队列中。
算法分析:
一开始我想用一般的思路, 队列的特性就是只能从头部出(pop), 只能从尾部进入(push). 那么每次都把队列论一圈找到最小的元素然后把这个元素放到队列的尾部, N圈以后就排序好了, 但是时间复杂度不行O(N^2) 大数据会超时, 那么想想是不是有O(NlogN)的算法, O(NlogN)的算法就那么几种, merge sort, quick sort(均摊), 最后其实merge sort在这里可以实现, 需要再借助第二个queue. 实现代码如下(可以AC):
void print(queue<int> q)
{
bool first=true;
while(!q.empty())
{
if(first)
{
printf("%d",q.front());
first=false;
}
else
printf(" %d",q.front());
q.pop();
}
printf("\n");
}
int min(int x,int y)
{
if(x<=y)
return x;
else
return y;
}
//队列归并排序
void queueMergeSort(queue<int> &q, int size)
{
queue<int> qTemp; //用于辅助排序
int step=1; //步幅, 2的指数1,2,4,8
int remain; //标记还有多少元素未进行归并
int k1,k2,i; //k1:q复制到qTemp队列中的元素 k2:q中将要和qTemp合并的元素的个数
while(step<=size)
{
remain=size; //每次归并前,初始化大小为队列大小
while(remain>0) // 一次合并开始
{
k1=min(step,remain);
//将k1个元素放入qTemp中, k1是remain和step中的最小值
for(i=0;i<k1;i++){ qTemp.push(q.front()); q.pop(); }
remain=remain-k1; //更新剩余值
k2=min(remain,step); //q中要合并的元素个数
remain=remain-k2;
//对q和qTemp队列中的前k2,k1个元素,进行合并排序
while(k1>0 && k2>0) { //将较小的元素压入队列尾部
if(q.front()<=qTemp.front())
{ q.push(q.front()); q.pop(); k2--; }
else
{ q.push(qTemp.front()); qTemp.pop(); k1--;}
}
while(k2>0) {//q中还有剩余元素未合并(较大的),直接加入q队列尾部
q.push(q.front()); q.pop(); k2--;
}
while(k1>0) {//qTemp中还有剩余元素未合并(较大的),直接加入q队列尾部
q.push(qTemp.front()); qTemp.pop(); k1--;
}
}// 一次合并结束
//print(q);
step=step*2;
}
}
参考: http://tech-wonderland.net/blog/pat-adt-3-09-sort-a-queue.html