数据结构-栈和队列面试题

实现一个栈,要求实现push,pop,min的时间复杂度最低。
思路是:入栈时一次入两个元素,第一个元素是要入栈的元素,第二个元素是min,min为当前栈的最小元素与插入元素的较小的那个元素。出栈时每次出两个,保证栈的结构仍然是先进后出。取栈顶元素时,也能保证每次取到的都是栈里最小的元素。

//实现一个栈要求,出栈入栈,返回最小值的时间复杂度是O(1)
typedef struct min_stack
{
    SeqStack stack; 
}min_stack;
void MinStackPush(min_stack* s,StackType value)
{
    if(s==NULL)
    {
        return;
    }
    StackType n;
    StackType min=value;
    int ret=SeqStackTop(&s->stack,&n);
    if(ret==0)
    {
        SeqStackPush(&s->stack,value);
        SeqStackPush(&s->stack,min);
        return;
    }
    if(value>n)
    {
        min=n;    
    }
    SeqStackPush(&s->stack,value);
    SeqStackPush(&s->stack,min);
}
void MinStackPop(min_stack* s)
{
    if(s==NULL)
    {
        return;
    }
    if(s->stack.size==0)
    {
        return;
    }
    SeqStackPop(&s->stack);
    SeqStackPop(&s->stack);
}
int MinStackTop(min_stack* s,StackType* value)
{
    if(s==NULL)
    {
        return 0;
    }
    if(s->stack.size==0)
    {
        return 0;
    }
    SeqStackTop(&s->stack,value);
    return 1;
}

测试代码:

void TestMin()
{
    min_stack s;
    StackType value;
    SeqStackInit(&s.stack);
    MinStackPush(&s,'d');
    int ret=MinStackTop(&s,&value);
    printf("ret expect 1,actual %d\n",ret);
    printf("top expect d,actual %c\n",value);
    MinStackPush(&s,'c');
    MinStackPush(&s,'b');
    MinStackPush(&s,'a');
    ret=MinStackTop(&s,&value);
    printf("ret expect 1,actual %d\n",ret);
    printf("top expect a,actual %c\n",value);
    MinStackPop(&s);
    ret=MinStackTop(&s,&value);
    printf("ret expect 1,actual %d\n",ret);
    printf("top expect b,actual %c\n",value);

}

这里写图片描述

使用两个栈实现一个队列
思路:定义两个栈,一个栈做输入用,一个栈做输出用,入栈时在输入这个栈里入栈,出栈与取栈顶元素都从输出这个栈里取。
这里写图片描述

//使用两个栈实现一个队列

typedef struct Queby2stack
{
    SeqStack input;
    SeqStack output;

}Queby2stack;

void Queueby2stackPush(Queby2stack* q,StackType value)
{
    if(q==NULL)
    {
        return;//非法输入
    }
    StackType top;
    while(q->output.size!=0)
    {
        SeqStackTop(&q->output,&top);
        SeqStackPop(&q->output);
        SeqStackPush(&q->input,top);
    }
    SeqStackPush(&q->input,value);
    while(q->input.size!=0)
    {
        SeqStackTop(&q->input,&top);
        SeqStackPop(&q->input);
        SeqStackPush(&q->output,top);
    }
}
void Queby2stackPop(Queby2stack* q)
{
    if(q==NULL)
    {
        return;
    }
    if(q->output.size==0)
    {
        return;
    }
    SeqStackPop(&q->output);
}

int Queby2stackTop(Queby2stack* q,StackType* value)
{
    if(q==NULL)
    {
        return 0;
    }
    if(q->output.size==0)
    {
        return 0;
    }
    SeqStackTop(&q->output,value);
    return 1;
}

void TestQueby2stack()
{
    Queby2stack q;
    StackType value;
    SeqStackInit(&q.input);
    SeqStackInit(&q.output);
    Queueby2stackPush(&q,'a');
    Queueby2stackPush(&q,'b');
    Queueby2stackPush(&q,'c');
    Queueby2stackPush(&q,'d');
    Queby2stackPrint(&q,"入队列");
    Queby2stackTop(&q,&value);
    printf("top expect a,actual %c\n",value);
    Queby2stackPop(&q);
    Queby2stackPop(&q);
    Queby2stackPrint(&q,"出队列");
    Queby2stackTop(&q,&value);
    printf("top expect c,actual %c\n",value);

}

