如何使用两个栈来表示一个队列

算法题目来自好大学慕课浙江大学《数据结构》队列的讨论题,题目如下:

如何用两个堆栈模拟实现一个队列?  如果这两个堆栈的容量分别是m和n(m>n),你的方法能保证的队列容量是多少

算法思想来自慕课好大学浙江大学《算法与数据结构》

代码如下:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 
  4 #define M 95
  5 #define N 10
  6 
  7 /*
  8 讨论2.3 如何用两个堆栈模拟实现一个队列?
  9 老师参与
 10 
 11 我认为队列的最大长度为M+N,下面是我的算法思想。
 12 1.入队列时,当小栈不满时,一直向小栈里面压入元素(入队),
 13 如果小栈满了但是大栈为空,那么就把小栈里面的元素分别弹栈并一一压入大栈里面。
 14 如此以来,小栈就为空,大栈未满被(M>N),此时可以执行继续入队列(元素压入小栈),或者出队列(元素从大栈弹栈)。
 15 如果入队列(元素压入小栈),则小栈会逐渐被放满。此时就有如下情况:
 16 1.如果大栈为空,那么按照上面的方法,把小栈内元素分别弹栈并压入大栈
 17 
 18 2.如果大栈中有元素,并且大栈的剩余空间R>N(小栈容量),建立一个临时数组,先把大栈中的元素
 19 全部弹栈并用数组保存,在把小栈的元素分别弹栈并一一压入大栈。在把临时数组中元素的按照出队列的顺序一一压入大栈中
 20 
 21 3.如果大栈中有元素而且大栈的剩余空间R<N(小栈的容量),那么此时我们的想法是把小栈中栈底的R个运算弹栈并压栈大栈中。
 22     首先用临时数组arr2保存小栈弹出的N-R个元素,在把大栈中的所有元素弹栈并放入一个临时数组中arr1中。
 23     把小栈中剩余的元素依次弹栈并压入大栈,再把临时数组arr1和临时数组arr2中的元素,按照之前的顺序压入大栈和小栈中、
 24     此时大栈已满,小栈还有N-R个元素可用。所有可用继续入队列(元素压入小栈),直到小栈也满为止。
 25 
 26     根据上树的算法,队列的最大容量为大栈满且小栈满,即为M+N
 27 
 28 下面是代码的具体实现:
 29 */
 30 
 31 
 32 //构造长度较小的栈
 33 typedef struct node1{
 34     int data[N];
 35     int top;
 36 }smallerStack,*pSmallerStack;
 37 
 38 //构造长度较大的栈
 39 typedef struct node2{
 40     int data[M];
 41     int top;
 42 }greaterStack,*pGreaterStack;
 43 
 44 
 45 /*==============================对长度较小的栈的操作=======================================*/
 46 pSmallerStack createSmallerStack(){
 47     pSmallerStack stack;
 48     stack = (pSmallerStack)malloc(sizeof(smallerStack));
 49     if(stack){
 50         stack->top=-1;
 51     }
 52     return stack;
 53 }
 54 
 55 int isSmallerStackFull(pSmallerStack stack){
 56     return stack->top== (N-1);
 57 }
 58 
 59 int isSmallerStackEmpty(pSmallerStack stack){
 60     return stack->top==-1;
 61 }
 62 
 63 void pushSmallerStack(pSmallerStack stack,int element){
 64     if(isSmallerStackFull(stack)){
 65         //printf("the smaller stack has been filled,don't allow push\n");
 66         return;
 67     }else{
 68         stack->data[++(stack->top)]=element;
 69     }
 70 }
 71 
 72 int popSmallerStack(pSmallerStack stack){
 73     if(isSmallerStackEmpty(stack)){
 74         //printf("the smaller stack is empty,don't pop\n");
 75     }else{
 76         return (stack->data[(stack->top)--]);
 77     }
 78 }
 79 
 80 //按照从top-->0 打印小栈元素
 81 void toStringSmallerStack(pSmallerStack stack){
 82     int n = stack->top;
 83     printf("\ntoSmallerStackString:");
 84     if(n==-1){
 85         printf("the smaller stack is empty");
 86     }else{
 87         while(n>=0){
 88             printf("%d ",stack->data[n]);
 89             n--;
 90         }
 91     }
 92     printf("\n");
 93 
 94 }
 95 
 96 
 97 
 98 
 99 /*======================对长度较大的栈的操作===============================*/
