双队列实现队列中元素排序

题目要求对一个队列中的元素进行排序,只允许使用一个临时队列,不能进行除去入队、出队、判空以外的任何操作。


实现方法为每次遍历队列,从中找出最小的元素,放入临时队列,遍历的过程是出队的过程,注意如果一个元素比当前的最小值大,则要放回队列当中,如果比当前的最小值小,则保存起来,暂时不放回队列中,发现更小的,把原来的最小值放入,更新最小值,在遍历完一次以后,将最小值存入临时队列。然后开始第二次遍历,注意每次遍历原队列中都会减少一个元素,因此共遍历队列N次,每次对队列N、N-1、N-2 ... 1这么多次出队操作来找最小值,在最后一次完成后临时队列中存放的就是排序好的结果,出队N次即可按非降序输出。


注意最坏的情况:如果最初的队列为非降序,则会造成大量的无用功,因此在原队列生成时就动态判断是否是非降序列,如果是,则直接将原队列打印。

#include<iostream>
#include<stdio.h>
using namespace std;

#define INF   99999999

#define MAXSIZE 100001

typedef struct {
	int items[MAXSIZE];
	int front;
	int rear;
}Queue;

void initQueue(Queue *q){

	q->front = q->rear = 0;

}

bool isEmpty(Queue *q){

	return q->front == q->rear;

}

void AddQ(Queue *q, int item){

	if ((q->rear + 1)%MAXSIZE == q->front)
	{
		// 为了区分空队列与满队列,必须保证rear和front不能再次碰面,因此要留出一个距离,提前判断是否添加后front=rear。
		printf("队列满");
		return;
	}
	q->rear = (q->rear + 1) % MAXSIZE;
	*(q->items + q->rear) = item;
}

int DeleteQ(Queue *q){

	if (q->rear == q->front)
	{
		printf("队列空");
		return NULL;
	}
	
	q->front = (q->front + 1) % MAXSIZE;
	return *(q->items + q->front);

}

int main(){
	
	Queue q;
	Queue tempQ;
	
	initQueue(&q);
	initQueue(&tempQ);
	
	int N;

	scanf("%d", &N);

	int buffer;

	bool isRising = true;
	int last = 0, now = -1;

	for (int i = 0; i < N; i++){
		scanf("%d", &buffer);
		AddQ(&q, buffer);
		now = buffer;
		if (i > 0 && now < last){
			isRising = false;
		}
		last = now;
	}

	if (isRising)
	{
		printf("%d", DeleteQ(&q));
		while (!isEmpty(&q))
		{
			printf(" %d", DeleteQ(&q));
		}
		printf("\n");
		return 0;
	}

	int min;

	for (int i = 0; i < N; i++){

		min = INF;

		for (int j = i; j < N; j++){

			buffer = DeleteQ(&q);

			if (buffer < min){
				if (min != INF) AddQ(&q, min);
				min = buffer;
			}
			else{
				AddQ(&q, buffer);
			}

		}

		AddQ(&tempQ, min);

	}

	printf("%d", DeleteQ(&tempQ));
	while (!isEmpty(&tempQ))
	{
		printf(" %d", DeleteQ(&tempQ));
	}
	printf("\n");
	

	return 0;
}


posted on 2015-03-05 22:57  张大大123  阅读(886)  评论(0编辑  收藏  举报

导航