赞
踩
目录
如果栈和队列忘了,不妨看看小生的这两篇复习一下数据结构与算法—栈 数据结构与算法—队列
将左括号放入栈中,通过出栈与为入栈的符号进行比较。
由于我们用C语言做这道题,所以代码前要加上咱们实现的栈的代码,同时要将数据类型STDataType改为char类型。
- typedef char STDataType;
- typedef struct Stack
- {
- STDataType* a;
- int top;
- int capacity;
- }ST;
-
- void STInit(ST* pst)
- {
- assert(pst);
- pst->a = NULL;
- pst->top = 0;
- pst->capacity = 0;
- }
-
- void STDestroy(ST* pst)
- {
- assert(pst);
- free(pst->a);
- pst->a = NULL;
- pst->top = 0;
- pst->capacity = 0;
- }
-
- void STPush(ST* pst,STDataType x)
- {
- if (pst->top == pst->capacity) {
- int newCapacity = pst->capacity == 0 ? 4 :pst-> capacity * 2;
- STDataType* tmp = (STDataType*)realloc(pst->a, newCapacity * sizeof(STDataType));
- if (tmp == NULL) {
- perror("realloc fail");
- return;
- }
- pst->a = tmp;
- pst->capacity = newCapacity;
- }
- pst->a[pst->top] = x;
- pst->top++;
- }
-
- bool STEmpty(ST* pst)
- {
- assert(pst);
- return pst->top == 0;
- }
-
- void STPop(ST* pst)
- {
- assert(pst);
- assert(!STEmpty(pst));
- pst->top--;
- }
-
- STDataType STTop(ST* pst)
- {
- assert(pst);
- assert(!STEmpty(pst));
- return pst->a[pst->top - 1];
- }
-
-
- int STSize(ST* pst)
- {
- assert(pst);
- return pst->top;
- }
-
- //------以下为OJ提供-------
-
- bool isValid(char* s) {
- ST st;
- STInit(&st);
- while (*s) {
- if (*s == '(' || *s == '[' || *s == '{') {
- STPush(&st, *s);
- }
- else {
- if (STEmpty(&st)) {
- STDestroy(&st);
- return false;
- }
- char top = STTop(&st);
- STPop(&st);
- if ((top != '(' && *s == ')') ||
- (top != '{' && *s == '}') ||
- (top != '[' && *s == ']')) {
- STDestroy(&st);
- return false;
- }
- }
- s++;
- }
- bool ret = STEmpty(&st);
- STDestroy(&st);
- return ret;
- }

isValid函数:
- 创建栈结构体ST变量 st,然后进行初始化。
- 以*s为循环进行条件
首先,创建一个名为
st
的ST
结构体实例,并使用STInit
初始化它。- 然后,遍历输入字符串
s
中的每个字符。- 对于每个字符,如果是左括号 '(','[','{' ,则将其推入栈中。
- 如果是右括号 ')',']','}' ,则执行以下操作:
检查栈是否为空,如果为空,表示没有对应的左括号,则销毁栈,返回
false
。否则,弹出栈顶元素,将其与当前右括号进行匹配。如果不匹配,则销毁栈,返回
false
。
- 最后,遍历完整个字符串后,检查栈是否为空。如果栈为空,表示所有括号都成功匹配,返回
true
,否则返回false
。- 最后,调用
STDestroy
销毁栈,并返回最终的匹配结果。
准备两个队列,第一个队列依次出队到只剩一个数据时停止,将已出队的数据依次入队到第二个队列,将第一个队列仅剩的一个数据出队即实现了栈的出栈。入栈时哪个队列不为空则在哪个队列入队。
由于我们用C语言做这道题,所以代码前要加上咱们实现的队列的代码。
- typedef int QDataType;
- typedef struct QueueNode
- {
- struct QueueNode* next;
- QDataType data;
- }QNode;
-
- typedef struct Queue
- {
- QNode* phead;
- QNode* ptail;
- int size;
- }Queue;
-
- void QueueInit(Queue* pq)
- {
- assert(pq);
- pq->phead = NULL;
- pq->ptail = NULL;
- pq->size = 0;
- }
- void QueueDestroy(Queue* pq)
- {
- assert(pq);
- QNode* cur = pq->phead;
- while (cur) {
- QNode* next = cur->next;
- free(cur);
- cur = next;
- }
- pq->phead = pq->ptail = NULL;
- pq->size = 0;
- }
- void QueuePush(Queue* pq, QDataType x)
- {
- assert(pq);
- QNode* newnode = (QNode*)malloc(sizeof(QNode));
- if (newnode == NULL) {
- perror("mallloc fail\n");
- return;
- }
- newnode->data = x;
- newnode->next = NULL;
- if (pq->ptail == NULL) {
- assert(pq->phead == NULL);
- pq->phead = pq->ptail = newnode;
- }
- else {
- pq->ptail->next = newnode;
- pq->ptail = newnode;
- }
- pq->size++;
- }
- bool QueueEmpty(Queue* pq)
- {
- assert(pq);
- return pq->size == 0;
- }
- void QueuePop(Queue* pq)
- {
- assert(pq);
- assert(!QueueEmpty(pq));
- if (pq->phead->next == NULL) {
- free(pq->phead);
- pq->phead = pq->ptail = NULL;
- }
- else {
- QNode* next = pq->phead->next;
- free(pq->phead);
- pq->phead = next;
- }
- pq->size--;
- }
- QDataType QueueFront(Queue* pq)
- {
- assert(pq);
- assert(!QueueEmpty(pq));
- return pq->phead->data;
- }
- QDataType QueueBack(Queue* pq)
- {
- assert(pq);
- assert(!QueueEmpty(pq));
- return pq->ptail->data;
- }
- int QueueSize(Queue* pq)
- {
- assert(pq);
- return pq->size;
- }
-
- //------以下为OJ提供-------
-
- typedef struct {
- Queue q1;
- Queue q2;
- } MyStack;
-
- MyStack* myStackCreate() {
- MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
- if (obj == NULL) {
- perror("malloc fail");
- return NULL;
- }
- 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* pEmptyQ = &obj->q1;
- Queue* pNonEmptyQ = &obj->q2;
- if (!QueueEmpty(&obj->q1)) {
- pEmptyQ = &obj->q2;
- pNonEmptyQ = &obj->q1;
- }
- while (QueueSize(pNonEmptyQ) > 1) {
- QueuePush(pEmptyQ, QueueFront(pNonEmptyQ));
- QueuePop(pNonEmptyQ);
- }
- int top = QueueFront(pNonEmptyQ);
- QueuePop(pNonEmptyQ);
- 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);
- }

