其实队列和栈挺像的,所以也就没有单独写一个实现队列的笔记,可以参考一下栈的实现:https://www.cnblogs.com/2015-16/p/12957964.html (同时这一篇也包含了队列的一些基本使用)
队列,简称队,也是一种操作受限的线性表。把进行插入的一端称做队尾(rear),进行删除的一端称做队头(front);(先进先出表)
环形队列:简而言之,在顺序队列中,我们删除元素,并没有真正删除,只是把front指针前进,那么两个指针都往前,后面自然会空出许多单元,这样就浪费了,我们采用环形队列,在逻辑上把一个数组掰弯,形成一个圆,让rear指到数组顶点之后可以回过头来,再次指向最开始的单元,这样就可以利用那些空间;
环形队列通常约定进队时少用一个数据元素空间,队满条件:(q->rear+1)% MaxSize == q->front ;队空条件:q->rear == q->front ;
队中元素个数:(rear-front+MaxSize)% MaxSize ;
**********************************************************************
题目来了:火车轨道重排
问题分析:分析题目意思我们可以大致得到,我们需要利用缓冲轨导,实现对车厢的排序。车厢排序有这样的特点,首先是,车厢数从1-n,是连续的数字,其次我们需要按照从小到大的顺序,一个一个的输出,可供我们选择缓冲轨道,但是,假设如果我现在车厢数目改变,或者说车厢数字顺序改变,那我们相应的,所需要的轨道数数目也可能改变。我设计了一个动态的轨道数目来解决这个问题。首先需要按照合适的格式,把我们需要重排的车厢数序列放入队列中,之后逐步的输出车厢数。即先考虑主轨,如果主轨不能(主轨目前可以输出的数字不是我想要的),那便考虑缓冲轨道,如果缓冲轨道也不能,那就是说明,我们需要的车厢,还在主轨的后边,我们便需要把主轨的前面的车厢分散进入缓冲轨道,以此实现输出。
1 void Rearrangment_Queue(Queue *& Q, intG_number) {2 int nowOut = 1, i, temp, Sign; //缓冲轨导数标记 G_number
3 Queue ** kq = new Queue *[G_number]; //数组指针
4 for (i = 0; i < G_number; i++)5 Initialize_Queue(kq[i], Q->number); //缓冲轨导初始化
6 while (nowOut <= Q->number) { //入轨判断
7 Sign = 0; //标记符Sign
8 if (Empty_Queue(Q) && Q->data[Q->front + 1] ==nowOut) {9 cout << nowOut << " ";10 nowOut++;11 Q->front++;12 Sign++; //标记符Sign
13 }14 for (i = 0; i < G_number; i++) //缓冲轨判断
15 if (Empty_Queue(kq[i]) && kq[i]->data[kq[i]->front + 1] ==nowOut) {16 cout << nowOut << " "; //缓冲轨非空(1)情况下进行匹配
17 nowOut++;18 kq[i]->front++;19 Sign++; //标记符Sign
20 }21 if (!Sign) { //缓冲轨生成
22 int j = 0;23 while (Q->data[Q->front + 1] !=nowOut) {24 Out_Queue(Q, temp);25 if (kq[j]->data[kq[j]->rear]
28 Enter_Queue(kq[++j], temp);29 }30 }31 }32 cout <
34 Destroy_Queue(kq[i]);35 delete[] kq;36 }
kq用来存放若干个缓冲轨,nowOut是目前需要输出的数字;
先处理主轨,再处理缓冲轨,最后,若均没有对应数字,则需要完成主轨和缓冲轨数字的变换;
当然还需要很多其余队列相关函数:初始化、销毁、进队、出队、判空以及创建队列和G_number求解;
1 #include
2 #include
3
4 using namespacestd;5
6 structQueue {7 int *data;8 int number; //车箱数
9 intfront, rear;10 };11 //初始化
12 void Initialize_Queue(Queue *& Q, intnumber) {13 Q = (Queue *)malloc(sizeof(Queue));14 Q->number = number; //车厢数固定
15 Q->data = new int[Q->number];16 Q->data[0] = 0; //确保后序判断需要
17 Q->front = Q->rear = -1;18 }19 //销毁
20 void Destroy_Queue(Queue *&Q) {21 delete[] Q->data;22 free(Q);23 }24 //进队
25 void Enter_Queue(Queue *& Q, inte) {26 Q->rear++;27 Q->data[Q->rear] =e;28 }29 //出队
30 void Out_Queue(Queue *& Q, int &e) {31 Q->front++;32 e = Q->data[Q->front];33 }34 //判空
35 bool Empty_Queue(Queue * Q) { //空 = 0 ,非空 = 1
36 return (!(Q->front == Q->rear));37 }38 //创建以及G_number
39 int Create_Queue(Queue *&Q) {40 int i, e, G_number = 0; //缓冲轨导数
41 cout << "请输入待重排的车厢序列 :";42 Q->rear = Q->number - 1;43 for (i = Q->number; i > 0; i--) {44 cin >>e;45 Q->data[i - 1] =e;46 if (i < Q->number && Q->data[i - 1] > Q->data[i])47 G_number++; //按最大所需轨道数计算
48 } //可能实际所需轨道数少于此数
49 return G_number; //但是方便
50 }51
52 void Rearrangment_Queue(Queue *& Q, intG_number) {53 int nowOut = 1, i, temp, Sign; //缓冲轨导数标记 G_number
54 Queue ** kq = new Queue *[G_number]; //数组指针
55 for (i = 0; i < G_number; i++)56 Initialize_Queue(kq[i], Q->number); //缓冲轨导初始化
57 while (nowOut <= Q->number) { //入轨判断
58 Sign = 0; //标记符Sign
59 if (Empty_Queue(Q) && Q->data[Q->front + 1] ==nowOut) {60 cout << nowOut << " ";61 nowOut++;62 Q->front++;63 Sign++; //标记符Sign
64 }65 for (i = 0; i < G_number; i++) //缓冲轨判断
66 if (Empty_Queue(kq[i]) && kq[i]->data[kq[i]->front + 1] ==nowOut) {67 cout << nowOut << " "; //缓冲轨非空(1)情况下进行匹配
68 nowOut++;69 kq[i]->front++;70 Sign++; //标记符Sign
71 }72 if (!Sign) { //缓冲轨生成
73 int j = 0;74 while (Q->data[Q->front + 1] !=nowOut) {75 Out_Queue(Q, temp);76 if (kq[j]->data[kq[j]->rear]
79 Enter_Queue(kq[++j], temp);80 }81 }82 }83 cout <
85 Destroy_Queue(kq[i]);86 delete[] kq;87 }88
89 intmain()90 {91 Queue *Q;92 intG_number, number;93 cout << "请输入最大车厢数 number :";94 cin >>number;95 Initialize_Queue(Q, number);96 G_number =Create_Queue(Q);97 cout << "火车车厢重排后 :";98 Rearrangment_Queue(Q, G_number);99 Destroy_Queue(Q);100 return 0;101 }
View Code
对于这样一个问题似乎也可以修改为一个利用队列进行排序的算法,但是对于空间方面的要求着实过大,理论上感觉还是可以的;
2020-05-25