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

栈和队列面试题(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).

思路:
这里写图片描述
参考代码:

//构建两个栈,一个栈存储元素,另一个栈存储当前最小值

typedef struct MinStack
{
    Stack s;
    Stack mins;
}MinStack;

void MinStackInit(MinStack* pms);
void MinStackDestory(MinStack* pms);

void MinStackPush(MinStack* pms, DataType x);
void MinStackPop(MinStack* pms);
int MinStackSize(MinStack* pms);
int MinStackEmpty(MinStack* pms);
DataType MinStackTop(MinStack* pms);
int MinStackMin(MinStack* pms);
void testmin();


void MinStackInit(MinStack* pms)
{
    assert(pms);
    StackInit(&pms->s);
    StackInit(&pms->mins);
}
void MinStackDestory(MinStack* pms)
{
    assert(pms);
    StackDestory(&pms->s);
    StackDestory(&pms->mins);

}

void MinStackPush(MinStack* pms, DataType x)
{
    assert(pms);
    StackPush(&pms->s, x);
    if (StackEmpty(&pms->mins) || StackTop(&pms->mins) >= x)
    {
        StackPush(&pms->mins, x);
    }

}
void MinStackPop(MinStack* pms)
{
    assert(pms);
    if (StackTop(&pms->mins) == StackTop(&pms->s))
    {
        StackPop(&pms->mins);
    }
    StackPop(&pms->s);

}
int MinStackSize(MinStack* pms)
{
    assert(pms);
    return StackSize(&pms->s);

}
int MinStackEmpty(MinStack* pms)
{
    assert(pms);
    return StackEmpty(&pms->s);
}
DataType MinStackTop(MinStack* pms)
{   
    assert(pms);
    return StackTop(&pms->s);


}
int MinStackMin(MinStack* pms)
{
    assert(pms);
    return StackTop(&pms->mins);

}

void testmin()
{
    MinStack s;
    MinStackInit(&s);

    MinStackPush(&s, 1);
    MinStackPush(&s, 2);
    MinStackPush(&s, 0);
    MinStackPush(&s, 0);
    MinStackPush(&s, 0);
    MinStackPush(&s, 8);
    MinStackPush(&s, 0);

    printf("大小:%d\n",MinStackSize(&s));
    printf("栈顶元素:%d\n",MinStackTop(&s));
    printf("最小值:%d\n",MinStackMin(&s));
    MinStackPop(&s);

    printf("大小:%d\n", MinStackSize(&s));
    printf("栈顶元素:%d\n", MinStackTop(&s));
    MinStackPop(&s);

    printf("大小:%d\n", MinStackSize(&s));
    printf("栈顶元素:%d\n", MinStackTop(&s));
    MinStackPop(&s);

    printf("大小:%d\n", MinStackSize(&s));
    printf("栈顶元素:%d\n", MinStackTop(&s));

    MinStackDestory(&s);

}
2.使用两个栈实现一个队列

思路:
这里写图片描述
参考代码:

typedef struct  QueueByTwoStack
{
    Stack s1;
    Stack s2;
}QueueByTwoStack;

void QueueByTwoStackInit(QueueByTwoStack* qts);
void QueueByTwoStackDestory(QueueByTwoStack* qts);

void QueueByTwoStackPush(QueueByTwoStack* qts, DataType x);
void QueueByTwoStackPop(QueueByTwoStack* qts);
DataType QueueByTwoStackFront(QueueByTwoStack* qts);
int QueueByTwoStackEmpty(QueueByTwoStack* qts);
int QueueByTwoStackSize(QueueByTwoStack* qts);
void testQueueByTwoStack();

void QueueByTwoStackInit(QueueByTwoStack* qts)
{
    assert(qts);
    StackInit(&qts->s1);
    StackInit(&qts->s2);
}
void QueueByTwoStackDestory(QueueByTwoStack* qts)
{
    assert(qts);
    StackDestory(&qts->s1);
    StackDestory(&qts->s2);

}

