栈和队列面试题总结

栈的基础操作
https://blog.csdn.net/hansionz/article/details/81636557
队列的基础操作
https://blog.csdn.net/hansionz/article/details/81636644

栈和队列面试题(c语言实现)

1.实现一个栈,要求实现Push(入栈)、Pop(出栈)、Min(返回最小值)的时间复杂度为O(1).
2.使用两个栈实现一个队列
3.使用两个队列实现一个栈
4.元素出栈、入栈的合法性。如入栈的序列(1,2,3,4,5),出栈序列为(4,5,3,2,1)
5.一个数组实现两个共享栈

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

思路:
这里写图片描述

/**************************************************************/
//1.获取最小值(O(1))
typedef struct GetMinStack
{
    Stack _mst;//存放正常入栈序列
    Stack _msmin;//存放最小值
}GetMinStack;

//入栈操作
void Stack_O1Push(GetMinStack* ps, DataType x);
//出栈操作
void Stack_O1Pop(GetMinStack* ps);
//获取最小值
DataType GetMinValue(GetMinStack* ps);
//取栈顶元素
DataType GetStack_O1Top(GetMinStack* ps);

void Stack_O1Push(GetMinStack* ps, DataType x)
{
    assert(ps);
    //存放数据的栈无论如何必须压栈
    StackPush(&ps->_mst, x);
    //如果存放最小值那个栈栈顶元素大于x或者是那个栈还为空,必须压栈
    if ((StackTop(&ps->_msmin) > x) || (StackEmpty(&ps->_msmin) == 0))
    {
        StackPush(&ps->_msmin, x);
    }
}
void Stack_O1Pop(GetMinStack* ps)
{
    assert(ps);
    //比较两个栈顶元素是否相同,如果相同都出栈,如果不相同,只出数据栈
    if (StackTop(&ps->_mst) == StackTop(&ps->_msmin))
    {
        StackPop(&ps->_msmin);
    }
    StackPop(&ps->_mst);
}
DataType GetMinValue(GetMinStack* ps)
{
    assert(ps);
    return StackTop(&ps->_msmin);
}
DataType GetStack_O1Top(GetMinStack* ps)
{
    assert(ps);
    return StackTop(&ps->_mst);
}
2.使用两个栈实现一个队列

思路:
这里写图片描述

typedef struct QueueBy2Stack
{
    Stack input;//实现入队的栈
    Stack output;//实现出队的栈
}QueueBy2Stack;

//初始化函数
void QueueInit(QueueBy2Stack* pq);
//销毁函数
void QueueDestroy(QueueBy2Stack* pq);
//入队函数
void QueuePush(QueueBy2Stack* pq, DataType x);
//出队函数
void QueuePop(QueueBy2Stack* pq);
//取队头元素函数
DataType QueueFront(QueueBy2Stack*pq);
//求队列大小
int QueueSize(QueueBy2Stack* pq);
//判断队列是否为空,空返回0,非空返回1
int QueueEmpty(QueueBy2Stack* pq);

/****************************************************************/
/*两个栈实现一个队列*/
void QueueInit(QueueBy2Stack* pq)
{
    assert(pq);
    StackInit(&pq->input);
    StackInit(&pq->output);
}
void QueueDestroy(QueueBy2Stack* pq)
{
    assert(pq);
    StackDestroy(&pq->input);
    StackDestroy(&pq->output);
}
void QueuePush(QueueBy2Stack* pq, DataType x)
{
    assert(pq);
    //把output栈所有元素拿到input栈
    while (StackEmpty(&pq->output))
    {
        DataType tmp;
        tmp = StackTop(&pq->output);
        StackPop(&pq->output);
        StackPush(&pq->input, tmp);
    }
    //然后入栈既入队
    StackPush(&pq->input, x);
}
void QueuePop(QueueBy2Stack* pq)
{
    assert(pq);
    //把input栈所有元素拿到output栈
    while (StackEmpty(&pq->input))
    {
        DataType tmp;
        tmp = StackTop(&pq->input);
        StackPop(&pq->input);
        StackPush(&pq->output, tmp);
    }
    //然后出栈相当于出队
    StackPop(&pq->output);
}
DataType QueueFront(QueueBy2Stack*pq)
{
    assert(pq);
    while (StackEmpty(&pq->input))
    {
        DataType tmp;
        tmp = StackTop(&pq->input);
        StackPop(&pq->input);
        StackPush(&pq->output, tmp);
    }
    //和pop一样只不过这里变成取栈顶
    return StackTop(&pq->output);
}
int QueueSize(QueueBy2Stack* pq)
{
    assert(pq);

    return StackSize(&pq->input) + StackSize(&pq->output);
}
//空返回0,非空返回1
int QueueEmpty(QueueBy2Stack* pq)
{
    assert(pq);

    return StackEmpty(&pq->input) | StackEmpty(&pq->output);
}
3.使用两个队列实现一个栈

