赞
踩
通过前面栈和队列的学习,现在来看这些算法题目
本题让判断括号是否有效
第一眼看可能没一点思路,但仔细分析一下;
我们学习过栈数据结构,知道栈先进后出的原则,那我们就可以使用啊;把题目的左括号存储起来,让右括号跟左括号一一比较。
思路:
遍历字符串,遇到左括号就括号入栈,遇到右括号就与栈顶数据进行对比,如果配对就继续;如果不配对,就返回false
画图分析:
现在有这样的括号字符串
遍历字符串,第一个是 { 左括号,就入栈
ps接着遍历, [ 依然是左括号,入栈
ps接着遍历, ( 还是左括号,入栈
ps接着遍历, ) 是右括号,与栈顶数据进行比较,括号匹配,出栈
ps接着遍历, ] 是右括号,与栈顶数据比较,括号匹配,出栈
ps接着遍历, } 是右括号,与栈顶数据进行比较,括号匹配,出栈
ps遍历完字符串,再判断栈是否为空?如果为空,就代表所以括号都匹配了;如果栈不为空,括号就不匹配。
此外,再遍历过程中,有依次括号不匹配就要直接返回false
力扣题代码如下:
- typedef char SType;
- typedef struct Stack {
- SType* arr;
- int size; // 栈顶
- int num; // 空间大小
- } Stack;
-
- // 初始化
- void STInit(Stack* ps) {
- assert(ps);
- ps->arr = NULL;
- ps->size = ps->num = 0;
- }
- // 判断栈是否为空
- bool STEmpty(Stack* ps) {
- assert(ps);
- return ps->size == 0;
- }
- // 入栈
- void STPush(Stack* ps, SType x) {
- assert(ps);
- // 判断空间大小是否足够
- if (ps->num <= ps->size) {
- int newnum = (ps->num == 0) ? 4 : 2 * ps->num;
- SType* tmp = (SType*)realloc(ps->arr, newnum * sizeof(Stack));
- if (tmp == NULL) {
- perror("realloc filed");
- exit(1);
- }
- ps->arr = tmp;
- ps->num = newnum;
- }
- ps->arr[ps->size++] = x;
- }
- // 出栈
- void STPop(Stack* ps) {
- assert(ps); // 不能传NULL
- assert(!STEmpty(ps)); // 栈不能为空
- ps->size--;
- }
- // 取栈顶数据
- SType STtop(Stack* ps) {
- assert(ps); // 不能传NULL
- assert(!STEmpty(ps)); // 栈不能为空
- return ps->arr[ps->size - 1];
- }
- // 获取栈中数据个数
- int STSize(Stack* ps) {
- assert(ps);
- return ps->size;
- }
- // 栈的销毁
- void STDesTroy(Stack* ps) {
- assert(ps);
- if (ps->arr)
- free(ps->arr);
- ps->arr = NULL;
- ps->size = ps->num = 0;
- }
-
- bool isValid(char* s) {
- Stack arr;
- // 初始化
- STInit(&arr);
- char* ps = s;
- while (*ps != '\0') {
- if (*ps == '(' || *ps == '[' || *ps == '{') {
- // 入栈
- STPush(&arr, *ps);
- } else {
- // 取栈顶数据
- if (STEmpty(&arr)) {
- return false;
- }
- char ch = STtop(&arr);
- if ((ch == '(' && *ps == ')') || (ch == '[' && *ps == ']') ||
- (ch == '{' && *ps == '}')) {
- STPop(&arr);
- } else {
- return false;
- }
- }
- ps++;
- }
- if (STEmpty(&arr)) // 栈为空
- {
- return true;
- }
- return false;
- }

