算法題目來自好大學慕課浙江大學《數據結構》隊列的討論題,題目以下: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 }
運行結果以下:ide