思路:
这里写图片描述

typedef struct StackBy2Queue
{
    Queue queue1;
    Queue queue2;
    int size;//有效元素的个数
}StackBy2Queue;

//初始化函数
void StackInit(StackBy2Queue* ps);
//销毁函数
void StackDestroy(StackBy2Queue* ps);
//入栈操作函数
void StackPush(StackBy2Queue* ps, DataType x);
//出栈操作函数
void StackPop(StackBy2Queue* ps);
//取栈顶元素函数
DataType StackGetTop(StackBy2Queue* ps);
//求栈的大小
int StackSize(StackBy2Queue* ps)
//判断栈是否为空,空返回0,非空返回1
int StackEmpty(StackBy2Queue* ps)
/***************************************************************/
/*两个队列实现一个栈*/
//初始化栈
void StackInit(StackBy2Queue* ps)
{
    assert(ps);
    QueueInit(&ps->queue1);
    QueueInit(&ps->queue2);
    ps->size = 0;
}
//销毁栈
void StackDestroy(StackBy2Queue* ps)
{
    assert(ps);
    QueueDestroy(&ps->queue1);
    QueueDestroy(&ps->queue2);
    ps->size = 0;
}
//入栈操作
void StackPush(StackBy2Queue* ps, DataType x)
{
    assert(ps);
    //两个队列都为空,插入哪一个都行,有一个队列不为空,就插入那个队列
    if (QueueSize(&ps->queue1) != 0)
    {
        QueuePush(&ps->queue1, x);
    }
    else
    {
        QueuePush(&ps->queue2, x);
    }
    ps->size++;
}
//出栈操作
void StackPop(StackBy2Queue* ps)
{
    assert(ps);
    //空栈
    if (ps->size == 0)
    {
        return;
    }
    //确定那个队列为空,那个不为空
    Queue* _Have = &ps->queue1;//有元素
    Queue* _NoHave = &ps->queue2;//没有元素

    if (QueueSize(&ps->queue1) == 0)
    {
        _Have = &ps->queue2;
        _NoHave = &ps->queue1;
    }
    //不为空的队列保留一个元素,最后出队既是出栈
    while (QueueSize(_Have)!=1)
    {
        DataType tmp;
        tmp = QueueFront(_Have);
        QueuePop(_Have);
        QueuePush(_NoHave, tmp);
    }
    QueuePop(_Have);
    ps->size--;
}
//取栈顶元素
DataType StackGetTop(StackBy2Queue* ps)
{
    assert(ps);
    //空栈
    if (ps->size == 0)
    {
        return;
    }
    Queue* _Have = &ps->queue1;//有元素
    Queue* _NoHave = &ps->queue2;//没有元素

    if (QueueSize(&ps->queue1) == 0)
    {
        _Have = &ps->queue2;
        _NoHave = &ps->queue1;
    }
    //直接返回队尾元素或者是下面的做法(移到另一个队列,取队头)
    return QueueBack(_Have);
#if 0
    while (QueueSize(_Have) != 1)
    {
        DataType tmp;
        tmp = QueueFront(_Have);
        QueuePop(_Have);
        QueuePush(_NoHave, tmp);
    }
    DataType cur = QueueFront(_Have);
    QueuePop(_Have);
    QueuePush(_NoHave, cur);
    return cur;
#endif
}
int StackSize(StackBy2Queue* ps)
{
    assert(ps);
    return QueueSize(&ps->queue1) + QueueSize(&ps->queue2);
}
//空 返回0,非空返回1
int StackEmpty(StackBy2Queue* ps)
{
    assert(ps);
    return QueueEmpty(&ps->queue1) | QueueEmpty(&ps->queue2);
}
4.元素出栈、入栈的合法性。如入栈的序列(1,2,3,4,5),出栈序列为(4,5,3,2,1)