// 栈s1入数据,s2出数据,
void QueueByTwoStackPush(QueueByTwoStack* qts, DataType x)
{
    assert(qts);
    StackPush(&qts->s1, x);

}
//s2出数据,如果有数据直接出,如果没有就从s1中把数据倒过来
void QueueByTwoStackPop(QueueByTwoStack* qts)
{
    assert(qts);
    if (StackEmpty(&qts->s2))
    {
        while (!StackEmpty(&qts->s1))
        {
            StackPush(&qts->s2, StackTop(&qts->s1));
            StackPop(&qts->s1);
        }
    }
    StackPop(&qts->s2);

}
DataType QueueByTwoStackFront(QueueByTwoStack* qts)
{
    assert(qts);
    if (StackEmpty(&qts->s2))
    {
        while (!StackEmpty(&qts->s1))
        {
            StackPush(&qts->s2, StackTop(&qts->s1));
            StackPop(&qts->s1);
        }
    }
    return StackTop(&qts->s2);
}
int QueueByTwoStackEmpty(QueueByTwoStack* qts)
{
    assert(qts);
    return StackEmpty(&qts->s1)&StackEmpty(&qts->s2);
}
int QueueByTwoStackSize(QueueByTwoStack* qts)
{
    assert(qts);
    return StackSize(&qts->s1) + StackSize(&qts->s2);
}

void testQueueByTwoStack()
{
    QueueByTwoStack stq;
    QueueByTwoStackInit(&stq);
    QueueByTwoStackPush(&stq, 1);
    QueueByTwoStackPush(&stq, 2);
    QueueByTwoStackPush(&stq, 3);
    QueueByTwoStackPush(&stq, 4);
    QueueByTwoStackPop(&stq);

    QueueByTwoStackPush(&stq, 5);
    QueueByTwoStackPush(&stq, 6);
    QueueByTwoStackPush(&stq, 7);
    QueueByTwoStackPush(&stq, 8);

    printf("%d", QueueByTwoStackSize(&stq));

    while (!QueueByTwoStackEmpty(&stq))
    {
        printf("%d ", QueueByTwoStackFront(&stq));
        QueueByTwoStackPop(&stq);
    }
    QueueByTwoStackDestory(&stq);
}
3.使用两个队列实现一个栈

思路:
这里写图片描述
参考代码:

typedef struct  StackByTwoQueue
{
    Queue q1;
    Queue q2;
}StackByTwoQueue;

void StackByTwoQueueInit(StackByTwoQueue* stq);
void StackByTwoQueueDestory(StackByTwoQueue* stq);
void StackByTwoQueuePush(StackByTwoQueue* stq, DataType x);
void StackByTwoQueuePop(StackByTwoQueue* stq);
DataType StackByTwoQueueFront(StackByTwoQueue* stq);
int StackByTwoQueueEmpty(StackByTwoQueue* stq);
int StackByTwoQueueSize(StackByTwoQueue* stq);

void testStackByTwoQueue();


