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

1.实现一个最小栈,每次取得都是栈里面的最小值,时间复杂度为O(1)
思路:每次入栈两个元素,一个存当前值,一个存当前栈的最小值,先将当前值入栈,再将最小值入栈,出栈时也一次出两个。如图所示:
这里写图片描述
代码如下:

#include"seqstack.h"
#include<stdio.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)
    {
        //将栈顶元素和value值进行比较,将小指赋给min
        if(top > value)
        {
            min = value;
        }
        min = top;
    }
    //一次入两个元素,先插value,后插min,才能保证栈顶元素是最小的
    SeqStackPush(&min_stack->stack,value);
    SeqStackPush(&min_stack->stack,min);
}

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)
    {
        return 0;//非法输入
    }
    SeqStackTop(&min_stack->stack,value);
}

///////////////////////////////////////
/////////以下是测试代码///////////////
//////////////////////////////////////

#define TEST_HEADER printf("\n==============%s============\n",__FUNCTION__)

void TestMinStack()
{
    TEST_HEADER;
    MinStack min_stack;
    MinStackInit(&min_stack);
    MinStackPush(&min_stack,'a');
    MinStackPush(&min_stack,'b');
    MinStackPush(&min_stack,'c');
    MinStackPush(&min_stack,'d');

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

    MinStackPop(&min_stack);
    MinStackPop(&min_stack);
    ret = MinStackTop(&min_stack,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value1 expected a,actual %c\n",value);  
}

int main()
{
    TestMinStack();
    printf("\n");
    return 0;
}

2.使用两个栈实现一个队列
思路:一个栈实现入队列的场景,一个栈实现出队列和取队首元素
这里写图片描述
例如上图,按照队列”先进先出”规则,先将a b c d按顺序依次压入input栈,然后取input栈栈顶元素按顺序依次出栈再压入output栈,最后在output栈依次出栈栈顶元素,就达到预期效果。
代码如下:

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

typedef struct QueueBy2Stack
{
    SeqStack input;
    SeqStack output;
}QueueBy2Stack;

void QueueInit(QueueBy2Stack* queue)
{
    if(queue == NULL)
    {
        return;//非法输入
    }
    SeqStackInit(&queue->input);
    SeqStackInit(&queue->output);
}

void QueuePush(QueueBy2Stack* q,SeqStackType value)
{
    if(q == NULL)
    {
        return;//非法输入
    }
    //先把所有output的元素出栈然后按顺序入栈到input里
    while(1)
    {
        SeqStackType top;
        int ret = SeqStackTop(&q->output,&top);
        if(ret == 0)
        {
            break;
        }
        SeqStackPush(&q->input,top);
        SeqStackPop(&q->output);
    }
    //把新元素value插入到input中
    SeqStackPush(&q->input,value);
    return;
}

void QueuePop(QueueBy2Stack* q)
{
    if(q == NULL)
    {
        return;//非法输入
    }
    //先把input里所有元素倒腾到output里
    while(1)
    {
        SeqStackType top;
        int ret = SeqStackTop(&q->input,&top);
        if(ret == 0)
        {
            break;
        }
        SeqStackPush(&q->output,top);
        SeqStackPop(&q->input);
    }
    SeqStackPop(&q->output);
    return;
}

int QueueFront(QueueBy2Stack* q,SeqStackType* value)
{
    if(q == NULL|| value == NULL)
    {
        return 0;;//非法输入
    }
    //把input里的所有元素倒腾到output里
    while(1)
    {
        SeqStackType top;
        int ret = SeqStackTop(&q->input,&top);
        if(ret == 0)
        {
            break;
        }
        SeqStackPush(&q->output,top);
        SeqStackPop(&q->input);
    }
    return SeqStackTop(&q->output,value);

}
////////////////////////////////////////
//////////以下是测试代码///////////////
///////////////////////////////////////
#if 1
#include<stdio.h>
#define TEST_HEADER printf("\n=================%s================\n",__FUNCTION__)

void TestQueue()
{
    TEST_HEADER;
    QueueBy2Stack queue;
    QueueInit(&queue);
    QueuePush(&queue,'a');
    QueuePush(&queue,'b');
    QueuePush(&queue,'c');
    QueuePush(&queue,'d');

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

    QueuePop(&queue);
    ret = QueueFront(&queue,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected b,acatual %c\n",value);

    QueuePop(&queue);
    ret = QueueFront(&queue,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected c,acatual %c\n",value);

    QueuePop(&queue);
    ret = QueueFront(&queue,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected d,acatual %c\n",value);

    QueuePop(&queue);
    ret = QueueFront(&queue,&value);
    printf("ret expected 0,actual %d\n",ret);
}

int main()
{
    TestQueue();
    printf("\n");
    return 0;
}
#endif

3.使用两个队列实现一个栈
思路:入栈时将元素插入到不为空的队列里,出栈时将不为空的队列里只留下最后一个元素,将其余元素出队列然后插入到另一个空队列里。需要注意的是要搞清楚将元素从哪个队列倒腾到哪个队列。
这里写图片描述
代码如下:

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

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

void StackInit(StackBy2Queue* stack)
{
    if(stack == NULL)
    {
        return;//非法输入
    }

    SeqQueueInit(&stack->queue1);
    SeqQueueInit(&stack->queue2);
}

void StackPush(StackBy2Queue* stack,SeqQueueType value)
{
    if(stack == NULL)
    {
        return;//非法输入
    }
    SeqQueue* input;
    //先判断哪个队列不为空,然后将元素插入到那个队列里
    if(stack->queue1.size != 0)
    {
        input = &stack->queue1;
    }
    input = &stack->queue2;
    SeqQueuePush(input,value);
}

void StackPop(StackBy2Queue* stack)
{
    if(stack == NULL)
    {
        return;//非法输入
    }
    //如果是空栈,直接返回
    if(stack->queue1.size == 0 && stack->queue2.size == 0)
    {
        return;
    }
    //先判断哪个队列为空,不为空队列为from,空队列为to
    SeqQueue* from = NULL;
    SeqQueue* to = NULL;
    if(stack->queue1.size > 0)
    {
        from = &stack->queue1;
        to = &stack->queue2;
    }
    else
    {
        from = &stack->queue2;
        to = &stack->queue1;
    }
    //把from中的元素倒腾到to中,直到from中只剩下一个元素
    while(1)
    {
        if(from->size == 1)
        {
            break;
        }
        SeqQueueType value;
        int ret = SeqQueueFront(from,&value);
        SeqQueuePop(from);
        SeqQueuePush(to,value);
    }
    SeqQueuePop(from);
}

int StackFront(StackBy2Queue* stack,SeqQueueType* value)
{
    if(stack == NULL)
    {
        return 0;//非法输入
    }
    //如果是空栈,直接返回
    if(stack->queue1.size == 0 && stack->queue2.size == 0)
    {
        return 0;
    }
    //先判断哪个队列为空,不为空队列为from,空队列为to
    SeqQueue* from = NULL;
    SeqQueue* to = NULL;
    if(stack->queue1.size > 0)
    {
        from = &stack->queue1;
        to = &stack->queue2;
    }
    else
    {
        from = &stack->queue2;
        to = &stack->queue1;
    }
    //把from中的元素倒腾到to中,直到from中只剩下一个元素
    while(1)
    {
        if(from->size == 1)
        {
            break;
        }
        SeqQueueFront(from,value);
        SeqQueuePop(from);
        SeqQueuePush(to,*value);
    }
    //将剩下的最后一个元素取出来赋给value
    SeqQueueFront(from,value);
    SeqQueuePop(from);
    SeqQueuePush(to,*value);
    return 1;
}

//以下是测试代码///
//
#if 1
#include<stdio.h>
#define TEST_HEADER printf("\n====================%s=======================\n",__FUNCTION__)
void TestStack()
{
    TEST_HEADER;
    StackBy2Queue stack;
    StackInit(&stack);
    StackPush(&stack,'a');
    StackPush(&stack,'b');
    StackPush(&stack,'c');
    StackPush(&stack,'d');

    SeqQueueType value;
    int ret = StackFront(&stack,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected d,actual %c\n",value);

    StackPop(&stack);
    ret = StackFront(&stack,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected c,actual %c\n",value);

    StackPop(&stack);
    ret = StackFront(&stack,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected b,actual %c\n",value);

    StackPop(&stack);
    ret = StackFront(&stack,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected a,actual %c\n",value);

    StackPop(&stack);
    ret = StackFront(&stack,&value);
    printf("ret expected 0,actual %d\n",ret);
}
int main()
{
    TestStack();
    printf("\n");
    return 0;
}
#endif

4.判断一个入栈序列是否可以通过入栈、出栈操作得到出栈序列,如,入栈序列(input)为(a,b,c,d,e),出栈序列(output)为(d,e,c,b,a)
思路:定义两重循环,第一重,循环的遍历input,然后将input中的元素入栈;第二重,取栈顶元素,如果栈顶元素的值和oi指向的值相同,循环的出栈,并且再次比较栈顶元素和oi移进之后的值。
这里写图片描述
代码如下:

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

//返回1表示能变换成功
//返回0表示不能变换成功
int StackOrder(char input[],size_t input_size,char output[],size_t output_size)
{
    SeqStack stack;
    SeqStackInit(&stack);
    size_t i = 0;
    size_t output_index = 0;
    char top;
    for( ;i < input_size;i++)
    {

      //1.循环的把input入栈
          SeqStackPush(&stack,input[i]);
          int ret = SeqStackTop(&stack,&top);
         //2.取栈顶元素,和output_index指向的元素进行比较
          while(1)
          {
                SeqStackTop(&stack,&top);
                 if(output_index >= output_size)
                 {
                     break;//output_index走到output数组的最后一个
                 }
                 //3.如果不相等,继续循环取下一个input元素入栈
                 if(top != output[output_index])
                 {
                     break;
                 }
                 //4.如果相等
                //  a)移进output_index
                //  b)把栈顶元素出栈
                //  c)再循环的比较栈顶元素和output_index指向的值
                 ++output_index;
                 SeqStackPop(&stack);
          }
          if(ret == 0)
          {
              break;//栈为空进行最终审判
          }
    }

    //5.如果最后栈为空并且output_index指向output数组中的最后一个元素的下一个元素,
    //就认为output可以通过input变换得到
    //6.否则则不能通过变换得到
    if(stack.size == 0 && output_index == output_size)
    {
        return 1;
    }
    return 0;
}
////////////////////////////////////
//////////以下为测试代码////////////
///////////////////////////////////
#if 1
#include<stdio.h>
#define TEST_HEADER printf("\n====================%s======================\n",__FUNCTION__)
void TestOrder()
{
    TEST_HEADER;
    char input[6] = "abcde";
    char output[6] = "decba";
    size_t input_size = strlen(input);
    size_t output_size = strlen(output);
    int ret = StackOrder(input,input_size,output,output_size);
    printf("ret expected 1,actual %d\n",ret);
    if(ret == 1)
    {
        printf("output 可以通过input变换得到\n");
    }
    else
    {
        printf("output 不能通过input变换得到\n");
    }   
}
int main()
{
    TestOrder();
    printf("\n");
    return 0;
}
#endif

5.一个数组实现两个栈(共享栈)
这里写图片描述
我们做一种约定:第一个栈区间为[0,top1),第二个栈区间为[top2,max_size),当top1 == top2表示栈满了。
代码如下:

#include<stdio.h>
#include<stddef.h>
#define SharedStackMixSize 1000

typedef char SharedStackType;

//[0,top1)表示第一个栈
//[top2,SharedSatckMixSize)表示第二个栈
typedef struct SharedStack
{
    SharedStackType data[SharedStackMixSize];
    size_t top1;
    size_t top2;
}SharedStack;

void SharedStackInit(SharedStack* stack)
{
    if(stack == NULL)
    {
        return;//非法输入
    }
    stack->top1 = 0;
    stack->top2 = SharedStackMixSize;
    return;
}

void SharedStackPush1(SharedStack* stack,SharedStackType value)
{
    if(stack == NULL)
    {
        return;//非法输入
    }
    if(stack->top1 >= stack->top2)
    {
        return;//栈已满,不能再插入元素
    }
    stack->data[stack->top1++] = value;//将元素插入到top1指向的位置,再将top1指向下一个位置
    return;
}

void SharedStackPush2(SharedStack* stack,SharedStackType value)
{
    if(stack == NULL)
    {
        return;//非法输入
    }
    if(stack->top1 >= stack->top2)
    {
        return;//栈已满,不能再插入元素
    }
    stack->data[--stack->top2] = value;//先将top2减一,再将元素插入到top2指向的位置
    return;
}

int SharedStackTop1(SharedStack* stack,SharedStackType* value)
{
    if(stack == NULL)
    {
        return 0;//非法输入
    }
    if(stack->top1 == 0)
    {
        return 0;//空栈
    }
    *value = stack->data[stack->top1-1];//top1的前一个位置为有效值,将其赋给value
    return 1;
}

int SharedStackTop2(SharedStack* stack,SharedStackType* value)
{
    if(stack == NULL)
    {
        return 0;//非法输入
    }
    if(stack->top2 == SharedStackMixSize)
    {
        return 0;//空栈
    }
    *value = stack->data[stack->top2];//top2指向的位置就是有效值,将其赋给value
    return 1;
}

void SharedStackPop1(SharedStack* stack)
{
    if(stack == NULL)
    {
        return;//非法输入
    }
    if(stack->top1 == 0)
    {
        return;//空栈
    }
    --stack->top1;
    return;
}

void SharedStackPop2(SharedStack* stack)
{
    if(stack == NULL)
    {
        return;//非法输入
    }
    if(stack->top2 == SharedStackMixSize)
    {
        return;//空栈
    }
    ++stack->top2;
    return;
}
/
///以下是测试代码///
///
#include<stdio.h>
#if 1
#define TEST_HEADER printf("\n=======================%s====================\n",__FUNCTION__)
void TestInit()
{
    TEST_HEADER;
    SharedStack stack;
    SharedStackInit(&stack);
}
void Test1()
{

    TEST_HEADER;
    SharedStack stack;
    SharedStackInit(&stack);
    SharedStackPush1(&stack,'a');
    SharedStackPush1(&stack,'b');
    SharedStackPush1(&stack,'c');
    SharedStackPush1(&stack,'d');

    SharedStackType value;
    int ret = SharedStackTop1(&stack,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected d,actual %c\n",value);

    SharedStackPop1(&stack);
    SharedStackPop1(&stack);
    ret = SharedStackTop1(&stack,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected b,actual %c\n",value);

    SharedStackPop1(&stack);
    SharedStackPop1(&stack);
    ret = SharedStackTop1(&stack,&value);
    printf("ret expected 0,actual %d\n",ret);
}

void Test2()
{

    TEST_HEADER;
    SharedStack stack;
    SharedStackInit(&stack);
    SharedStackPush2(&stack,'a');
    SharedStackPush2(&stack,'b');
    SharedStackPush2(&stack,'c');
    SharedStackPush2(&stack,'d');

    SharedStackType value;
    int ret = SharedStackTop2(&stack,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected d,actual %c\n",value);

    SharedStackPop2(&stack);
    SharedStackPop2(&stack);
    ret = SharedStackTop2(&stack,&value);
    printf("ret expected 1,actual %d\n",ret);
    printf("value expected b,actual %c\n",value);

    SharedStackPop2(&stack);
    SharedStackPop2(&stack);
    ret = SharedStackTop2(&stack,&value);   
    printf("ret expected 0,actual %d\n",ret);
}
int main()
{
    TestInit();
    Test1();
    Test2();
    printf("\n");
    return 0;
}
#endif


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值