栈和队列的相关笔试面试题

在程序中引用的“seqstack.h”文件和“seqqueue.h”可以参见https://blog.csdn.net/Nessie_zhao/article/details/79917049
https://blog.csdn.net/Nessie_zhao/article/details/79834404

1.实现一个栈,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值)的时间复杂度为O(1);

思想:一次入栈两个元素,先入栈的是要存放的元素,后入栈的是栈中最小的元素
这里写图片描述

#include<stdio.h>
#include"seqstack.h"
typedef struct MinStack
{
    SeqStack stack;
}MinStack;

void MinStackInit(MinStack* min_stack)
{
    if(min_stack == NULL)
    {
        //非法输入
        return;
    }
    SeqStackInit(&min_stack->stack);
}
void MinStackPush(MinStack* min_stack,SeqStackType value)
{
    if(min_stack == NULL)    
    {
        //非法输入
        return;
    }
    SeqStackType min = value;
    SeqStackType top;
    int ret = SeqStackTop(&min_stack->stack,&top);
    if(ret != 0)
    {
        //栈非空
        min = top < value ? top : value;//如果top值比value值小就把top赋给min,否则把value值赋给min
    }
    //先插入value,再插入最小值,这样才能保证栈顶是最小值
    SeqStackPush(&min_stack->stack,value);
    SeqStackPush(&min_stack->stack,min);
    return;
}
void MinStackPop(MinStack* min_stack)
{
    if(min_stack == NULL)
    {
        //非法输入
        return;
    }
    if(min_stack->stack.size == 0)//如果栈中没有元素
    {
        return;
    }
    //入栈的时候入了两个元素,所以出栈的时候也是两个两个一起出
    SeqStackPop(&min_stack->stack);
    SeqStackPop(&min_stack->stack);
    return;
}
int MinStackTop(MinStack* min_stack,SeqStackType* value)
{
    if(min_stack == NULL || value == NULL)
    {
        //非法输入
        return 0;
    }
    if(min_stack->stack.size == 0){
        return  0;
    }
    return SeqStackTop(&min_stack->stack,value);
}
//////////////////////////////////////////////////////////
//以下为测试代码
//////////////////////////////////////////////////////////
#if 1
#define TEST_HEADER printf("\n==========================%s=============================\n",__FUNCTION__);
void TestMinStack()
{
    TEST_HEADER;
    MinStack min_stack;
    MinStackInit(&min_stack);
    MinStackPush(&min_stack,'9');
    MinStackPush(&min_stack,'5');
    MinStackPush(&min_stack,'2');
    MinStackPush(&min_stack,'7');

    SeqStackType value;
    int ret = MinStackTop(&min_stack,&value);
    printf("ret expected : 1,actual %d\n",ret);
    printf("value expected : 2,actual %c\n",value);
    MinStackPop(&min_stack);
    ret = MinStackTop(&min_stack,&value);
    printf("ret expected : 1,actual %d\n",ret);
    printf("value expected : 2,actual %c\n",value);
    MinStackPop(&min_stack);
    ret = MinStackTop(&min_stack,&value);
    printf("ret expected : 1,actual %d\n",ret);
    printf("value expected : 5 actual %c\n",value);
    MinStackPop(&min_stack);
    ret = MinStackTop(&min_stack,&value);
    printf("ret expected : 1,actual %d\n",ret);
    printf("value expected : 9,actual %c\n",value);
    MinStackPop(&min_stack);
    ret = MinStackTop(&min_stack,&value);
    printf("ret expected : 0 actual %d\n",ret);
}
int main()
{
    TestMinStack();
    return 0;
}
#endif
2.使用两个栈实现一个队列;

思想:队列是先进先出,而栈是后进先出
定义一个input栈,一个output栈,入栈的时候将output中的元素都倒腾到input中,再压入想入栈的元素。出栈的时候将input中的元素都倒腾到output中,再出栈栈顶元素,就达到了队列的先进先出的效果。
这里写图片描述

#include <stdio.h>
#include"seqstack.h"

typedef struct QueueBy2Stack
{
    //input 用于入队列场景
    SeqStack input;
    //output 用于出队列场景
    SeqStack output;
}QueueBy2Stack;