1、
typedef struct { Queue q1; Queue q2; } MyStack;首先在匿名结构体MyStack中设置两个成员 q1、q2,他们的类型为结构体Queue。
2、
MyStack* myStackCreate() { MyStack* obj = (MyStack*)malloc(sizeof(MyStack)); if (obj == NULL) { perror("malloc fail"); return NULL; } QueueInit(&obj->q1); QueueInit(&obj->q2); return obj; }myStackCreate中首先创建结构体 MyStack 指针 obj,并为其开辟空间,开辟失败则打印错误信息,然后对 obj 的两个成员 (队列) 进行初始化。
3、
void myStackPush(MyStack* obj, int x) { if (!QueueEmpty(&obj->q1)) { QueuePush(&obj->q1, x); } else { QueuePush(&obj->q2, x); } }myStackPush中首先判断哪个队列不为空,对不为空的队列进行入队(入栈)。
4、
int myStackPop(MyStack* obj) { Queue* pEmptyQ = &obj->q1; Queue* pNonEmptyQ = &obj->q2; if (!QueueEmpty(&obj->q1)) { pEmptyQ = &obj->q2; pNonEmptyQ = &obj->q1; } while (QueueSize(pNonEmptyQ) > 1) { QueuePush(pEmptyQ, QueueFront(pNonEmptyQ)); QueuePop(pNonEmptyQ); } int top = QueueFront(pNonEmptyQ); QueuePop(pNonEmptyQ); return top; }
- myStackPop中首先要找到为“空”和“不为空”的队列,假设队列q1为空,q2不为空,通过QueueEmpty判断如果q1为空则假设不变,否则二者互换。
- 然后将不为空的队列的数据依次入队到为空的队列,入队结束后将不为空的队列进行出队,进行下一次循环,直到不为空的队列只剩一个元素停止循环。
- 调用QueueFront函数获取队头节点赋值给变量top,将不为空队列仅剩的数据出队。
- 返回top。
5、
int myStackTop(MyStack* obj) { if (!QueueEmpty(&obj->q1)) { return QueueBack(&obj->q1); } else { return QueueBack(&obj->q2); } }myStackTop函数找出不为空的队列,对不为空的队列调用QueueBack返回栈顶元素。
6、
bool myStackEmpty(MyStack* obj) { return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2); }myStackEmpty调用QueueEmpty判断两个队列是否为空即为判断栈是否为空。
7、
void myStackFree(MyStack* obj) { QueueDestroy(&obj->q1); QueueDestroy(&obj->q2); free(obj); }myStackFree调用 QueueDestroy释放两个队列的内存空间,最后释放栈 obj 的内存空间。
一个栈用于入队,一个栈用于出队。出队栈不为空则从入队栈依次出栈,然后入栈到出队栈,这时原本入队栈的数据在出队栈中直接出栈,即可实现队列的先进先出,再次入队时数据进入入队栈,等待出队栈为空时再将数据倒过来。
由于我们用C语言做这道题,所以代码前要加上咱们实现的栈的代码。
- typedef int STDataType;
- typedef struct Stack
- {
- STDataType* a;
- int top;
- int capacity;
- }ST;
-
- void STInit(ST* pst)
- {
- assert(pst);
- pst->a = NULL;
- pst->top = 0;
- pst->capacity = 0;
- }
-
- void STDestroy(ST* pst)
- {
- assert(pst);
- free(pst->a);
- pst->a = NULL;
- pst->top = 0;
- pst->capacity = 0;
- }
-
- void STPush(ST* pst, STDataType x)
- {
- if (pst->top == pst->capacity) {
- int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
- STDataType* tmp = (STDataType*)realloc(pst->a, newCapacity * sizeof(STDataType));
- if (tmp == NULL) {
- perror("realloc fail");
- return;
- }
- pst->a = tmp;
- pst->capacity = newCapacity;
- }
- pst->a[pst->top] = x;
- pst->top++;
- }
-
- bool STEmpty(ST* pst)
- {
- assert(pst);
- return pst->top == 0;
- }
-
- void STPop(ST* pst)
- {
- assert(pst);
- assert(!STEmpty(pst));
- pst->top--;
- }
-
- STDataType STTop(ST* pst)
- {
- assert(pst);
- assert(!STEmpty(pst));
- return pst->a[pst->top - 1];
- }
-
- int STSize(ST* pst)
- {
- assert(pst);
- return pst->top;
- }
-
- //------以下为OJ提供-------
-
- typedef struct {
- ST pushst;
- ST popst;
- } MyQueue;
-
- MyQueue* myQueueCreate() {
- MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
- if (obj == NULL) {
- perror("malloc fail");
- return 0;
- }
- STInit(&obj->pushst);
- STInit(&obj->popst);
- return obj;
- }
-
- void myQueuePush(MyQueue* obj, int x) {
- STPush(&obj->pushst, x);
- }
-
- int myQueuePop(MyQueue* obj) {
- int front = myQueuePeek(obj);
- STPop(&obj->popst);
- return front;
- }
-
- int myQueuePeek(MyQueue* obj) {
- if (STEmpty(&obj->popst)) {
- while (!STEmpty(&obj->pushst)) {
- STPush(&obj->popst, STTop(&obj->pushst));
- STPop(&obj->pushst);
- }
- }
- return STTop(&obj->popst);
- }
-
- bool myQueueEmpty(MyQueue* obj) {
- return STEmpty(&obj->pushst) && STEmpty(&obj->popst);
- }
-
- void myQueueFree(MyQueue* obj) {
- STDestroy(&obj->pushst);
- STDestroy(&obj->popst);
- free(obj);
- }

