算法题目来自好大学慕课浙江大学《数据结构》队列的讨论题,题目以下: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