3.栈和队列面试题
1)括号匹配问题
typedef char STDataType;
typedef struct stack
{
STDataType* a;
int top;
int capacity;
}stack;
void StackInit(stack* ps)//初始化
{
assert(ps != NULL);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
void StackDestroy(stack* ps)//销毁
{
assert(ps != NULL);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity=0;
}
void StackPush(stack* ps, STDataType x)//入栈
{
assert(ps != NULL);
if (ps->top == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType)*newcapacity);
if (tmp == NULL)
{
exit(1);
}
ps->a = tmp;
ps->capacity = newcapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
bool StackEmpty(stack* ps)//判断栈是否为空
{
assert(ps != NULL);
return ps->top==0;
}
void StackPop(stack* ps)//出栈
{
assert(ps != NULL);
assert(!StackEmpty(ps));
ps->top--;
}
STDataType StackTop(stack* ps)//取栈顶元素
{
assert(ps != NULL);
assert(!StackEmpty(ps));
return ps->a[ps->top - 1];
}
bool isValid(char * s){
stack st;
StackInit(&st);
while(*s)
{
if(*s=='('||*s=='['||*s=='{')
{
StackPush(&st,*s);
s++;
}
else
{
if(StackEmpty(&st))return false;
STDataType top=StackTop(&st);
StackPop(&st);
if(top=='{'&&*s=='}'||top=='['&&*s==']'||top=='('&&*s==')')
{
s++;
}
else return false;
}
}
bool ret=StackEmpty(&st);
StackDestroy(&st);
return ret;
}
遇到左半括号把左半括号入到栈里,遇到右半括号让左半括号出栈,看两个括号是不是一对
2)用队列实现栈
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QueueNode;
typedef struct Queue
{
QueueNode* head;
QueueNode* tail;
}Queue;
void QueueInit(Queue* q)//初始化队列
{
assert(q!=NULL);
q->head = q->tail = NULL;
}
void QueueDestroy(Queue* q)//销毁队列
{
assert(q != NULL);
QueueNode* p = q->head;
while (p != NULL)
{
QueueNode* s = p->next;
free(p);
p = s;
}
}
bool QueueEmpty(Queue* q)//检测队列是否为空
{
assert(q != NULL);
return q->head == NULL;
}
void QueuePush(Queue* q, QDataType x)//队尾入队列
{
assert(q!=NULL);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
if (newnode == NULL)exit(1);
newnode->data = x;
newnode->next = NULL;
if (q->head == NULL)
{
q->head=q->tail= newnode;
}
else
{
q->tail->next = newnode;
q->tail = q->tail->next;
}
}
void QueuePop(Queue* q)//队头出队列
{
assert(q != NULL);
assert(!QueueEmpty(q));
if (q->head->next == NULL)
{
free(q->head);
q->head = q->tail = NULL;
}
else
{
QueueNode* s = q->head;
q->head = q->head->next;
free(s);
}
}
QDataType QueueFront(Queue* q)//获取队列头部元素
{
assert(q != NULL);
assert(!QueueEmpty(q));
return q->head->data;
}
QDataType QueueBack(Queue* q)//获取队列队尾元素
{
assert(q != NULL);
assert(!QueueEmpty(q));
return q->tail->data;
}
int QueueSize(Queue* q)//获取队列中有效元素个数
{
assert(q != NULL);
int i = 0;
QueueNode* s = q->head;
while (s != NULL)
{
i++;
s = s->next;
}
return i;
}
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack*obj=(MyStack*)malloc(sizeof(MyStack));
QueueInit(&obj->q1);
QueueInit(&obj->q2);
return obj;
}
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1,x);
}
else
{
QueuePush(&obj->q2,x);
}
}
int myStackPop(MyStack* obj) {
Queue*empty=&obj->q1;
Queue*unempty=&obj->q2;
if(!QueueEmpty(empty))
{
empty=&obj->q2;
unempty=&obj->q1;
}
while(QueueSize(unempty)>1)
{
QueuePush(empty,QueueFront(unempty));
QueuePop(unempty);
}
int top=QueueFront(unempty);
QueuePop(unempty);
return top;
}
int myStackTop(MyStack* obj) {
if(!QueueEmpty(&obj->q1))
{
return QueueBack(&obj->q1);
}
else
{
return QueueBack(&obj->q2);
}
}
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj) {
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}
把元素都入到一个队列里(1234),然后往另外一个空队列里导(123),当导到只剩一个元素的时候,剩的那一个(4)出队列,这样后入的先出了和栈的顺序相同,每出栈一次,两个队列就要导一次,第一次入栈入到哪个栈都可以因为都是空的,后面如果再入,入到非空的栈里。
因为一个队的元素出队之后入到另外一个队,元素的顺序根本没有变化,而要实现的是栈,出队的元素顺序是出栈的逆序,所以只能靠来回倒来得到逆序的元素
3)用栈实现队列
typedef int STDataType;
typedef struct stack
{
STDataType* a;
int top;
int capacity;
}stack;
void StackInit(stack* ps)//初始化
{
assert(ps != NULL);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
void StackDestroy(stack* ps)//销毁
{
assert(ps != NULL);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity=0;
}
void StackPush(stack* ps, STDataType x)//入栈
{
assert(ps != NULL);
if (ps->top == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType)*newcapacity);
if (tmp == NULL)
{
exit(1);
}
ps->a = tmp;
ps->capacity = newcapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
bool StackEmpty(stack* ps)//判断栈是否为空
{
assert(ps != NULL);
return ps->top==0;
}
void StackPop(stack* ps)//出栈
{
assert(ps != NULL);
assert(!StackEmpty(ps));
ps->top--;
}
STDataType Stacktop(stack* ps)//取栈顶元素
{
assert(ps != NULL);
assert(!StackEmpty(ps));
return ps->a[ps->top - 1];
}
int StackSize(stack* ps)//元素个数
{
assert(ps != NULL);
return ps->top;
}
typedef struct {
stack pushst;
stack popst;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue*obj=(MyQueue*)malloc(sizeof(MyQueue));
StackInit(&obj->pushst);
StackInit(&obj->popst);
return obj;
}
void myQueuePush(MyQueue* obj, int x) {
StackPush(&obj->pushst,x);
}
int myQueuePop(MyQueue* obj) {
if(StackEmpty(&obj->popst))
{
while(!StackEmpty(&obj->pushst))
{
StackPush(&obj->popst,Stacktop(&obj->pushst));
StackPop(&obj->pushst);
}
}
int front=Stacktop(&obj->popst);
StackPop(&obj->popst);
return front;
}
int myQueuePeek(MyQueue* obj) {
if(StackEmpty(&obj->popst))
{
while(!StackEmpty(&obj->pushst))
{
StackPush(&obj->popst,Stacktop(&obj->pushst));
StackPop(&obj->pushst);
}
}
return Stacktop(&obj->popst);
}
bool myQueueEmpty(MyQueue* obj) {
return StackEmpty(&obj->popst)&&StackEmpty(&obj->pushst);
}
void myQueueFree(MyQueue* obj) {
StackDestroy(&obj->popst);
StackDestroy(&obj->pushst);
free(obj);
}
两个栈,元素(1234)入到第一个栈里,再出栈(4321),入到第二个栈里(4321),此时元素的顺序整个调过来了,再从第二个栈里出栈(1234)就和正常出队的顺序(1234)是一样的了,再出队就不用再来回导数据了
因为一个栈的元素出栈之后入到另外一个栈,元素的顺序变成了逆序,而要实现的是队,逆序的元素出栈顺序恰好是队的出队顺序,所以不用再来回倒
要等负责出队的栈的元素全出栈后,在把负责入队的栈里的元素倒过来
4)设计循环队列
typedef struct {
int*a;
int k;
int head;
int tail;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->a=malloc(sizeof(int)*(k+1));
obj->head=0;
obj->tail=0;
obj->k=k;
return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->head==obj->tail;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
int next=obj->tail+1;
if(next==obj->k+1)next=0;
return next==obj->head;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(myCircularQueueIsFull(obj))return false;
obj->a[obj->tail]=value;
obj->tail++;
if(obj->tail==obj->k+1)
obj->tail=0;
//obj->tail%=(k+1);
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))return false;
obj->head++;
if(obj->head==obj->k+1)
obj->head=0;
return true;
}
int myCircularQueueFront(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))return -1;
return obj->a[obj->head];
}
int myCircularQueueRear(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))return -1;
int prev=obj->tail-1;
//int prev=obj->tail-1+k+1
//prev%=(k+1);
if(obj->tail==0)prev=obj->k;
return obj->a[prev];
}
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
free(obj);
}
4.概念选择题
第一题
一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出栈的顺序是(B)
A 12345ABCDE
B EDCBA54321
C ABCDE12345
D 54321EDCBA
第二题
若进栈序列为 1,2,3,4进栈过程中可以出栈,则下列不可能的一个出栈序列是(C)
A 1,4,3,2
B 2,3,4,1
C 3,1,4,2
D 3,4,2,1
第三题
循环队列的存储空间为 Q(1:100) ,初始状态为 front=rear=100 。经过一系列正常的入队与退队操作后front=rear=99则循环队列中的元素个数为(D)
A 1
B 2
C 99
D 0或者100
第四题
以下(B)不是队列的基本运算?
A 从队尾插入一个新元素
B 从队列中删除第i个元素
C 判断一个队列是否为空
D 读取队头元素的值
第五题
现有一循环队列,其队头指针为front,队尾指针为rear;循环队列长度为N,实际最多存N-1个数据其队内有效长度为?(B)
A (rear - front + N) % N + 1
B (rear - front + N) % N
C (rear - front) % (N + 1)
D (rear - front + N) % (N - 1)