一、有效括号
题目描述:给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的相同类型的左括号。输入输出例子如下:
输入"{}",返回true
输入"{)",返回false
思路:使用栈相关的结构来进行解题。栈是先进后出,后进先出,利用这一特性,在外头定义一个函数用来返回右括号对应的左括号,然后再进行出栈操作,若不相等说明不是有效的,若是相等的则将栈顶元素拿出,然后再取第二个元素再与下面元素进行匹配。出完所有栈内元素时,若top为0则表示都一一对应了,返回true, 反之返回false。
char pairs(char a)
{
if (a == ')') return '(';
else if (a == '}') return '{';
else if (a == ']') return '[';
else return 0;
}
bool isValid(char* s) {
int len = strlen(s);
if (len % 2 == 1) return false;
int i = 0;
int stack[len + 1], top = 0;
for (i = 0; i < len; i++)
{
char ch = pairs(s[i]);
if (ch)
{
if (top == 0 || stack[top - 1] != ch)
{
return false;
}
top--;
}
else {
stack[top++] = s[i];
}
}
return top == 0;
}
二、用队列实现栈 -- 用两个队列实现一个后进先出的栈
思路:先将所有元素插入到其中一个队列中,若要实现后进先出,就先将这个队列中的元素插入到另一个队列中,直到这个队列只剩最后一个元素时,将这个元素出队列。同理要出第二个元素也是这个操作,再将这个队列元素插入到刚才空的队列中,这个队列只剩一个元素时再出队列。
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QueueNode;
typedef struct Queue
{
QueueNode* head;
QueueNode* tail;
}Queue;
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
}
void QueueDestroy(Queue* pq)
{
assert(pq);
QueueNode* cur = pq->head;
while (cur)
{
QueueNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
}
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
newnode->data = x;
newnode->next = NULL;
if (pq->head == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
Queue* next = pq->head->next;
free(pq->head);
pq->head = next;
if (pq->head == NULL)
{
pq->tail = NULL;
}
}
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
int QueueSize(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
int n = 0;
QueueNode* cur = pq->head;
while (cur)
{
++n;
cur = cur->next;
}
return n;
}
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL;
}
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack* st = (MyStack*)malloc(sizeof(MyStack));
QueueInit(&st->q1);
QueueInit(&st->q2);
return st;
}
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);
}
}
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj) {
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
obj = NULL;
}
三、用栈实现队列 --- 用两个栈实现一个先入先出的队列
思路:先将所有元素插入其中一个栈中,若要实现先入先出的队列,那就将这个栈中的元素插入到另一个栈中,这样栈中所有元素就倒过来了,再对这个栈进行出栈操作,就实现了先入先出的操作了。
typedef int STDateType;
typedef struct Stack
{
STDateType* a;
int top;
int capacity;
}ST;
void StackInit(ST* ps);
void StackDestroy(ST* ps);
void StackPush(ST* ps, STDateType x);
void StackPop(ST* ps);
STDateType StackTop(ST* ps);
int StackSize(ST* ps);
bool StackEmpty(ST* ps);
void StackInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
void StackDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
void StackPush(ST* ps, STDateType x)
{
assert(ps);
if (ps->top == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDateType* tmp = realloc(ps->a, sizeof(STDateType) * newCapacity);
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->a = tmp;
ps->capacity = newCapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
STDateType StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->a[ps->top - 1];
}
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
typedef struct {
ST pushST;
ST popST;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* q = (MyQueue*)malloc(sizeof(MyQueue));
StackInit(&q->pushST);
StackInit(&q->popST);
return q;
}
void myQueuePush(MyQueue* obj, int x) {
StackPush(&obj->pushST, x);
}
void popStEmpty(MyQueue* obj)
{
while (!StackEmpty(&obj->pushST))
{
StackPush(&obj->popST, StackTop(&obj->pushST));
StackPop(&obj->pushST);
}
}
int myQueuePop(MyQueue* obj) {
if (StackEmpty(&obj->popST))
{
popStEmpty(obj);
}
int top = StackTop(&obj->popST);
StackPop(&obj->popST);
return top;
}
int myQueuePeek(MyQueue* obj) {
if (StackEmpty(&obj->popST))
{
popStEmpty(obj);
}
return StackTop(&obj->popST);
}
bool myQueueEmpty(MyQueue* obj) {
return StackEmpty(&obj->pushST) && StackEmpty(&obj->popST);
}
void myQueueFree(MyQueue* obj) {
StackDestroy(&obj->pushST);
StackDestroy(&obj->popST);
free(obj);
obj = NULL;
}
四、设计循环队列
什么是循环队列?
循环队列就是首尾相接的队列。
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QueueNode;
typedef struct Queue
{
QueueNode* head;
QueueNode* tail;
QDataType capacity;
QDataType size;
}Queue;
void QueueInit(Queue* pq, int x);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
void QueueInit(Queue* pq, int x)
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
pq->capacity = x + 1;
pq->size = 0;
}
void QueueDestroy(Queue* pq)
{
assert(pq);
QueueNode* cur = pq->head;
while (cur)
{
QueueNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
}
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
newnode->data = x;
newnode->next = NULL;
pq->size++;
if (pq->head == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
Queue* next = pq->head->next;
pq->head = next;
pq->size--;
if (pq->head == NULL)
{
pq->tail = NULL;
}
}
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
int QueueSize(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
int n = 0;
QueueNode* cur = pq->head;
while (cur)
{
++n;
cur = cur->next;
}
return n;
}
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL;
}
typedef struct {
Queue q;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* cq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
QueueInit(&cq->q, k);
return cq;
}
int queuefull(Queue* pq)
{
if (pq->size == pq->capacity - 1)
{
return 1;
}
else
{
return 0;
}
}
int queueEmpty(Queue* pq)
{
if (pq->size == 0)
{
return 1;
}
else {
return 0;
}
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if (queuefull(&obj->q) != 1)
{
QueuePush(&obj->q, value);
return true;
}
else
{
return false;
}
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if (queueEmpty(&obj->q) != 1)
{
QueuePop(&obj->q);
return true;
}
else {
return false;
}
}
int myCircularQueueFront(MyCircularQueue* obj) {
if (QueueEmpty(&obj->q))
{
return -1;
}
else {
return QueueFront(&obj->q);
}
}
int myCircularQueueRear(MyCircularQueue* obj) {
if (QueueEmpty(&obj->q))
{
return -1;
}
else {
return QueueBack(&obj->q);
}
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
if (queueEmpty(&obj->q) == 1)
{
return true;
}
else {
return false;
}
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
if (queuefull(&obj->q) == 1)
{
return true;
}
else {
return false;
}
}
void myCircularQueueFree(MyCircularQueue* obj) {
QueueDestroy(&obj->q);
free(obj);
obj = NULL;
}
总结
以上就是关于栈和队列的一些OJ题的解法,如果本文章对你有帮助,请点赞支持一下,若有问题可在下方留言沟通。