目录
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); }