1、
typedef struct { ST pushst; ST popst; } MyQueue;在MyQueue结构体中创建两个栈 pushst 和 popst。
2、
MyQueue* myQueueCreate() { MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue)); if (obj == NULL) { perror("malloc fail"); return 0; } STInit(&obj->pushst); STInit(&obj->popst); return obj; }创建一个 MyQueue 类型的队列 obj 。然后通过 malloc 申请内存,如果申请失败则调用perror打印错误信息,结束函数,然后分别初始化 pushst 和 popst 两个栈,返回队列obj。
3、
void myQueuePush(MyQueue* obj, int x) { STPush(&obj->pushst, x); }将元素 x 入队。直接调用 STPush 函数将元素 x 压入 pushst 栈。
4、
int myQueuePop(MyQueue* obj) { int front = myQueuePeek(obj); STPop(&obj->popst); return front; }这个函数用于将队首元素出队,并返回其值。首先调用
myQueuePeek
函数获取队首元素的值,然后调用STPop
函数将元素从popst
栈中弹出。
5、
int myQueuePeek(MyQueue* obj) { if (STEmpty(&obj->popst)) { while (!STEmpty(&obj->pushst)) { STPush(&obj->popst, STTop(&obj->pushst)); STPop(&obj->pushst); } } return STTop(&obj->popst); }这个函数用于获取队首元素的值。首先判断 popst 栈是否为空,如果为空则将 pushst 栈中的所有元素依次弹出并压入 popst 栈,最后通过 STTop 函数获取 popst 栈顶元素的值。
6、
bool myQueueEmpty(MyQueue* obj) { return STEmpty(&obj->pushst) && STEmpty(&obj->popst); }这个函数用于判断队列是否为空。只有当
pushst
和popst
两个栈都为空时,队列才为空。
7、
void myQueueFree(MyQueue* obj) { STDestroy(&obj->pushst); STDestroy(&obj->popst); free(obj); }这个函数用于释放 MyQueue 类型队列所占用的内存空间。
首先调用 STDestroy 函数销毁 pushst 和 popst 两个栈,然后调用 free 函数释放 obj 所占用的内存空间。
选择数组作为循环队列,为了避免队列为空和队列为满时
front
和rear
相同的情况,将数组的容量设置为比题中要求的队列长度大一(即实际容量为k+1)。
- typedef struct {
- int front;
- int rear;
- int k;
- int* a;
- } MyCircularQueue;
-
- MyCircularQueue* myCircularQueueCreate(int k) {
- MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
- obj->a = (int*)malloc((k + 1) * sizeof(int));
- obj->k = k;
- obj->front = obj->rear = 0;
- return obj;
- }
-
- bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
- return obj->front == obj->rear;
- }
-
- bool myCircularQueueIsFull(MyCircularQueue* obj) {
- return (obj->rear + 1) % (obj->k + 1) == obj->front;
- }
-
- bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
- if (myCircularQueueIsFull(obj)) {
- return false;
- }
- obj->a[obj->rear] = value;
- obj->rear++;
- obj->rear %= (obj->k + 1);
- return true;
- }
-
- bool myCircularQueueDeQueue(MyCircularQueue* obj) {
- if (myCircularQueueIsEmpty(obj)) {
- return false;
- }
- obj->front++;
- obj->front %= (obj->k + 1);
- return true;
- }
-
- int myCircularQueueFront(MyCircularQueue* obj) {
- if (myCircularQueueIsEmpty(obj)) {
- return -1;
- }
- return obj->a[obj->front];
- }
-
- int myCircularQueueRear(MyCircularQueue* obj) {
- if (myCircularQueueIsEmpty(obj)) {
- return -1;
- }
- return obj->a[(obj->rear + obj->k) % (obj->k + 1)];
- }
-
- void myCircularQueueFree(MyCircularQueue* obj) {
- free(obj->a);
- free(obj);
- }

