双队列实现队列中元素排序
题目要求对一个队列中的元素进行排序,只允许使用一个临时队列,不能进行除去入队、出队、判空以外的任何操作。
实现方法为每次遍历队列,从中找出最小的元素,放入临时队列,遍历的过程是出队的过程,注意如果一个元素比当前的最小值大,则要放回队列当中,如果比当前的最小值小,则保存起来,暂时不放回队列中,发现更小的,把原来的最小值放入,更新最小值,在遍历完一次以后,将最小值存入临时队列。然后开始第二次遍历,注意每次遍历原队列中都会减少一个元素,因此共遍历队列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; }