使用队列来实现栈,我们直到,队列是先进先出,而栈是先进后出。这里我们需要用两个队列来实现栈的相关操作
思路:
保证两个队列中有一个为空,再两个队列之间来回导入导出数据。
入栈:往不为空的队列里面插入数据
出栈:找到不为空的队列,将size-1个数据导入到另一个队列,最后剩余的一个数据,就是要出栈的数据
取栈顶元素:找到不为空的队列,取队尾元素即可
假设依次插入了1,2,3三个数据,现在要出栈
将q1中数据size-1(2个)导入到q2中。
现在q1当中剩余的数据就是要出栈的数据(即栈顶)。这样就满足了栈先进先出的特点。
力扣题代码如下:
- typedef int QType;
- typedef struct QueueNode // 队列节结构
- {
- QType data;
- struct QueueNode* next;
- } QueueNode;
- typedef struct Queue // 队列结构
- {
- int size; // 队列中的数据个数
- QueueNode* phead; // 队头
- QueueNode* ptial; // 队尾
- } Queue;
-
- // 初始化
- void QueueInit(Queue* pq) {
- assert(pq);
- pq->phead = pq->ptial = NULL;
- pq->size = 0;
- }
- // 判断队列是否为空
- bool QueueEmpty(Queue* pq) {
- assert(pq);
- return pq->size == 0;
- }
- // 入队列--从队尾插入数据
- void QueuePush(Queue* pq, QType x) {
- assert(pq);
- QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
- newnode->data = x;
- newnode->next = NULL;
- if (QueueEmpty(pq)) // 队列为空
- {
- pq->phead = pq->ptial = newnode;
- } else { // 队列不为空
- pq->ptial->next = newnode;
- pq->ptial = newnode;
- }
- pq->size++;
- }
- // 出队列--从对头删除数据
- void QueuePop(Queue* pq) {
- assert(pq); // 不能传NULL
- //assert(!QueueEmpty(pq)); // 队列不能为空
- QueueNode* del = pq->phead;
- pq->phead = pq->phead->next;
- if (pq->size == 1) // 队列只有一个节点
- {
- pq->ptial = NULL;
- }
- pq->size--;
- free(del);
- del = NULL;
- }
- // 取队头数据
- QType QueueFront(Queue* pq) {
- assert(pq); // 不能传NULL
- //assert(!QueueEmpty(pq)); // 队列不能为空
- return pq->phead->data;
- }
- // 取队尾数据
- QType QueueBack(Queue* pq) {
- assert(pq); // 不能传NULL
- //assert(!QueueEmpty(pq)); // 队列不能为空
- return pq->ptial->data;
- }
- // 获取队列数据个数
- int QueueSize(Queue* pq) {
- assert(pq); // 不能传NULL
- return pq->size;
- }
- // 销毁队列
- void QueueDesTroy(Queue* pq) {
- assert(pq); // 不能传NULL
- //assert(!QueueEmpty(pq)); // 队列不能为空
- QueueNode* pcur = pq->phead;
- while (pcur) {
- QueueNode* del = pcur;
- pcur = pcur->next;
- free(del);
- del = NULL;
- }
- pq->phead = pq->ptial = NULL;
- pq->size = 0;
- }
-
- typedef struct {
- Queue q1;
- Queue q2;
- } MyStack;
-
- MyStack* myStackCreate() {
- MyStack* Qst = (MyStack*)malloc(sizeof(MyStack));
- QueueInit(&Qst->q1);
- QueueInit(&Qst->q2);
- return Qst;
- }
-
- void myStackPush(MyStack* obj, int x) {
- // 往不为空的队列中插入数据
- if (QueueEmpty(&obj->q1)) {
- QueuePush(&obj->q2, x);
- } else {
- QueuePush(&obj->q1, x);
- }
- }
-
- int myStackPop(MyStack* obj) {
- // 先找到不为空的队列
- Queue* empq = &obj->q1;
- Queue* noneq = &obj->q2;
- if (!(QueueEmpty(&obj->q1))) // 如果q1不为空
- {
- empq = &obj->q2;
- noneq = &obj->q1;
- }
- //empq -- 空队列
- //noneq -- 非空队列
- while(QueueSize(noneq) > 1) {
- // 将noneq队列的数据导入到empq中去
- QueuePush(empq, QueueFront(noneq));
- QueuePop(noneq);
- }
- int ret = QueueFront(noneq);
- QueuePop(noneq);
- return ret;
- }
-
- int myStackTop(MyStack* obj) {
- if(QueueEmpty(&obj->q1))
- {
- return QueueBack(&obj->q2);
- }else{
- return QueueBack(&obj->q1);
- }
- }
-
- bool myStackEmpty(MyStack* obj) {
- return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
- }
-
- void myStackFree(MyStack* obj) {
- free(obj);
- obj = NULL;
- }

