栈和队列 面试题 概念选择题 数据结构 C语言实现

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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值