1、
typedef struct { int front; int rear; int k; int* a; } MyCircularQueue;定义MyCircularQueue结构体,front指向队列第一个元素,rear指向队列最后一个元素的下一个位置,k为队列容量,指针a用于动态分配数组存储队列元素。
2、
MyCircularQueue* myCircularQueueCreate(int k) { MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue)); obj->a = (int*)malloc((k + 1) * sizeof(int)); obj->k = k; obj->front = obj->rear = 0; return obj; }对队列obj开辟空间,为数组a分配k+1个整型元素大小的空间,多出来的一个空间用于区分空队列和满队列,将k的值存储在队列obj中,初始化
front
和rear
为 0。
这里将检查队列是否为空或已满的函数从后面移动到这里,方便后续函数能正常调用。
3、
bool myCircularQueueIsEmpty(MyCircularQueue* obj) { return obj->front == obj->rear; }如果front与rear重合,则队列为空。
4、
bool myCircularQueueIsFull(MyCircularQueue* obj) { return (obj->rear + 1) % (obj->k + 1) == obj->front; }通过
(obj->rear + 1) % (obj->k + 1)
计算下一个元素将要插入的位置,如果这个位置和front
相同,说明队列已满。
5、
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) { if (myCircularQueueIsFull(obj)) { return false; } obj->a[obj->rear] = value; obj->rear++; obj->rear %= (obj->k + 1); return true; }首先检查队列是否已满。
- 如果满了,返回 false;不满则将数据放入数组的rear位置,然后rear向后移动一位。
- 如果rear移动到最后一个元素的后一项位置,则通过 obj->rear %= (obj->k + 1); 更新rear的位置。
6、
bool myCircularQueueDeQueue(MyCircularQueue* obj) { if (myCircularQueueIsEmpty(obj)) { return false; } obj->front++; obj->front %= (obj->k + 1); return true; }
- 首先检查队列是否为空。如果为空,返回
false,
- 如果不空,更新
front
的值,表示已经移除了一个元素,返回 true。
7、
int myCircularQueueFront(MyCircularQueue* obj) { if (myCircularQueueIsEmpty(obj)) { return -1; } return obj->a[obj->front]; }
- 如果队列为空,返回 -1。
- 如果不空,返回
front
指向的元素。
8、
int myCircularQueueRear(MyCircularQueue* obj) { if (myCircularQueueIsEmpty(obj)) { return -1; } return obj->a[(obj->rear + obj->k) % (obj->k + 1)]; }
- 如果队列为空,返回 -1。
- 如果不空,返回
rear
指向的前一个元素。
9、
void myCircularQueueFree(MyCircularQueue* obj) { free(obj->a); free(obj); }释放队列数组
a
和队列结构体的内存空间。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。