上一个题让我们用队列来实现栈,这个用两个栈来实现队列。
定义两个栈
思路:
往PushST中插入数据,再将数据导入到PopST中,出栈即可;
入队列:往PushST中插入数据
出队列:判断栈PopST是否为空?如果PopST栈为空,就将栈PushST中数据导入到栈PopST中去,再让栈PopST出栈操作;如果不为空,直接让栈PopST出栈操作即可。
取队头数据:和出队列操作一样,只是不需要出栈操作,只取数据
分析:
假设依次插入了1,2,3三个数据,现在出栈一次,再插入一个数据4,最后取队头数据,依次出栈。
出栈一次,PopST为空,就将PushST中数据导入到PopST中去。
依次导入
出栈;
再插入数据4
取队头数据:
最后依次出队列
现在,PopST栈为空,就要先将PushST中数据先导入到PopST中。
再出队列
力扣题代码如下:
- typedef int SType;
- typedef struct Stack
- {
- SType* arr;
- int size; //栈顶
- int num; //空间大小
- }Stack;
- //初始化
- void STInit(Stack* ps)
- {
- assert(ps);
- ps->arr = NULL;
- ps->size = ps->num = 0;
- }
- //判断栈是否为空
- bool STEmpty(Stack* ps)
- {
- assert(ps);
- return ps->size == 0;
- }
- //入栈
- void STPush(Stack* ps, SType x)
- {
- assert(ps);
- //判断空间大小是否足够
- if (ps->num <= ps->size)
- {
- int newnum = (ps->num == 0) ? 4 : ps->num * 2;
- SType* tmp = (SType*)realloc(ps->arr, newnum * sizeof(Stack));
- if (tmp == NULL)
- {
- perror("realloc filed");
- exit(1);
- }
- ps->arr = tmp;
- ps->num = newnum;
- }
- ps->arr[ps->size++] = x;
- }
- //出栈
- void STPop(Stack* ps)
- {
- assert(ps); //不能传NULL
- assert(!STEmpty(ps)); //栈不能为空
- ps->size--;
- }
- //取栈顶数据
- SType STtop(Stack* ps)
- {
- return ps->arr[ps->size - 1];
- }
- //获取栈中数据个数
- int STSize(Stack* ps)
- {
- assert(ps);
- return ps->size;
- }
- //栈的销毁
- void STDesTroy(Stack* ps)
- {
- assert(ps);
- if (ps->arr)
- free(ps->arr);
- ps->arr = NULL;
- ps->size = ps->num = 0;
- }
-
-
- typedef struct {
- Stack s1;
- Stack s2;
- } MyQueue;
-
- //初始化
- MyQueue* myQueueCreate() {
- MyQueue* Queue=(MyQueue*)malloc(sizeof(MyQueue));
- STInit(&Queue->s1);
- STInit(&Queue->s2);
- return Queue;
- }
- //插入数据
- void myQueuePush(MyQueue* obj, int x) {
- assert(obj);
- STPush(&obj->s1, x);
- }
-
- int myQueuePop(MyQueue* obj) {
- assert(obj);
- if(STEmpty(&obj->s2))
- {
- //把s1中数据导入到s2
- while(!STEmpty(&obj->s1))
- {
- STPush(&obj->s2,STtop(&obj->s1));
- STPop(&obj->s1);
- }
- }
- int ret=STtop(&obj->s2);
- STPop(&obj->s2);
- return ret;
- }
-
- int myQueuePeek(MyQueue* obj) {
- if(STEmpty(&obj->s2))
- {
- //把s1中数据导入到s2
- while(!STEmpty(&obj->s1))
- {
- STPush(&obj->s2,STtop(&obj->s1));
- STPop(&obj->s1);
- }
- }
- return STtop(&obj->s2);
- }
-
- bool myQueueEmpty(MyQueue* obj) {
- return (STEmpty(&obj->s1)) && (STEmpty(&obj->s2));
- }
-
- void myQueueFree(MyQueue* obj) {
- if(obj)
- free(obj);
- obj=NULL;
- }

设计循环队列,这里使用数组来设计
这里会设计到的一些问题:
插入数据,如何判断空间是否满了?
这里多申请一个空间,便于判断空间是否满了
删除数据,如何去删?
这里,删除front指向的数据,就是队头数据
详细代码如下:
-
- typedef struct {
- int* arr;
- int front;
- int rear;
- int num;
- } MyCircularQueue;
-
- MyCircularQueue* myCircularQueueCreate(int k) {
- MyCircularQueue* pq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
- pq->arr = malloc((k + 1) * sizeof(int));
- pq->front = pq->rear = 0;
- pq->num = k;
- return pq;
- }
-
- bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
-
- return (obj->rear == obj->front);
- }
-
- bool myCircularQueueIsFull(MyCircularQueue* obj) {
- return (obj->rear + 1) % (obj->num + 1) == obj->front;
- }
-
- bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
-
- if (myCircularQueueIsFull(obj)) // 队列满了
- {
- return false;
- }
- // 插入数据
- obj->arr[obj->rear++] = value;
- obj->rear %= (obj->num + 1);
- return true;
- }
-
- bool myCircularQueueDeQueue(MyCircularQueue* obj) {
- if (myCircularQueueIsEmpty(obj)) {
- return false;
- }
- obj->front++;
- obj->front %= (obj->num + 1);
- return true;
- }
-
- int myCircularQueueFront(MyCircularQueue* obj) {
- if (myCircularQueueIsEmpty(obj))
- return -1;
- return obj->arr[obj->front];
- }
-
- int myCircularQueueRear(MyCircularQueue* obj) {
- if (myCircularQueueIsEmpty(obj))
- return -1;
- int ret=obj->rear-1;
- if(obj->rear==0)
- {
- ret=obj->num;
- }
- return obj->arr[ret];
- }
-
- void myCircularQueueFree(MyCircularQueue* obj) {
- free(obj->arr);
- free(obj);
- obj = NULL;
- }

感谢各位大佬支持并指出问题,
如果本篇内容对你有帮助,可以一键三连支持以下,感谢支持!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。