这里写图片描述

使用两个队列实现一个栈
思路:这个题目相比于两个栈实现一个队列要复杂一些,两个栈都有既定的目标,一个做输入一个作输出。但是这两个队列没有特殊的区别。两个队列都做输出,也都做输入。画一张图来说明。
首先两个空队列,并且将元素入队列至其中一个队列中,因为我们是要实现一个栈,所以先进后出,所以出栈时应该要先出e,但是由于队列的结构限制,我们现在出队列只能出a,所以这时借助第二个队列来做一个“桥梁”。
这里写图片描述
将队列1中前几个元素都入队列至第二个队列中,此时队列1中只有e一个元素,此时再将它出队列,就能达到出栈的效果。

这里写图片描述

大致的过程就是这样,这种结构在做出栈入栈取栈顶元素时,要做的最重要的一件事是判断在该时刻哪一个队列是非空的,就对哪一个队列做入栈操作,出栈操作则要借助第二个队列。

//用两个队列实现一个栈
typedef struct Stackby2que
{
    SeqQueue que1;
    SeqQueue que2;
}Stackby2que;
void Stackby2quePush(Stackby2que* s,SeqQueType value)
{
    if(s==NULL)
    {
        return;
    }
    if(s->que1.size!=0)
    {
        SeqQueuePush(&s->que1,value);
    }
    else
    {
        SeqQueuePush(&s->que2,value);
    }
}
void Stackby2quePop(Stackby2que* s)
{
    if(s==NULL)
    {
        return;
    }
    if(s->que1.size==0&&s->que2.size==0)
    {
        return;
    }
    if(s->que1.size!=0)
    {
        SeqQueType top;
        while(s->que1.size!=1)
        {
            SeqQueueTop(&s->que1,&top);
            SeqQueuePop(&s->que1);
            SeqQueuePush(&s->que2,top);
        }
        SeqQueuePop(&s->que1);
    }
    else if(s->que2.size!=0)
    {
        SeqQueType top;
        while(s->que2.size!=1)
        {
            SeqQueueTop(&s->que2,&top);
            SeqQueuePop(&s->que2);
            SeqQueuePush(&s->que1,top);
        }
        SeqQueuePop(&s->que2);
    }
}
int Stackby2queTop(Stackby2que* s,SeqQueType* value)
{
    if(s==NULL||value==NULL)
    {
        return 0;
    }
    if(s->que1.size==0&&s->que2.size==0)
    {
        return 0;
    }
    if(s->que1.size!=0)
    {
        while(1)
        {
            SeqQueueTop(&s->que1,value);
            SeqQueuePush(&s->que2,*value);
            SeqQueuePop(&s->que1);
            if(s->que1.size==0)
            {
                return 1;
            }
        }
    }
    else if(s->que2.size!=0)
    {
        while(1)
        {
            SeqQueueTop(&s->que2,value);
            SeqQueuePush(&s->que1,*value);
            SeqQueuePop(&s->que2);
            if(s->que2.size==0)
            {
                return 1;
            }
        }
    }
    return 0;
}
/////////////////////////////////////////////
//测试
////////////////////////////////////////////
void Stackby2quePrint(Stackby2que* s,const char* msg)
{
    printf("%s\n",msg);
    if(s->que1.size!=0)
    {
        size_t i=s->que1.head;
        for(;i!=s->que1.tail;i++)
        {
            if(i>=MaxSize)
            {
                i=0;
            }
            printf("[%c] ",s->que1.data[i]);
        }
        printf("\n");
    }
    else if(s->que2.size!=0)
    {
        size_t i=s->que2.head;
        for(;i!=s->que2.tail;i++)
        {
            if(i>=MaxSize)
            {
                i=0;
            }
            printf("[%c] ",s->que2.data[i]);
        }
        printf("\n");
    }
}

void TestStackby2que()
{
    Stackby2que s;
    SeqQueType value;
    SeqQueueInit(&s.que1);
    SeqQueueInit(&s.que2);
    Stackby2quePush(&s,'a');
    Stackby2quePush(&s,'b');
    Stackby2quePush(&s,'c');
    Stackby2quePush(&s,'d');
    Stackby2quePrint(&s,"入栈");
    Stackby2queTop(&s,&value);
    printf("top expect d,actual %c\n",value);
    Stackby2quePop(&s);
    Stackby2quePrint(&s,"出栈");
    Stackby2quePop(&s);
    Stackby2quePrint(&s,"出栈");
    Stackby2queTop(&s,&value);
    printf("top expect b,actual %c\n",value);

}