void QueueBy2StackInit(QueueBy2Stack* q)
{
    if(q == NULL)
    {
        //非法输入
        return;
    }
    //将两个栈都初始化
    SeqStackInit(&q->input);
    SeqStackInit(&q->output);
}
void QueueBy2StackPush(QueueBy2Stack* q,SeqStackType value)
{
    if(q == NULL)
    {
        //非法输入
        return;
    }
    //先把output中的元素都倒腾到input中
    while(1)
    {
        SeqStackType top;
        int ret = SeqStackTop(&q->output,&top);
        if(ret == 0)//栈中已经没有元素了
        {
            break;
        }
        //将output中的元素出栈,压入input中
        SeqStackPop(&q->output);
        SeqStackPush(&q->input,top);
    }
    //再把value入队列
    SeqStackPush(&q->input,value);
    return;
}
void QueueBy2StackPop(QueueBy2Stack* q)
{
    if(q == NULL)
    {
        //非法输入
        return;
    }
    //把input中的元素都倒腾到output中
    while(1)
    {
        SeqStackType top;
        int ret = SeqStackTop(&q->input,&top);
        if(ret == 0)
        {
            break;
        }
        SeqStackPop(&q->input);
        SeqStackPush(&q->output,top);
    }
    SeqStackPop(&q->output);
    return;
}
int QueueBy2StackFront(QueueBy2Stack* q,SeqStackType* value)
{
    if(q == NULL || value == NULL)
    {
        //非法输入
        return 0;
    }
    while(1)
    {
        SeqStackType top;
        int ret = SeqStackTop(&q->input,&top);
        if(ret == 0)
        {
            break;
        }
        SeqStackPop(&q->input);
        SeqStackPush(&q->output,top);
    }
    //现在output中栈顶元素就是最先进来的元素
    return SeqStackTop(&q->output,value);
}
///////////////////////////////////////////////////////////
//以下为测试代码
///////////////////////////////////////////////////////////
#if 1
#define TEST_HEADER printf("\n===================================%s=====================================\n",__FUNCTION__);
void TestQueueBy2Stack()
{
    TEST_HEADER;
    QueueBy2Stack queue;
    QueueBy2StackInit(&queue);
    QueueBy2StackPush(&queue,'a');
    QueueBy2StackPush(&queue,'b');
    QueueBy2StackPush(&queue,'c');
    QueueBy2StackPush(&queue,'d');

    SeqStackType value;
    int ret = QueueBy2StackFront(&queue,&value);
    printf("ret :expected 1 ,actual %d\n",ret);
    printf("value :expected a ,actual %c\n",value);

    QueueBy2StackPop(&queue);
    ret = QueueBy2StackFront(&queue,&value);
    printf("ret :expected 1 ,actual %d\n",ret);
    printf("value :expected b ,actual %c\n",value);

    QueueBy2StackPop(&queue);
    ret = QueueBy2StackFront(&queue,&value);
    printf("ret :expected 1 ,actual %d\n",ret);
    printf("value :expected c ,actual %c\n",value);

    QueueBy2StackPop(&queue);
    ret = QueueBy2StackFront(&queue,&value);
    printf("ret :expected 1 ,actual %d\n",ret);
    printf("value :expected d ,actual %c\n",value);

    QueueBy2StackPop(&queue);
    ret = QueueBy2StackFront(&queue,&value);
    printf("ret :expected 0 ,actual %d\n",ret);
}
int main()
{
    TestQueueBy2Stack();
    return 0;
}
#endif
3.使用两个队列实现一个栈;

思想:两个队列哪个不为空就把要插入的元素插到那个队列中。有元素的定义为 from 队列,没有元素的定义为 to 队列,将 from 中的元素都倒腾到 to 中直至剩一个元素的时候再出队列,这样就达到了栈的后进先出的效果。
这里写图片描述

#include <stdio.h>
#include"seqqueue.h"

typedef struct StackBy2Queue
{
    SeqQueue queue1;
    SeqQueue queue2;
}StackBy2Queue;