void StackByTwoQueueInit(StackByTwoQueue* stq)
{
    assert(stq);
    QueueInit(&stq->q1);
    QueueInit(&stq->q2);
}
void StackByTwoQueueDestory(StackByTwoQueue* stq)
{
    assert(stq);
    QueueDestory(&stq->q1);
    QueueDestory(&stq->q2);

}
//两个队列实现栈,开始入队时,q1空入q2,q2空入q1,非空队上插入数据,另一个队当出栈时的缓存区
void StackByTwoQueuePush(StackByTwoQueue* stq, DataType x)
{
    assert(stq);
    if (QueueEmpty(&stq->q1))
    {
        QueuePush(&stq->q2, x);
    }
    else
    {
        QueuePush(&stq->q1, x);
    }

}
//出栈时,将非空队列前n-1数据导入空队,将原非空队列第n个数据出队
void StackByTwoQueuePop(StackByTwoQueue* stq)
{
    assert(stq);
    Queue *empty = &stq->q1, *noempty = &stq->q2;
    if (!QueueEmpty(&stq->q1))
    {
        empty = &stq->q2;
        noempty = &stq->q1;
    }
    while (QueueSize(noempty) > 1)
    {
        QueuePush(empty, QueueFront(noempty));
        QueuePop(noempty);
    }
    QueuePop(noempty);

}
DataType StackByTwoQueueFront(StackByTwoQueue* stq)
{
    assert(stq);
    if (QueueEmpty(&stq->q1))
    {
        return QueueBack(&stq->q2);
    }
    else
        return QueueBack(&stq->q1);
}
int StackByTwoQueueEmpty(StackByTwoQueue* stq)
{
    assert(stq);
    return QueueEmpty(&stq->q1)&QueueEmpty(&stq->q2);
}
int StackByTwoQueueSize(StackByTwoQueue* stq)
{
    assert(stq);
    return QueueSize(&stq->q1) + QueueSize(&stq->q2);
}

void testStackByTwoQueue()
{
    StackByTwoQueue stq;
    StackByTwoQueueInit(&stq);
    StackByTwoQueuePush(&stq, 1);
    StackByTwoQueuePush(&stq, 2);
    StackByTwoQueuePush(&stq, 3);
    StackByTwoQueuePush(&stq, 4);
    StackByTwoQueuePop(&stq);

    StackByTwoQueuePush(&stq, 5);
    StackByTwoQueuePush(&stq, 6);
    StackByTwoQueuePush(&stq, 7);
    StackByTwoQueuePush(&stq, 8);

    printf("%d     ", StackByTwoQueueSize(&stq));

    while (!StackByTwoQueueEmpty(&stq))
    {
        printf("%d ", StackByTwoQueueFront(&stq));
        StackByTwoQueuePop(&stq);
    }
    StackByTwoQueueDestory(&stq);
}
4.元素出栈、入栈的合法性。如入栈的序列(1,2,3,4,5),出栈序列为(4,5,3,2,1)

思路:
如入栈的序列(1,2,3,4,5),出栈序列为(4,5,3,2,1)
传入两个数组,一个是进入栈的序列另一个是出栈顺序,创建一个栈,将进入栈的序列依次压入栈中,当进入序列和出栈序列的第一个元素相同时,弹出这个元素,同时出栈序列,向后走,该元素已经成功出栈,此时若入栈序列还有元素继续重复上述操作,直到,最后一个元素也入栈,这时栈中剩下的元素位置已经固定,只能从栈顶依次弹出,每次弹出前栈顶元素和弹出序列元素比较若相等则继续弹出,同时弹出序列向后移动,一旦栈顶元素和弹出序列不相等,说明弹出序列要弹出的元素不在栈顶,所以无法弹出,所以就是非法弹出,否则继续重复上述操作,直到栈中的元素数目为0,即栈空,证明弹出序列合法
这里写图片描述
参考代码:

int Check(int *stack_in, int *stack_out, int len_in, int len_out);
void testInWithOut();



int Check(int *in, int *out, int len_in, int len_out)
{
    /*Stack s;
    StackInit(&s);
    assert(stack_in && stack_out);
    //两个序列长度不相等,不合法  
    if (len_in != len_out)
        return 0;

    int j = 0;
    int i = 0;
    for (; i < len_in; i++)
    {
        StackPush(&s, stack_in[i]);
        //入栈序列栈顶元素与当前出栈序列元素不相等,不合法  
        while (StackSize(&s) > 0 && StackTop(&s) == stack_out[j])
        {
            StackPop(&s);
            j++;
        }
    }*/

    Stack s;
    StackInit(&s);
    assert(in && out);
    //两个序列长度不相等,不合法  
    if (len_in != len_out)
        return 0;

    int index = 0;
    int outdex = 0;

    while (index < len_in)
    {
        StackPush(&s, in[index]);
        index++;
        while (!StackEmpty(&s) && (StackTop(&s) == out[outdex]))
        {
            StackPop(&s);
            outdex++;
        }

    }

    //当所有出栈序列元素都匹配完之后,栈不为空,不合法
    if (StackEmpty(&s))
    {
        StackDestory(&s);
        return 1;
    }
    else
    {
        StackDestory(&s);
        return 0;
    }
}


