zoukankan      html  css  js  c++  java
  • 如何使用两个栈来表示一个队列

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

    如何用两个堆栈模拟实现一个队列?  如果这两个堆栈的容量分别是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
    ");
     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
    ");
     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("
    toSmallerStackString:");
     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("
    ");
     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
    ");
    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
    ");
    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("
    toGreaterStackString:");
    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("
    ");
    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
    ");
    159         pushGreaterStack(stack2,popSmallerStack(stack1));
    160         i++;
    161     }
    162     //printf("is stack1 full %d
    ",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
    ");
    245         popSmallerStackPushGreaterStack(stack1,stack2,N);
    246         //printf("is stack1 full %d
    ",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
    ");
    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
    ");
    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("
    ");
    301 
    302     if(isSmallerStackEmpty(stack1) && isGreaterStackEmpty(stack2)){
    303         printf("the queue is empry
    ");
    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

    运行结果如下:

     

  • 相关阅读:
    文件处理
    集合 字符编码
    3-11作业
    win 10 在vs2017下对mpi的安装以及认识
    java中二维数组的排序
    java中Arrays的用法
    java中随机二维数组中寻找最大值并输出坐标
    用java打印图形
    面向对象object与constructor
    for each in for in 与for of
  • 原文地址:https://www.cnblogs.com/yghjava/p/6637992.html
Copyright © 2011-2022 走看看