void StackBy2QueueInit(StackBy2Queue* s)
{
    if(s == NULL)
    {
        //非法输入
        return;
    }
    //初始化两个队列
    SeqQueueInit(&s->queue1);
    SeqQueueInit(&s->queue2);
    return;
}
void StackBy2QueuePush(StackBy2Queue* s,SeqQueueType value)
{
    if(s == NULL)
    {
        //非法输入
        return;
    }
    //取两个队列中非空的插入
    SeqQueue* input = s->queue1.size != 0 ? &s->queue1 : &s->queue2;
    SeqQueuePush(input,value);
    return;
}
void StackBy2QueuePop(StackBy2Queue* s)
{
    if(s == NULL)
    {
        //非法输入
        return;
    }
    if(s->queue1.size == 0 && s->queue2.size == 0)
    {
        //说明是空栈
        return;
    }
    //要把from中的元素倒腾到to中
    //并且一直倒腾到from中只剩一个元素
    SeqQueue* from = NULL;
    SeqQueue* to = NULL;
    //将有元素的队列赋给from
    //没有元素的队列赋给to
    if(s->queue1.size > 0)
    {
        from = &s->queue1;
        to = &s->queue2;
    }
    else
    {
        from = &s->queue2;
        to = &s->queue1;
    }
    while(1)
    {
        if(from->size == 1)
        {
            //from中只剩下一个元素
            break;
        }
        SeqQueueType value;
        SeqQueueFront(from,&value);
        SeqQueuePop(from);
        SeqQueuePush(to,value);
    }
    //from最后剩下的一个元素就是最后入队列的,最先出去
    SeqQueuePop(from);
    return;
}
int StackBy2QueueTop(StackBy2Queue* s,SeqQueueType* value)
{
    if(s == NULL || value == NULL)
    {
        //非法输入
        return 0;
    }
    //要把from中的元素倒腾到to中
    //并且一直倒腾到from中只剩一个元素
    SeqQueue* from = NULL;
    SeqQueue* to = NULL;
    if(s->queue1.size > 0)
    {
        from = &s->queue1;
        to = &s->queue2;
    }
    else
    {
        from = &s->queue2;
        to = &s->queue1;
    }
    while(1)
    {
        if(from->size == 0) {
            //已经要停止倒腾了,此时的from的对首元素就是栈顶元素
            break;
        }
        SeqQueueFront(from,value);
        SeqQueuePop(from);
        SeqQueuePush(to,*value);
    }
    SeqQueueFront(from,value);
}
///////////////////////////////////////////////////////////
//以下为测试代码
///////////////////////////////////////////////////////////
#if 1
#define TEST_HEADER printf("\n===================================%s======================================\n",__FUNCTION__);
void TestStackBy2Queue()
{
    TEST_HEADER;
    StackBy2Queue stack;
    StackBy2QueueInit(&stack);
    StackBy2QueuePush(&stack,'a');
    StackBy2QueuePush(&stack,'b');
    StackBy2QueuePush(&stack,'c');
    StackBy2QueuePush(&stack,'d');

    SeqQueueType value;
    int ret = StackBy2QueueTop(&stack,&value);
    printf("ret :expected 1,actual %d\n",ret);
    printf("value :expected d,actual %c\n",value);
    StackBy2QueuePop(&stack);
    ret = StackBy2QueueTop(&stack,&value);
    printf("ret :expected 1,actual %d\n",ret);
    printf("value :expected c,actual %c\n",value);
    StackBy2QueuePop(&stack);
    ret = StackBy2QueueTop(&stack,&value);
    printf("ret :expected 1,actual %d\n",ret);
    printf("value :expected b,actual %c\n",value);
    StackBy2QueuePop(&stack);
    ret = StackBy2QueueTop(&stack,&value);
    printf("ret :expected 1,actual %d\n",ret);
    printf("value :expected a,actual %c\n",value);
    StackBy2QueuePop(&stack);
   ret = StackBy2QueueTop(&stack,&value);
   printf("ret :expected 0,actual %d\n",ret);
}
int main()
{
    TestStackBy2Queue();
    return 0;
}
#endif
4.元素出栈、入栈顺序的合法性。如入栈的顺序(a,b,c,d,e),出栈序列为(d,e,c,,b,a);

思想:第一重循环,循环的遍历 input ,如果栈顶元素的值和 output_index 的值相等循环出栈,并且再次比较栈顶元素和output_index 移进后的值。
这里写图片描述

这里写图片描述

接下来比较栈顶元素和output_index所指向的元素是否相等

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

此时栈已经空了,而且output_index 也走到了结尾,所以该入栈顺序是合法的!按照此方法编写相应代码如下:

#include <stdio.h>
#include<stddef.h>
#include"seqstack.h"
//返回1表示能够变换成功
//返回0表示不能变换成功
int StackOrder(char input[],size_t input_size,char output[],size_t output_size)
{
    SeqStack stack;
    SeqStackInit(&stack);
    //循环的把input的元素入栈
    size_t i = 0;
    size_t output_index = 0;
        char top;
    for(;i < input_size;++i)
    {
        SeqStackPush(&stack,input[i]);
        int ret = SeqStackTop(&stack,&top);
        if(ret == 0)
        {
            //栈已空,准备进行最终审判
            break;
        }
        //取栈顶元素,和output_index指向的元素比较
        while(1)
        {
            if(output_index >= output_size )
            {
                //output序列已经遍历完了,也得进行最终审判
                break;
            }
            if(top != output[output_index])//比较栈顶元素和此时output_index所指的值是否相等,如果不相等就继续入栈
            {
                break;
            }
            ++output_index;//output_index指针后移
            SeqStackPop(&stack);//将栈顶元素出栈
        }
    }
    while(1)
     {
        //如果不相等,继续循化取下一个input元素入栈
        //如果相等
        //a)移进output_index
        //b) 把栈顶元素出栈
        //c)循环的比较栈顶元素和output_index指向的元素的值
        SeqStackTop(&stack,&top);
        if(output_index >= output_size)
        {
             //output序列已经遍历完了,也得进行最终审判
               break;
         }
        if(top != output[output_index])
        {
             break;
         }
        ++output_index;
        SeqStackPop(&stack);
    }
  //如果最终栈为空并且output_index指向output数组中的最后一个元素,就认为能够变换得到
    //否则就无法变换得到
    if(stack.size == 0 && output_index == output_size)
    {
        return 1;
    }
    return 0;
}
///////////////////////////////////////////////////////////
//以下为测试代码
///////////////////////////////////////////////////////////
#if 1
#define TEST_HEADER printf("\n======================================%s===================================\n",__FUNCTION__);

void TestStackOrder()
{
    TEST_HEADER;
    char input[5] = {'a','b','c','d','e'};
    char output1[5] = {'d','e','c','b','a'};
    char output2[5] = {'a','b','c','d','e'};
    char output3[5] = {'e','d','c','b','a'};
    char output4[5] = {'d','e','a','b','c'};
    int size_in = sizeof(input);
    int size_out1 = sizeof(output1);
    int size_out2 = sizeof(output2);
    int size_out3 = sizeof(output3);
    int size_out4 = sizeof(output4);
    int ret = StackOrder(input,size_in,output1,size_out1);
    printf("ret : expected 1,actual %d\n",ret);
    ret = StackOrder(input,size_in,output2,size_out2);
    printf("ret : expected 1,actual %d\n",ret);
    ret = StackOrder(input,size_in,output3,size_out3);
    printf("ret : expected 1,actual %d\n",ret);
    ret = StackOrder(input,size_in,output4,size_out4);
    printf("ret : expected 0,actual %d\n",ret);
}
int main()
{
    TestStackOrder();
    return 0;
}
#endif
5.一个数组实现两个共享栈;

思想:
第一个栈:[0,top1)
第二个栈:[top2,max_size)
表示栈满了条件:top1 == top2
这里写图片描述

#include <stdio.h>

#define SharedStackMaxSize 1000
typedef char SharedStackType;
//[0,top1)表示第一个栈
//[top2,SharedStackMaxSize)表示第二个栈
typedef struct SharedStack
{
    SharedStackType data[SharedStackMaxSize];
    size_t top1;
    size_t top2;
}SharedStack;

void SharedStackInit(SharedStack* s)
{
    if(s == NULL)
    {
        //非法输入
        return;
    }
    s->top1 = 0;//top1是从0开始,每入栈一个元素top1++
    s->top2 = SharedStackMaxSize;//top2是从SharedStackMaxSize,每入栈一个元素,top2--
    return;
}

void SharedStackPush1(SharedStack* s,SharedStackType value)
{
    if(s == NULL)
    {
        //非法输入
        return;
    }
    if(s->top1 >= s->top2)
    {
        //第一个栈已经满了
        return;
    }
    //将value值赋给s->data[top1],并将top1后移
    s->data[s->top1++] = value;
    return;
}