100 pGreaterStack createGreaterStack(){
101     pGreaterStack stack;
102     stack = (pGreaterStack)malloc(sizeof(greaterStack));
103     if(stack){
104         stack->top=-1;
105     }
106     return stack;
107 }
108 
109 int isGreaterStackFull(pGreaterStack stack){
110     return stack->top== (M-1);
111 }
112 
113 int isGreaterStackEmpty(pGreaterStack stack){
114     return stack->top==-1;
115 }
116 
117 void pushGreaterStack(pGreaterStack stack,int element){
118     if(isGreaterStackFull(stack)){
119         printf("the Greater stack has been filled,don't allow push\n");
120         return;
121     }else{
122         stack->data[++(stack->top)]=element;
123     }
124 }
125 
126 int popGreaterStack(pGreaterStack stack){
127     if(isGreaterStackEmpty(stack)){
128         printf("the Greater stack is empty,don't pop\n");
129     }else{
130         return (stack->data[(stack->top)--]);
131     }
132 }
133 
134 //按照从top-->0打印大栈元素
135 void toStringGreaterStack(pGreaterStack stack){
136     int n = stack->top;
137     printf("\ntoGreaterStackString:");
138     if(n==-1){
139         printf("the greater stack is empty");
140     }else{
141         while(n>=0){
142             printf("%d ",stack->data[n]);
143             n--;
144         }
145     }
146     printf("\n");
147 
148 }
149 
150 
151 
152 /*
153 把小栈中n个元素分别弹栈并且分别压入大栈
154 */
155 void popSmallerStackPushGreaterStack(pSmallerStack stack1,pGreaterStack stack2,int n){
156     int i=0;
157     while(!isSmallerStackEmpty(stack1) && i<n){
158         //printf("move\n");
159         pushGreaterStack(stack2,popSmallerStack(stack1));
160         i++;
161     }
162     //printf("is stack1 full %d\n",isSmallerStackFull(stack1));
163 }
164 
165 /*
166 这个函数实现当小栈满但是大栈未满时,如何把小栈元素(全部或者部分)弹栈并压入大栈
167 */
168 int buildTempArrayThenpopSmallerStackPushGreaterStack(pSmallerStack stack1,pGreaterStack stack2){
169     int n = stack2->top+1;//获取大栈的元素个数
170     int arr1[n];//定义临时数组,用于存放大栈元素
171     int temp = M-n;//获取大栈空余空间个数
172     //printf("test2,%d",N-temp);
173     int arr2[N];//定义临时数组arr2,用于存放小栈元素
174     int i=0;
175 
176     if(temp>=N){
177         /*
178         如果大栈中的空余空间大于小栈的长度,
179         先把大栈元素全部弹栈并用数组保存,在把小栈元素一一弹栈并分别压入大栈,在按顺序把临时
180         数组中的元素压入大栈。
181         */
182         while(!isGreaterStackEmpty(stack2)){//把大栈元素全部弹栈
183             arr1[i]=popGreaterStack(stack2);
184             i++;
185         }
186         popSmallerStackPushGreaterStack(stack1,stack2,N);//把小栈元素全部弹栈并压入大栈
187         i=n-1;
188         while(i>=0){//按顺序把临时数组的元素压入大栈
189             pushGreaterStack(stack2,arr1[i]);
190             i--;
191         }
192     }else{
193         /*
194         大栈空间剩余空间不足以放入全部的小栈元素
195         求出大栈的空余空间temp
196         1.先把大栈中所有元素弹栈并用临时数组保存
197         2.先把小栈中的N-temp个元素弹栈用临时数组保存
198         3.在小栈中的temp个元素分别弹栈并一一压栈大栈。
199         4.分别按照顺序把临时数组中的元素一一压栈回大栈和小栈
200         */
201         i=0;
202         while(!isGreaterStackEmpty(stack2)){//弹栈大栈中所有元素
203             arr1[i]=popGreaterStack(stack2);
204             i++;
205         }
206         i=0;
207         while(!isSmallerStackEmpty(stack1) && i<N-temp){//把小栈中N-temp个元素弹栈
208             arr2[i]=popSmallerStack(stack1);
209             i++;
210         }
211         popSmallerStackPushGreaterStack(stack1,stack2,temp);//在小栈中的temp个元素分别弹栈并一一压栈大栈。
212 
213         //分别按照顺序把临时数组中的元素一一压栈回大栈和小栈
214         i=n-1;
215         while(i>=0){
216             pushGreaterStack(stack2,arr1[i]);
217             i--;
218         }
219         i=N-temp-1;
220         while(i>=0){
221             pushSmallerStack(stack1,arr2[i]);
222             i--;
223         }
224     }
225         return 1;
226 }
227 
228 /*
229 入队列,思路:
230 1.如果小栈不满,压入小栈,
231 2.如果小栈满了,大栈为空,把小栈元素分别弹栈并压入大栈,并把元素压入已经为空的小栈中
232 3.如果小栈满了,大栈不为空且大栈不满,分为下面两种情况
233     3.1.如果大栈中有元素,并且大栈的剩余空间R>N(小栈容量),建立一个临时数组,先把大栈中的元素
234         全部弹栈并用数组保存,在把小栈的元素分别弹栈并一一压入大栈。在把临时数组中元素的按照出队列的顺序一一压入大栈中
235     3.2.如果大栈中有元素而且大栈的剩余空间R<N(小栈的容量),那么此时我们的想法是把小栈中栈底的R个运算弹栈并压栈大栈中。
236     首先用临时数组arr2保存小栈弹出的N-R个元素,在把大栈中的所有元素弹栈并放入一个临时数组中arr1中。
237     把小栈中剩余的元素依次弹栈并压入大栈,再把临时数组arr1和临时数组arr2中的元素,按照之前的顺序压入大栈和小栈中、
238     此时大栈已满,小栈还有N-R个元素可用。所有可用继续入队列(元素压入小栈),直到小栈也满为止。
239 4.如果大栈元素满了小栈元素也满了,则队列满了
240 最大的队列容量:为 M+N
241 */
242 int addQueue(pSmallerStack stack1,pGreaterStack stack2,int element){
243     if(isSmallerStackFull(stack1) && isGreaterStackEmpty(stack2)){
244         //printf("stack1 fill\n");
245         popSmallerStackPushGreaterStack(stack1,stack2,N);
246         //printf("is stack1 full %d\n",isSmallerStackFull(stack1));
247         pushSmallerStack(stack1,element);
248         return 1;
249     }else if(isSmallerStackFull(stack1) && !isGreaterStackEmpty(stack2) && !isGreaterStackFull(stack2)){
250         buildTempArrayThenpopSmallerStackPushGreaterStack(stack1,stack2);
251         pushSmallerStack(stack1,element);
252         return 1;
253     }else if(!isSmallerStackFull(stack1)){
254         pushSmallerStack(stack1,element);
255         return 1;
256     }else{
257             //printf(" greater index %d ",stack2->top);
258             //toStringGreaterStack(stack2);
259             printf("the stack has been filled\n");
260             return 0;
261         }
262 }
263 
264 /*
265 出队列:
266 1.如果大栈不为空,大栈进行弹栈
267 2.如果大栈为空,小栈不为空,把小栈元素分别弹栈并压入大栈,对大栈进行一次弹栈操作
268 3.如果大栈为空,小栈也为空,那么队列为空
269 */
270 int deleteQueue(pSmallerStack stack1,pGreaterStack stack2){
271     if(!isGreaterStackEmpty(stack2)){
272         return popGreaterStack(stack2);
273     }else if(isGreaterStackEmpty(stack2) && !isSmallerStackEmpty(stack1)){
274         popSmallerStackPushGreaterStack(stack1,stack2,N);
275         return popGreaterStack(stack2);
276     }else{
277         printf("the stack has been empty\n");
278         return;
279     }
280 }
281 
282 /*根据入队列的顺序打印队列中的元素,和出队列规则一致*/
283 void toString(pSmallerStack stack1,pGreaterStack stack2){
284     int top;
285     printf("Queue toString:");
286     if(!isGreaterStackEmpty(stack2)){
287         top = stack2->top;
288         while(top>=0){
289             printf("%d ",stack2->data[top]);
290             top--;
291         }
292     }
293     if(!isSmallerStackEmpty(stack1)){
294         top = 0;
295         while(top<=stack1->top){
296             printf("%d ",stack1->data[top]);
297             top++;
298         }
299     }
300     printf("\n");
301 
302     if(isSmallerStackEmpty(stack1) && isGreaterStackEmpty(stack2)){
303         printf("the queue is empry\n");
304     }
305 }
306 
307 void main(){
308     /*在第四行和第五行调整M和N的大小,来查看测试结果
309         当 M=89 N=10,队列容量为99
310         当M=90 N=10 队列容量为100
311         当M=91 N=10,队列容量为101
312     */
313     pSmallerStack stack1 = createSmallerStack();
314     pGreaterStack stack2 = createGreaterStack();
315     int i=0;
316     for(i=1;i<=100;i++){
317         int result =  addQueue(stack1,stack2,i);
318         if(result){
319             toString(stack1,stack2);
320         }else{
321             break;
322         }
323     }
324 }
Two stack into squeue

 

 

 

 

运行结果如下:

 

 

 

 

 

转载于:https://www.cnblogs.com/yghjava/p/6637992.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值