《数据结构学习笔记---第七篇》---栈和队列的OJ练习

目录

1. 括号匹配问题。OJ链接

2. 用队列实现栈。OJ链接

3. 用栈实现队列。OJ链接


1. 括号匹配问题。OJ链接

step1:思路分析 

1.括号匹配,我们首先考虑用栈实现,我们通过符号栈帧的思想知道,求前中后缀表达式的时候用的就是栈帧,操作数栈和符号栈。

2.根据常见的情况 考虑怎么使用栈,首先我们以示例2为例——(){} []”,如果我们用栈我们可以先考虑把“{[ ” 压入栈中  遇到“} 或  ”就停下来 进行匹配,例如本例就是我们将栈中的和字符串中的进行匹配,后续相同,即可说明是匹配的。如果是(({{[[]]}} ) )这样看起来就很复杂,但是其实我们先把(({{[[压入栈中,又将]]}} ) )与pop出的栈顶元素匹配,此时也是匹配的,所以满足。但如果是{(}){]{这种情况 ,很明显我们现将{( 压入栈中,然后发现栈顶与字符串第一个是} 不匹配,即可说明不满足。

step2. 实现代码:


typedef char STDataType;
typedef struct Stack {
	STDataType*a ;
	int capacity;
	int top;
}ST;

void StackInit(ST*ps);

void StackDestroy(ST* ps);
void StackPush(ST* ps, STDataType x);
void StackPop(ST* ps);

STDataType StackTop(ST* ps);
//返回栈顶元素
bool StackEmpty(ST* ps);
//判空
int  StackSize(ST* ps);

bool StackEmpty(ST* ps)
{
	assert(ps);

	/*if (ps->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/
	return(ps->top == 0);
}

void StackInit(ST* ps)
{
	assert(ps);
	//创建一个节点空间类似顺序表;
	ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		exit(-1);
		
	}
	ps->top = 0;
	ps->capacity = 4;
}
void StackDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}
void StackPush(ST* ps, STDataType x)

{
	assert(ps);
	if (ps->top == ps->capacity)//判断是否栈满  需要扩容
	{
		STDataType* tmp = (STDataType*)realloc(ps->a,sizeof(STDataType) * ps->capacity*2);
		if (tmp == NULL)
		{
			perror("melloc fail");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity *= 2;

	}
	ps->a[ps->top] = x;
	ps->top++;
}
void StackPop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->top--;
}

STDataType StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->a[ps->top - 1];
}

int  StackSize(ST* ps)
{
	assert(ps);

	return ps->top;
}


bool isValid(char* s) {
    ST st;
    StackInit(&st);
    while(*s)
    {
        if(*s=='['||*s=='{'||*s=='(')
        {
            StackPush(&st,*s);
            s++;//字符串后移一个单位
        }
        else
        {
            if(StackEmpty(&st))
            {
                StackDestroy(&st);//防止内存泄漏
                return false;
            }
           //前面已经返回了所以这里并不需要else
                char top = StackTop(&st);
                StackPop(&st);//出栈操作  不能忘取值不代表出栈;
                if((*s==']'&&top !='[')||(*s=='}'&&top !='{')||(*s==')'&&top !='('))
                {
                    StackDestroy(&st);//防止内存泄漏
                    return false ;
                }

                else
                {
                    ++s;
                }
        }
    }
    bool ret =StackEmpty(&st);
    StackDestroy(&st);//防止内存泄漏
    return ret;
}

2. 用队列实现栈。OJ链接

 step1:思路分析 

1.考虑到栈的特型,无非就是后进先出,那么队列是先进先出,我们想要实现压栈操作,其实和入队是一样的,那么我们将Queue1压入,例如压入123456.那么我们想要实现出栈操作就必须要pop出6,我们此时还有第二个队列,我们可以将12345出队,送入Queue2,再将Queue1当做栈顶元素pop出就可以了。但此时我们也要注意如果在进行压栈操作就必须是银压入Queue2了。

step2. 实现代码:


typedef int QDataType;
typedef struct QueueNode {//创建队列结点
	QDataType data;
	struct QueueNode* next;//别学了单链表 就不会类比其他特殊链表结点的创建
	
}QNode;
typedef struct Queue {//创建队列 指针结构体
	QNode* head;
	QNode* tail;
	int size;
}Queue;

void QueueInit(Queue* ps);
void QueueDestroy(Queue* ps);
void QueuePush(Queue* ps, QDataType x);
void QueuePop(Queue* ps);
void QueuePrint(Queue* ps);
//返回队头队尾元素
QDataType Queuefront(Queue* ps);
QDataType Queueback(Queue* ps);

bool QueueEmpty(Queue* ps);
int QueueSize(Queue* ps);


void QueueInit(Queue* ps)
{
	assert(ps);
	ps->head = NULL;
	ps->tail = NULL;
	ps->size = 0;
}
void QueueDestroy(Queue* ps)
{
	assert(ps);
	QNode* cur = ps->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	ps->head = NULL;
	ps->tail = NULL;
	ps->size = 0;

}
void QueuePush(Queue* ps, QDataType x)
{
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	if (ps->tail == NULL)
	{
		ps->tail = ps->head = newnode;
	}
	else
	{
		ps->tail->next = newnode;
		ps->tail = newnode;
	}
	ps->size++;
	
}
void QueuePrint(Queue* ps)
{
	if (ps == NULL)

	{
		printf("NULL\n");
	}
	QNode* cur = ps->head;
	while (cur)
	{
		QNode* next = cur->next;
		printf("%d->", cur->data);
		cur = next;
	}
	printf("NULL\n");
}
void QueuePop(Queue* ps)
{
	assert(ps);
	assert(!QueueEmpty(ps));
	if (ps->head->next == NULL)
	{
		free(ps->head);
		ps->head = NULL;
		ps->tail = NULL;
		ps->size = 0;
	}
	else {
		
		QNode* del = ps->head;
		
		ps->head = ps->head->next;
		free(del);
		ps->size--;
	}
}
//返回队头队尾元素
QDataType Queuefront(Queue* ps)
{
	assert(ps);
	assert(!QueueEmpty(ps));
	return (ps->head->data);
	
}
QDataType Queueback(Queue* ps)
{
	assert(ps);
	assert(!QueueEmpty(ps));
	return (ps->tail->data);
}

bool QueueEmpty(Queue* ps)
{
	assert(ps);

	return ps->head == NULL && ps->tail == NULL;
}
int QueueSize(Queue* ps)
{
	assert(ps);
	
	return (ps->size);
}




typedef struct {
 Queue q1; //栈的结构体里面定义两个队列
 Queue q2;
} MyStack;


MyStack* myStackCreate() {
     MyStack*obj=(MyStack*)malloc(sizeof(MyStack));
     QueueInit(&obj->q1);
     QueueInit(&obj->q2);
     return obj;
}

bool myStackEmpty(MyStack* obj) {
    return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}


void myStackFree(MyStack* obj) {
      QueueDestroy(&obj->q1);
      QueueDestroy(&obj->q2);
      free(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*emptyQ=&obj->q1;
    Queue*nonemptyQ=&obj->q2;
    
    if(!QueueEmpty(&obj->q1))
     {
        emptyQ=&obj->q2;
        nonemptyQ=&obj->q1;
     }
     while(QueueSize(nonemptyQ)>1)
     {
         QueuePush(emptyQ,Queuefront(nonemptyQ));
         QueuePop(nonemptyQ);
     }
     int top=Queuefront(nonemptyQ);
     QueuePop(nonemptyQ);
     return top;
     
}

int myStackTop(MyStack* obj) {
    if(!QueueEmpty(&obj->q1))
     {
        return Queueback(&obj->q1);
     }
     else {
        return Queueback(&obj->q2);
     }
    
}

3. 用栈实现队列。OJ链接

 step1:思路分析 

1.考虑到队列先进先出,我们可以让元素先压入Stack1中例如123456,那么我们想要得到对头元素,我们可以将StackPop出来,65432放入栈Stack2中,取Stack1栈顶元素即可。

2.那么接下来Stack2里面有65432,我们要是在再压入789,我们如何得到队首元素呢?有一种方法就是如果我们把65432pop回栈1中,然后插入789,再pop回栈2,这样是不是有些麻烦了。

3.但是如果我们把栈1定义为入栈,把栈2定义为出栈,我们可以继续吧789压入栈1,然后栈2的元素继续pop因为此时栈2的出栈顺序刚好满足出队的顺序。

step2. 实现代码:

typedef int STDataType;
typedef struct Stack {
	STDataType*a ;
	int capacity;
	int top;
}ST;

void StackInit(ST*ps);

void StackDestroy(ST* ps);
void StackPush(ST* ps, STDataType x);
void StackPop(ST* ps);

STDataType StackTop(ST* ps);
//返回栈顶元素
bool StackEmpty(ST* ps);
//判空
int  StackSize(ST* ps);




void StackInit(ST* ps)
{
	assert(ps);
	//创建一个节点空间类似顺序表;
	ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		exit(-1);
		
	}
	ps->top = 0;
	ps->capacity = 4;
}
void StackDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}
void StackPush(ST* ps, STDataType x)

{
	assert(ps);
	if (ps->top == ps->capacity)//判断是否栈满  需要扩容
	{
		STDataType* tmp = (STDataType*)realloc(ps->a,sizeof(STDataType) * ps->capacity*2);
		if (tmp == NULL)
		{
			perror("melloc fail");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity *= 2;

	}
	ps->a[ps->top] = x;
	ps->top++;
}
void StackPop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->top--;
}

STDataType StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->a[ps->top - 1];
}
bool StackEmpty(ST* ps)
{
	assert(ps);

	/*if (ps->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/
	return(ps->top == 0);
}
int  StackSize(ST* ps)
{
	assert(ps);

	return ps->top;
}



typedef struct {
    ST Pushq;
    ST Popq;
    
} MyQueue;
bool myQueueEmpty(MyQueue* obj);

MyQueue* myQueueCreate() {
    MyQueue*ps=(MyQueue*)malloc(sizeof(MyQueue));
    StackInit(&ps->Pushq);
    StackInit(&ps->Popq);
    return ps;
    
}
bool myQueueEmpty(MyQueue* obj) {
    return StackEmpty(&obj->Popq)&&StackEmpty(&obj->Pushq);
}
int myQueuePeek(MyQueue* obj) {
     assert(obj);
     assert(!myQueueEmpty(obj));
   if(StackEmpty(&obj->Popq))
    {
        while(!StackEmpty(&obj->Pushq))
        {
             StackPush(&obj->Popq,StackTop(&obj->Pushq));
             StackPop(&obj->Pushq);
        }
        
    }
    return StackTop(&obj->Popq);
}

void myQueuePush(MyQueue* obj, int x) {
    assert(obj);
    StackPush(&obj->Pushq,x);
}

int myQueuePop(MyQueue* obj) {
    assert(obj);
    assert(!myQueueEmpty(obj));
    int peek=myQueuePeek(obj);
    StackPop(&obj->Popq);
    return peek;
}

void myQueueFree(MyQueue* obj) {
   assert(obj);
    StackDestroy(&obj->Popq);
      StackDestroy(&obj->Pushq);
      free(obj);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值