这里写图片描述
元素出栈入栈的合法性
这道题的意思是指,如果入栈的序列(1,2,3,4,5),出栈序列为(4,5,3,2,1)是否合法。
首先有两个序列,先将入栈序列从第一个开始入栈,入栈一个之后取栈顶元素,与第二个序列开始比较,如果不相等,就继续入栈,如果想等,就将该元素出栈,在取当前栈顶元素与该序列的下一个元素比较,以此类推,直到第二个序列全部都比较完毕了,说明此时成立。如果第一个序列全部入完,但是此时第二个序列还没有比较完,那么就不成立。
这里写图片描述


int StackCorrect(SeqStack* stack,char* str1,char *str2,int len)
{
    if(stack==NULL||str1==NULL||str2==NULL)
    {
        return 0;
    }
    int i=0;
    for(;i<len;i++)
    {
        //入栈一个元素,取栈顶元素与比较序列的元素比较
        StackType top;
        SeqStackPush(stack,*str1);
        SeqStackTop(stack,&top);
        while(top==*str2)
        {
            //如果栈顶元素与比较序列相等,就出栈,然后比较下一个
            SeqStackPop(stack);
            SeqStackTop(stack,&top);
            str2++;
        }
        str1++;
    }
    if(*str2=='\0')
    {
        return 1;
    }
    return 0;
}
void TestStackCorrect()
{
    SeqStack stack;
    SeqStackInit(&stack);
    char str1[]="abcde";
    char str2[]="bcdea";
    char str3[]="ceabd";
    int len=strlen(str1);

    int ret=StackCorrect(&stack,str1,str2,len);
    printf("ret expect 1,actual %d\n",ret);
    ret=StackCorrect(&stack,str1,str3,len);
    printf("ret expect 0,actual %d\n",ret);

}

这里写图片描述

用一个数组实现两个栈
我们可以用一个数组的两端模拟两个栈顶。一个栈顶元素是top1,一个栈顶元素是top2。这样就实现了一个数组中同时存在两个栈。如下图所示。
一个栈的区间是:[0,top1)
一个栈的区间是:(top2,MAX_SIZE]
这里写图片描述

//用一个数组实现两个栈
//[0,top1)
//(top2,MAX_SIZE]
#define MAX_SIZE 100
typedef char ShareStackType;
typedef struct ShareStack
{
    ShareStackType data[MAX_SIZE];
    size_t top1;
    size_t top2;

}ShareStack;
void ShareStackInit(ShareStack* stack)
{
    if(stack==NULL)
    {
        return;
    }
    stack->top1=0;
    stack->top2=MAX_SIZE;
}
void ShareStackPush1(ShareStack* stack,ShareStackType value)
{
    if(stack==NULL)
    {
        return;
    }
    if(stack->top1==stack->top2)
    {
        return;
    }
    stack->data[stack->top1++]=value;
}
void ShareStackPush2(ShareStack* stack,ShareStackType value)
{
    if(stack==NULL)
    {
        return;
    }
    if(stack->top1==stack->top2)
    {
        return;
    }
    stack->data[stack->top2--]=value;
}
void ShareStackpPop1(ShareStack* stack)
{
    if(stack==NULL)
    {
        return;
    }
    stack->top1--;
}
void ShareStackpPop2(ShareStack* stack)
{
    if(stack==NULL)
    {
        return;
    }
    stack->top2++;
}
int ShareStackTop1(ShareStack* stack,ShareStackType* value)
{
    if(stack==NULL)
    {
        return 0;
    }
    if(stack->top1==stack->top2)
    {
        return 0;
    }
    *value=stack->data[stack->top1-1];
    return 1;

}

int ShareStackTop2(ShareStack* stack,ShareStackType* value)
{
    if(stack==NULL)
    {
        return 0;
    }
    if(stack->top1==stack->top2)
    {
        return 0;
    }
    *value=stack->data[stack->top2+1];
    return 1;

}

这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值