void testInWithOut()
{
    int stack_in[] = { 1, 2, 3, 4, 5 };       //入栈序列  
    int stack_out[] = { 4, 5, 3, 2, 1 };      //出栈序列  
    int len_in = sizeof(stack_in) / sizeof(stack_in[0]);      //入栈序列长度  
    int len_out = sizeof(stack_out) / sizeof(stack_out[0]);   //出栈序列长度  
    int ret = Check(stack_in, stack_out, len_in, len_out);
    if (ret == 1)
        printf("合法\n");
    else
        printf("不合法\n");

}
5.一个数组实现两个共享栈

思路:
这里写图片描述
参考代码:

//方案一:

#define MAXSIZE 10
//利用数组实现一个静态共享栈,第一个栈是从前往后入栈,第二栈的元素从后往前放
typedef struct SharedStack
{
    int data[MAXSIZE];
    int top1;     //左栈顶
    int top2;     //右栈顶
}SharedStack;

//flag为判断区分两个栈 ,规定1为左栈,2为右栈

void SharedStackInit(SharedStack* s);

// 入栈 
void SharedStackPush(SharedStack* s, int data, int flag);
// 出栈 
void SharedStackPop(SharedStack* s, int flag);
// 获取栈顶元素 
int SharedStackTop(SharedStack* s, int flag);
// 有效元素的个数 
int SharedStackSize(SharedStack* s, int flag);
// 检测栈是否为空 
int SharedStackEmpty(SharedStack* s, int flag);

void SharedStackInit(SharedStack* s)
{
    s->top1 = 0;
    s->top2 = MAXSIZE - 1;
}

// 入栈 
void SharedStackPush(SharedStack* s, int data, int flag)
{
    if (s->top2 <= s->top1)
        return;

    if (1 == flag)
        s->data[s->top1++] = data;
    else
        s->data[s->top2--] = data;
}

// 出栈 
void SharedStackPop(SharedStack* s, int flag)
{
    if (SharedStackEmpty(s, flag))
        return;

    if (1 == flag)
        s->top1--;
    else
        s->top2++;
}

// 获取栈顶元素 
int SharedStackTop(SharedStack* s, int flag)
{
    assert(!SharedStackEmpty(s, flag));
    if (1 == flag)
        return s->data[s->top1 - 1];
    else
        return s->data[s->top2 + 1];
}

// 有效元素的个数 
int SharedStackSize(SharedStack* s, int flag)
{
    if (1 == flag)
        return s->top1;
    else
        return MAXSIZE - s->top2 - 1;
}

// 检测栈是否为空 
int SharedStackEmpty(SharedStack* s, int flag)
{
    if (1 == flag)
        return 0 == s->top1;
    else
        return MAXSIZE - 1 == s->top2;
}

//方案二;
typedef int SDataType;
typedef struct SShareStack
{
    SDataType* data;
    int top1;
    int top2;
    int capacity;

}SShareStack;

void  SShareStackInit(SShareStack* pss);
void  SShareStackDestory(SShareStack* pss,int flag);

void  SShareStackPush(SShareStack* pss,SDataType x,int flag);
void  SShareStackPop(SShareStack* pss, int flag);
int  SShareStackSize(SShareStack* pss, int flag);
SDataType  SShareStackTop(SShareStack* pss, int flag);
int  SShareStackEmpty(SShareStack* pss, int flag);
void testShareStack();