思路:
这里写图片描述

/*************************************************************/
/*检查出入栈的合法性,合法返回1,不合法返回0*/
int CheckLegal(int* num_in, int* num_out,int len_in,int len_out)
{
    Stack s;
    StackInit(&s);
    //如果两个出入栈序列长度不相同必然不合法
    if (len_in != len_out)
    {
        return 0;
    }
    assert(num_in);
    assert(num_out);
    int j = 0;
    for (int i = 0; i < len_in; i++)
    {
        StackPush(&s, num_in[i]);
        //栈顶元素和出栈序列相同则出栈一次,出栈序列向后移动一位
        //不相同则继续入栈入栈序列
        while ((StackEmpty(&s) != 0) && (StackTop(&s) == num_out[j]))
        {
            StackPop(&s);
            j++;
        }
    }
    return StackEmpty(&s) == 0 ? 1 : 0;
}
5.一个数组实现两个共享栈

思路:
这里写图片描述
第一种用于有缺陷,这里就不实现了。只实现第二种和第三种方式。

第二种实现方式:

#define MAXSIZE 10
typedef struct StackShare
{
    DataType* _a;
    int top_low;//左栈栈顶
    int top_high;//右栈栈顶
}StackShare;
//初始化栈
void StackShareInit(StackShare* ps);
//销毁栈
void StackShareDestroy(StackShare* ps);
//检查栈是否满
int StackIsFull(StackShare* ps);
//检查共享栈是否为空
int StackShareEmpty(StackShare* ps, char c);
//求栈的大小
int StackShareSize(StackShare* ps, char c);
//入栈操作
void StackSharePush(StackShare* ps, DataType x, char c);
//出栈操作
void StackSharePop(StackShare* ps, char c);
//取栈顶元素
DataType StackShareTop(StackShare* ps, char c);
/***************************************************************/
/*共享栈,‘L’代表左栈,‘R’代表右栈(静态实现)*/
//初始化栈
void StackShareInit(StackShare* ps)
{
    assert(ps);
    memset(ps->_a, sizeof(DataType)*MAXSIZE, 0);
    ps->top_high = MAXSIZE - 1;
    ps->top_low = 0;
}
//销毁栈
void StackShareDestroy(StackShare* ps, char c)
{
    assert(ps);
    assert((c == 'R' || (c == 'L')));
    if (c == 'L')
    {
        ps->top_low = 0;
    }
    else
    {
        ps->top_high = 0;
    }
}
//判断栈是否为空,空返回0,非空返回1
int StackShareEmpty(StackShare* ps, char c)
{
    assert(ps);
    assert((c == 'R' || (c == 'L')));
    //左栈
    if (c == 'L')
    {
        return ps->top_low == 0 ? 0 : 1;
    }
    //右栈
    else
    {
        return ps->top_high == MAXSIZE - 1 ? 0 : 1;
    }
}
//栈的大小
int StackShareSize(StackShare* ps, char c)
{
    assert(ps);
    assert((c == 'R' || (c == 'L')));
    if (c == 'L')
    {
        return ps->top_low;
    }
    else 
    {
        return MAXSIZE - 1 - ps->top_high;
    }
}
//入栈
void StackSharePush(StackShare* ps, DataType x, char c)
{
    assert(ps);
    assert((c == 'R' || (c == 'L')));
    if (StackIsFull(ps))
    {
        printf("StackFull\n");
        return;
    }
    if (c == 'L')
    {
        ps->_a[ps->top_low] = x;
        ps->top_low++;
    }
    else
    {
        ps->_a[ps->top_high] = x;
        ps->top_high--;
    }
}
//出栈
void StackSharePop(StackShare* ps, char c)
{
    assert(ps);
    assert((c == 'R' || (c == 'L')));
    if (c == 'L')
    {
        if (StackShareEmpty(ps, c))
        {
            ps->top_low--;
        }
        else
        {
            printf("StackEmpty\n");
        }
    }
    else
    {
        if (StackShareEmpty(ps, c))
        {
            ps->top_high++;
        }
        else
        {
            printf("StackEmpty\n");
        }
    }
}
//取栈顶元素
DataType StackShareTop(StackShare* ps, char c)
{
    assert(ps);
    assert((c == 'R' || (c == 'L')));
    if (c == 'L')
    {
        return ps->_a[ps->top_low - 1];
    }
    else
    {
        return ps->_a[ps->top_high + 1];
    }
}
//判断栈是否满,满返回1,不满返回0
int StackIsFull(StackShare* ps)
{
    assert(ps);
    if (ps->top_low <= ps->top_high)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

第二种实现方式(奇偶栈):

/******************************************************/
/*5.一个数组实现一个共享栈(奇偶栈)*/
//初始化共享栈(动态实现)
void ShareStackInit(ShareStack* ps)
{
    assert(ps);
    ps->_a = (DataType*)malloc(sizeof(DataType)* 3);
    ps->_top_l = 0;
    ps->_top_r = 1;
    ps->capacity = 3;
}
//销毁共享栈
void ShareStackDestroy(ShareStack* ps, char c)
{
    assert(ps);
    assert(c == 'L' || c == 'R');
    if (c == 'L')
    {
        ps->_top_l = 0;
        if (ps->_top_r == 1)
        {
            free(ps->_a);
            ps->_a = NULL;
            ps->capacity = 0;
        }
    }
    else
    {
        ps->_top_r = 1;
        if (ps->_top_l == 0)
        {
            free(ps->_a);
            ps->_a = NULL;
            ps->capacity = 0;
        }
    }
}
//入栈
void ShareStackPush(ShareStack* ps, DataType x, char c)
{
    assert(ps);
    assert(c == 'L' || c == 'R');
    if (c == 'L')
    {
        if (ps->_top_l >= ps->capacity)
        {
            DataType* tmp = realloc(ps->_a, (sizeof(DataType)*  (2 * ps->capacity)));
            if (tmp != NULL)
            {
                ps->_a = tmp;
            }
            ps->capacity *= 2;
        }
        ps->_a[ps->_top_l] = x;
        ps->_top_l += 2;
    }
    else
    {
        if (ps->_top_r >= ps->capacity)
        {
            DataType* tmp = realloc(ps->_a, 2 * (ps->capacity));
            if (tmp != NULL)
            {
                ps->_a = tmp;
            }
            ps->capacity *= 2;
        }
        ps->_a[ps->_top_r] = x;
        ps->_top_r += 2;
    }
}
//出栈
void ShareStackPop(ShareStack* ps, char c)
{
    assert(ps);
    assert(c == 'L' || c == 'R');
    if (c == 'L')
    {
        if (ps->_top_l == 0)
        {
            printf("StackEmpty\n");
            return;
        }
        ps->_top_l -= 2;
    }
    else
    {
        if (ps->_top_r == 0)
        {
            printf("StackEmpty\n");
            return;
        }
        ps->_top_r -= 2;
    }
}
取栈顶元素
DataType ShareStackTop(ShareStack* ps, char c)
{
    assert(ps);
    assert(c == 'L' || c == 'R');
    if (c == 'L')
    {
        return ps->_a[ps->_top_l - 2];
    }
    else
    {
        return ps->_a[ps->_top_r - 2];
    }
}
//为空返回0,非空返回1
int ShareStackEmpty(ShareStack* ps, char c)
{
    assert(ps);
    assert(c == 'L' || c == 'R');
    if (c == 'L')
    {
        return ps->_top_l == 0 ? 0 : 1;
    }
    else
    {
        return ps->_top_r == 1 ? 0 : 1;
    }
}
//求栈的大小
int ShareStackSize(ShareStack* ps, char c)
{
    assert(ps);
    assert(c == 'L' || c == 'R');
    if (c == 'L')
    {
        return ps->_top_l / 2;
    }
    else
    {
        return ps->_top_r / 2;//向下取整
    }
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值