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