void  SShareStackInit(SShareStack* pss)
{
    assert(pss);
    pss->data = (SDataType*)malloc(sizeof(SDataType)* 4);
    pss->capacity = 4;
    pss->top1 = 0;
    pss->top2 = 1;
}
void  SShareStackDestory(SShareStack* pss,int flag)
{
    assert(pss);
    if (flag == 1)
    {
        pss->top1 = 0;
        if (pss->top2 == 1)
        {
            free(pss->data);
            pss->data = NULL;
        }

    }
    else
    {
        pss->top2 = 1;
        if (pss->top1 == 0)
        {
            free(pss->data);
            pss->data = NULL;
        }
    }                                                      

}

SDataType* AddCapacity(SShareStack* pss)
{
    assert(pss);
    SDataType* tmp = (SDataType*)realloc(pss->data, sizeof(SDataType)*(pss->capacity + 4));
    assert(tmp);
    pss->data = tmp;
    pss->capacity += 4;
    printf("增容成功\n");

    return pss->data;

}
void  SShareStackPush(SShareStack* pss, SDataType x, int flag)
{
    assert(pss&&((flag ==1)||(flag ==2)));

    if (flag == 1)
    {
        if (pss->top1 == pss->capacity - 2)
        {
            pss->data=AddCapacity(pss);
            //AddCapacity(pss);
        }
        pss->data[pss->top1] = x;
        pss->top1 += 2;
    }
    else
    {
        if (pss->top2 == pss->capacity - 1)
        {
            pss->data=AddCapacity(pss);
            //AddCapacity(pss);
        }
        pss->data[pss->top2] = x;
        pss->top2 += 2;
    }

}
void  SShareStackPop(SShareStack* pss, int flag)
{
    assert(pss && ((flag == 1) || (flag == 2)));

    if (flag == 1)
    {
        if (pss->top1 == 0)
            return;
        else
            pss->top1 -= 2;

    }
    else
    {
        if (pss->top2 == 1)
            return;
        else
            pss->top2 -= 2;

    }
}
int  SShareStackSize(SShareStack* pss, int flag)
{
    assert(pss && ((flag == 1) || (flag == 2)));
    if (flag == 1)
        return pss->top1/2;
    else
        return pss->top2/2;

}
SDataType  SShareStackTop(SShareStack* pss, int flag)
{
    assert(pss && ((flag == 1) || (flag == 2)));
    if (flag == 1)
        return pss->data[pss->top1-2];
    else
        return pss->data[pss->top2-2];


}
int  SShareStackEmpty(SShareStack* pss, int flag)
{
        assert(pss&&((flag ==1)||(flag ==2)));
        if (flag == 1)
            return pss->top1 == 0;
        else
            return pss->top2 == 1;

}
void testShareStack()
{
    SShareStack s;
    SShareStackInit(&s);

    SShareStackPush(&s, 3, 1);
    SShareStackPush(&s, 4, 2);
    SShareStackPush(&s, 5, 1);
    SShareStackPush(&s, 1, 2);
    SShareStackPush(&s, 5, 1);
    SShareStackPush(&s, 1, 2);

    printf("大小:%d %d\n", SShareStackSize(&s, 1), SShareStackSize(&s, 2));
    printf("栈顶:%d %d\n", SShareStackTop(&s, 1), SShareStackTop(&s, 2));
    printf("判空:%d %d\n", SShareStackEmpty(&s, 1), SShareStackEmpty(&s, 2));

    SShareStackPop(&s, 1);
    SShareStackPop(&s, 2);

    printf("大小:%d %d\n", SShareStackSize(&s, 1), SShareStackSize(&s, 2));
    printf("栈顶:%d %d\n", SShareStackTop(&s, 1), SShareStackTop(&s, 2));
    printf("判空:%d %d\n", SShareStackEmpty(&s, 1), SShareStackEmpty(&s, 2));

    SShareStackDestory(&s,1);
    SShareStackDestory(&s, 2);
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农印象

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值