赞
踩
作者:[南航科院小张
南航科院小张的博客
专栏:从c语言的入门到进阶
学习知识不只是要懂,还要会用;想要找到好的工作,这里给大家介绍一件可以斩获诸多大厂offer的利器–牛客网
点击免费注册和我一起开始刷题之路吧!!!
题解:这里我们可以用栈的特性:先进后出;要是遇到左括号就入栈,要是右括号就和栈顶的元素进行比较,看是否匹配,要是匹配,就把栈顶出栈,要是不匹配,直接返回false;下面有几个要注意的点:
- 全部都是左括号;这个情况的话就是可以出循环,但是我们要在后面判断一下栈是否为空,要是空,那么就符合题意,返回true;否则返回false;
- 全部是右括号;这个问题当第一个右括号的时候就会返回法false,因为不匹配;
- 右括号比左括号多;这个情况的话也是最后面的判断栈是否空可以解决;
下面代码要注意的是c语言没有栈,我自己实现的一个栈,然后就是在返回true或者false之前的时候一定要销毁栈!!!
// 支持动态增长的栈 typedef char STDataType; typedef struct Stack { STDataType* a; int top; // 栈顶 int capacity; // 容量 }Stack; // 初始化栈 void StackInit(Stack* ps); // 入栈 void StackPush(Stack* ps, STDataType data); // 出栈 void StackPop(Stack* ps); // 获取栈顶元素 STDataType StackTop(Stack* ps); // 获取栈中有效元素个数 int StackSize(Stack* ps); // 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 int StackEmpty(Stack* ps); // 销毁栈 void StackDestroy(Stack* ps); void StackInit(Stack* ps) { assert(ps); ps->a = NULL; ps->capacity = ps->top = 0; } void StackPush(Stack* ps, STDataType data) { assert(ps); if (ps->top == ps->capacity) { int newcapacity = ps->capacity == 0 ? 4 : ps->capacity *2; STDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newcapacity); if (temp == NULL) { perror("realloc fail"); exit(-1); } ps->a = temp; ps->capacity = newcapacity; } ps->a[ps->top] = data; ps->top++; } void StackPop(Stack* ps) { assert(ps); assert(!StackEmpty(ps)); ps->top--; } STDataType StackTop(Stack* ps) { assert(ps); assert(!StackEmpty(ps)); return ps->a[ps->top - 1]; } int StackSize(Stack* ps) { assert(ps); return ps->top; } int StackEmpty(Stack* ps) { assert(ps); return ps->top ==0; } void StackDestroy(Stack* ps) { assert(ps); free(ps->a); ps->a = NULL; ps->capacity = ps->top = 0; } bool isValid(char * s){ Stack st; StackInit(&st); while(*s){ if(*s=='('||*s=='{'||*s=='['){ StackPush(&st,*s); } else{ if(StackEmpty(&st)){//为了防止栈为空,下面的StackPop接口还在用; StackDestroy(&st); return false; } char top=StackTop(&st); if(*s==')'&&top!='(' ||*s=='}'&&top!='{' ||*s==']'&&top!='[') { StackDestroy(&st); return false; } else{ StackPop(&st); } } ++s; } bool flag=StackEmpty(&st); StackDestroy(&st); return flag; }
思路很简单,但是用代码实现起来还是有点挑战的哈哈;
栈的特点:先进后出;队列特点:先进先出;
用两个队列实现栈,利用队列的特点,把先进的数据导到另外一个队列里面,然后剩下一个数据,然后出这个数据(pop数据),这样就实现了栈的出数据特点,栈顶出数据;我们要控制那里的队列为空就往空队列导数据,非空队列留下一个来出数据,就这样一直在两个队列里面操作,然后入数据就往非空队列里入数据;我这里是直接写的队列哈,所以比较多代码;
// 链式结构:表示队列 typedef int QDataType; typedef struct QListNode { struct QListNode* next; QDataType data; }QNode; // 队列的结构 typedef struct Queue { size_t sz; QNode* head; QNode* tail; }Queue; // 初始化队列 void QueueInit(Queue* q); // 队尾入队列 void QueuePush(Queue* q, QDataType data); // 队头出队列 void QueuePop(Queue* q); // 获取队列头部元素 QDataType QueueFront(Queue* q); // 获取队列队尾元素 QDataType QueueBack(Queue* q); // 获取队列中有效元素个数 int QueueSize(Queue* q); // 检测队列是否为空,如果为空返回非零结果,如果非空返回0 int QueueEmpty(Queue* q); // 销毁队列 void QueueDestroy(Queue* q); void QueueInit(Queue* q) { assert(q); q->head = q->tail = NULL; q->sz = 0; } void QueuePush(Queue* q, QDataType data) { assert(q); QNode* newnode = (QNode*)malloc(sizeof(QNode)); if (newnode == NULL) { perror("malloc fail"); exit(-1); } else { newnode->data = data; newnode->next = NULL; } if (q->head == NULL) { q->head = q->tail = newnode; q->sz++; } else { q->tail->next = newnode; q->tail = newnode; q->sz++; } } void QueuePop(Queue* q) { assert(q); assert(!QueueEmpty(q)); if (q->head->next == NULL) { free(q->head); q->head = q->tail = NULL; q->sz--; } else { QNode* cur = q->head->next; free(q->head); q->head = cur; q->sz--; } } QDataType QueueFront(Queue* q) { assert(q); assert(!QueueEmpty(q)); return q->head->data; } QDataType QueueBack(Queue* q) { assert(q); assert(!QueueEmpty(q)); return q->tail->data; } int QueueSize(Queue* q) { assert(q); return q->sz; } int QueueEmpty(Queue* q) { assert(q); return q->head == NULL && q->tail == NULL; } void QueueDestroy(Queue* q) { assert(q); QNode* cur = q->head; while (cur) { QNode* next = cur->next; free(cur); cur = next; } q->head = q->tail = NULL; } typedef struct { Queue q1; Queue q2; } MyStack; MyStack* myStackCreate() { MyStack* obj=(MyStack*)malloc(sizeof(MyStack)); if(obj==NULL){ perror("malloc fail"); exit(-1); } 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* EmptyQ=&obj->q1; Queue* noEmptyQ=&obj->q2; if(!QueueEmpty(&obj->q1)){ EmptyQ=&obj->q2; noEmptyQ=&obj->q1; } while(QueueSize(noEmptyQ)>1){ int top=QueueFront(noEmptyQ); QueuePop(noEmptyQ); QueuePush(EmptyQ,top); } int top=QueueFront(noEmptyQ); QueuePop(noEmptyQ); return top; } int myStackTop(MyStack* obj) { Queue* EmptyQ=&obj->q1; Queue* noEmptyQ=&obj->q2; if(!QueueEmpty(&obj->q1)){ EmptyQ=&obj->q2; noEmptyQ=&obj->q1; } while(QueueSize(noEmptyQ)>1){ int top=QueueFront(noEmptyQ); QueuePop(noEmptyQ); QueuePush(EmptyQ,top); } int top=QueueFront(noEmptyQ); QueuePop(noEmptyQ); QueuePush(EmptyQ,top); return top; } bool myStackEmpty(MyStack* obj) { return QueueEmpty(&(obj->q1)) && QueueEmpty(&(obj->q2)); } void myStackFree(MyStack* obj) { QueueDestroy(&obj->q1); QueueDestroy(&obj->q2); free(obj); } /** * Your MyStack struct will be instantiated and called as such: * MyStack* obj = myStackCreate(); * myStackPush(obj, x); * int param_2 = myStackPop(obj); * int param_3 = myStackTop(obj); * bool param_4 = myStackEmpty(obj); * myStackFree(obj); */
思路很简单,但是用代码实现起来还是有点挑战的哈哈;
栈的特点:先进后出;队列特点:先进先出;
用栈来模拟队列的特点,有了上面的题解,想必我们很容易想到方法了,这题比上一题简单哦,我们搞两个栈,一个栈专门用来入数据,一个栈专门用来出数据,因为入数据完后将全部数据到入专门的出数据的栈里面的时候,出数据的栈的数据是符合队列的出数据规则的了;所以可以对两个栈分开工作;
要注意的是:出数据的栈要判断是否为空,要是空的话就导数据,然后再出;
//Stack // 支持动态增长的栈 typedef int STDataType; typedef struct Stack { STDataType* a; int top; // 栈顶 int capacity; // 容量 }Stack; // 初始化栈 void StackInit(Stack* ps); // 入栈 void StackPush(Stack* ps, STDataType data); // 出栈 void StackPop(Stack* ps); // 获取栈顶元素 STDataType StackTop(Stack* ps); // 获取栈中有效元素个数 int StackSize(Stack* ps); // 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 int StackEmpty(Stack* ps); // 销毁栈 void StackInit(Stack* ps) { assert(ps); ps->a = NULL; ps->capacity = ps->top = 0; } void StackPush(Stack* ps, STDataType data) { assert(ps); if (ps->top == ps->capacity) { int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; STDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newcapacity); if (temp == NULL) { perror("realloc fail"); exit(-1); } ps->a = temp; ps->capacity = newcapacity; } ps->a[ps->top] = data; ps->top++; } void StackPop(Stack* ps) { assert(ps); assert(!StackEmpty(ps)); ps->top--; } STDataType StackTop(Stack* ps) { assert(ps); assert(!StackEmpty(ps)); return ps->a[ps->top - 1]; } int StackSize(Stack* ps) { assert(ps); return ps->top; } int StackEmpty(Stack* ps) { assert(ps); return ps->top == 0 ? 1 : 0; } void StackDestroy(Stack* ps) { assert(ps); free(ps->a); ps->a = NULL; ps->capacity = ps->top = 0; } typedef struct { Stack PopST; Stack PushST; } MyQueue; MyQueue* myQueueCreate() { MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue)); if(obj==NULL){ perror("malloc fail"); exit(-1); } StackInit(&obj->PopST); StackInit(&obj->PushST); return obj; } void myQueuePush(MyQueue* obj, int x) { StackPush(&obj->PushST,x); } //判断PopST队列是否为空,要是空,就导数据; void PushSTTOPopST(MyQueue* obj){ if(StackEmpty(&obj->PopST)){ while(!StackEmpty(&obj->PushST)){ int top=StackTop(&obj->PushST); StackPop(&obj->PushST); StackPush(&obj->PopST,top); } } } int myQueuePop(MyQueue* obj) { PushSTTOPopST(obj); int top=StackTop(&obj->PopST); StackPop(&obj->PopST); return top; } int myQueuePeek(MyQueue* obj) { PushSTTOPopST(obj); int top=StackTop(&obj->PopST); return top; } bool myQueueEmpty(MyQueue* obj) { return StackEmpty(&obj->PopST)&&StackEmpty(&obj->PushST); } void myQueueFree(MyQueue* obj) { StackDestroy(&obj->PopST); StackDestroy(&obj->PushST); free(obj); } /** * Your MyQueue struct will be instantiated and called as such: * MyQueue* obj = myQueueCreate(); * myQueuePush(obj, x); * int param_2 = myQueuePop(obj); * int param_3 = myQueuePeek(obj); * bool param_4 = myQueueEmpty(obj); * myQueueFree(obj); */
这道题其实难,可以用链表也可以用顺序表,不过我觉得用顺序表更简单容易实现一点;为了可以判断什么时候是满的什么时候是空的,我们有两个方法,一个是用size来计数,第二个是直接加一个节点;加了一个节点后当数据为空,就是head等于tail的时候,当(tail+1)%N等于head的时候为满数据,这个时候不能再插入数据了;我们一定要注意这是一个循环的,到边界的时候一定要有回去,这个时候我的实现是%N,返回尾元素则很巧,(tail-1+n)%n;我们要画图多观察才容易理解;要是不容易理解代码,可以画图然后看着代码来还原思路;
typedef struct { int* a; int head; int tail; int N; } MyCircularQueue; MyCircularQueue* myCircularQueueCreate(int k) { MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue)); if(obj==NULL){ perror("obj malloc fail"); exit(-1); } obj->a=(int*)malloc(sizeof(int)*(k+1));//加一个空间,便于判断空和满; if(obj->a==NULL){ perror("a malloc fail"); exit(-1); } obj->N=k+1;//作用很大,便于下标的循环恢复; obj->head=obj->tail=0; return obj; } bool myCircularQueueIsEmpty(MyCircularQueue* obj) { return obj->tail==obj->head; } bool myCircularQueueIsFull(MyCircularQueue* obj) { return (obj->tail+1)%(obj->N)==obj->head; } bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) { if(myCircularQueueIsFull(obj)) return false; obj->a[obj->tail]=value; obj->tail++; obj->tail%=obj->N;//防止在最大下标+1的情况,要循环进行恢复最小下标; return true; } bool myCircularQueueDeQueue(MyCircularQueue* obj) { if(myCircularQueueIsEmpty(obj)) return false; obj->head++; obj->head%=obj->N; 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; return obj->a[(obj->tail-1+obj->N)%(obj->N)]; } void myCircularQueueFree(MyCircularQueue* obj) { free(obj->a); obj->a=NULL; free(obj); } /** * Your MyCircularQueue struct will be instantiated and called as such: * MyCircularQueue* obj = myCircularQueueCreate(k); * bool param_1 = myCircularQueueEnQueue(obj, value); * bool param_2 = myCircularQueueDeQueue(obj); * int param_3 = myCircularQueueFront(obj); * int param_4 = myCircularQueueRear(obj); * bool param_5 = myCircularQueueIsEmpty(obj); * bool param_6 = myCircularQueueIsFull(obj); * myCircularQueueFree(obj); */
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。