void SharedStackPush2(SharedStack* s,SharedStackType value)
{
    if(s == NULL)
    {
        //非法输入
        return;
    }
   if(s->top1 >= s->top2) 
   {
       //栈已经满了
       return;
   }
   //先把top2前移,再将value值赋给s->data[top2]
   s->data[--s->top2] = value;
   return;
}

void SharedStackPop1(SharedStack* s)
{
    if(s == NULL)
    {
        //非法输入
        return;
    }
    if(s->top1 == 0)
    {
        return;
    }
    //直接将top1前移
    --s->top1;
    return;
}

void SharedStackPop2(SharedStack* s)
{
    if(s == NULL)
    {
        //非法输入
        return;
    }
    if(s->top2 == SharedStackMaxSize)
    {
        return;
    }
    //将top2后移
    ++s->top2;
    return;
}

int SharedStackTop1(SharedStack* s,SharedStackType* value)
{
    if(s == NULL || value == NULL)
    {
        //非法输入
        return 0;
    }
    if(s->top1 == 0)
    {
        return 0;
    }
    //因为此时top1位置上没有元素,最后一个入栈的元素在top1-1位置上,所以需要先减1,再进行赋值
    *value = s->data[s->top1 - 1];
    return 1;
}

int SharedStackTop2(SharedStack* s,SharedStackType* value)
{
    if(s == NULL || value == NULL)
    {
        //非法输入
        return 0;
    }
    if(s->top2 == SharedStackMaxSize)
    {
        return 0;
    }
    //此时top2位置上就是最后入栈一个元素
    *value = s->data[s->top2];
    return 1;
}
///////////////////////////////////////////////////////////
//以下为测试代码
///////////////////////////////////////////////////////////
#define TEST_HEADER printf("\n=======================================%s=====================================\n",__FUNCTION__);
void TestSharedStack()
{
    TEST_HEADER;
    SharedStack stack;
    SharedStackInit(&stack);
    SharedStackPush1(&stack,'a');    
    SharedStackPush1(&stack,'b');    
    SharedStackPush1(&stack,'c');    
    SharedStackPush1(&stack,'d');    

    SharedStackType value1;
    int ret = SharedStackTop1(&stack,&value1);
    printf("ret :expected 1,actual %d\n",ret);
    printf("value :expected d,actual %c\n",value1);
    SharedStackPop1(&stack);
    ret = SharedStackTop1(&stack,&value1);
    printf("ret :expected 1,actual %d\n",ret);
    printf("value :expected c,actual %c\n",value1);
    SharedStackPop1(&stack);
    ret = SharedStackTop1(&stack,&value1);
    printf("ret :expected 1,actual %d\n",ret);
    printf("value :expected b,actual %c\n",value1);
    SharedStackPop1(&stack);
    ret = SharedStackTop1(&stack,&value1);
    printf("ret :expected 1,actual %d\n",ret);
    printf("value :expected a,actual %c\n",value1);
    SharedStackPop1(&stack);
    ret = SharedStackTop1(&stack,&value1);
    printf("ret :expected 0,actual %d\n",ret);

    TEST_HEADER;
    SharedStackPush2(&stack,'a');    
    SharedStackPush2(&stack,'b');    
    SharedStackPush2(&stack,'c');    
    SharedStackPush2(&stack,'d');    
    SharedStackType value2;
    ret = SharedStackTop2(&stack,&value2);
    printf("ret :expected 1,actual %d\n",ret);
    printf("value :expected d,actual %c\n",value2);
    SharedStackPop2(&stack);
    ret = SharedStackTop2(&stack,&value2);
    printf("ret :expected 1,actual %d\n",ret);
    printf("value :expected c,actual %c\n",value2);
    SharedStackPop2(&stack);
    ret = SharedStackTop2(&stack,&value2);
    printf("ret :expected 1,actual %d\n",ret);
    printf("value :expected b,actual %c\n",value2);
    SharedStackPop2(&stack);
    ret = SharedStackTop2(&stack,&value2);
    printf("ret :expected 1,actual %d\n",ret);
    printf("value :expected a,actual %c\n",value2);
    SharedStackPop2(&stack);
    ret = SharedStackTop2(&stack,&value2);
    printf("ret :expected 0,actual %d\n",ret);
}
int main()
{
    TestSharedStack();
    return 0;
}
#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值