如何使用兩個棧來表示一個隊列

算法題目來自好大學慕課浙江大學《數據結構》隊列的討論題,題目以下:node

如何用兩個堆棧模擬實現一個隊列?  若是這兩個堆棧的容量分別是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

 

 

 

 

運行結果以下:ide

 

 

 

 

相關文章
相關標籤/搜索