@[toc]
目录
目录
1.栈OJ
(1)括号匹配问题
思路:这个题的数组s满足条件的只有当遍历到元素为‘}’或者‘]’或者‘)’时,判断前一个元素是否与之对应, 如果相对应的话,就同时删除这个元素和其上一个元素, 而这个方法正好符合把数组的左括号元素一一插入进栈,栈的顶部元素和数组的第一个元素对应的话,数组s++,栈的top--。
注: 如果数组s符合条件的话,那么左括号和右括号的数量一定是相同的,则当数组里的右括号遍历完时,栈也一定为空
代码如下:
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)
{
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
// 入栈
void StackPush(Stack* ps, STDataType data)
{
assert(ps);
if (ps->top == ps->capacity)
{
int newCapacity = (ps->capacity == 0 ? 4 : 2 * ps->capacity);
ps->a = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
if (ps->a == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->capacity = newCapacity;
}
ps->a[ps->top] = data;
ps->top++;
}
// 出栈
void StackPop(Stack* ps)
{
assert(ps);
assert(ps->top > 0);
ps->top--;
}
// 获取栈顶元素
STDataType StackTop(Stack* ps)
{
assert(ps);
StackEmpty(ps);
return ps->a[ps->top - 1];
}
// 获取栈中有效元素个数
int StackSize(Stack* ps)
{
assert(ps);
assert(ps->top >= 0);
return ps->top;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps)
{
assert(ps);
assert(ps->top >= 0);
return ps->top == 0;
}
// 销毁栈
void StackDestroy(Stack* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
bool isValid(char* s) {
Stack st;
StackInit(&st);
while(*s)
{
//左括号直接进栈
if(*s == '{' || *s == '[' || *s == '(')
{
StackPush(&st, *s);
}
//右括号开始和栈顶元素比较
if(*s == ')' || *s == ']' || *s == '}')
{
//当数组遍历到左括号时,栈一定不能为空
if(StackEmpty(&st))
{
return false;
}
char top = StackTop(&st);
StackPop(&st);
//如果有一对括号匹配,我们还要判断其他的是否匹配,但是如果有一对括号不匹配,就可以直接判断false
if((top =='{' && *s != '}') || (top =='(' && *s != ')') || (top =='[' && *s != ']'))
{
return false;
}
}
s++;
}
return StackEmpty(&st);
}
(2)用栈来实现队列
思路:栈的特点是“先进后出”,而队列的特点是“先进先出”,要想用栈模拟出队列,我们可以设置两个栈,一个pushStack,一个popStack,在入数据时,我们可以把数据统一地压入pushStack里,在出栈的时候,我们先将数据导入到popStack中,这样pushStack的栈底元素就被翻到popStack的栈顶,也就可以第一个被删除掉。
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 StackDestroy(Stack* ps);
// 初始化栈
void StackInit(Stack* ps)
{
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
// 入栈
void StackPush(Stack* ps, STDataType data)
{
assert(ps);
if (ps->top == ps->capacity)
{
int newCapacity = (ps->capacity == 0 ? 4 : 2 * ps->capacity);
ps->a = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
if (ps->a == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->capacity = newCapacity;
}
ps->a[ps->top] = data;
ps->top++;
}
// 出栈
void StackPop(Stack* ps)
{
assert(ps);
assert(ps->top > 0);
ps->top--;
}
// 获取栈顶元素
STDataType StackTop(Stack* ps)
{
assert(ps);
StackEmpty(ps);
return ps->a[ps->top - 1];
}
// 获取栈中有效元素个数
int StackSize(Stack* ps)
{
assert(ps);
assert(ps->top >= 0);
return ps->top;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps)
{
assert(ps);
assert(ps->top >= 0);
return ps->top == 0;
}
// 销毁栈
void StackDestroy(Stack* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
typedef struct {
Stack pushStack;
Stack popStack;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
if(obj == NULL)
{
return NULL;
}
StackInit(&obj->pushStack);
StackInit(&obj->popStack);
return obj;
}
void myQueuePush(MyQueue* obj, int x) {
assert(obj);
StackPush(&(obj->pushStack), x);
}
int myQueuePop(MyQueue* obj) {
//把pushStack里面的全部元素都转移到popStack中,这时,原来导入的数据在popStack里位置顺序相反
while(!StackEmpty(&(obj->pushStack)))
{
int top = StackTop(&(obj->pushStack));
StackPop(&(obj->pushStack));
StackPush(&(obj->popStack),top);
}
//删除掉popStack的栈顶元素,也就是相当于队列的第一个元素
int QueueFront = StackTop(&(obj->popStack));
StackPop(&(obj->popStack));
//再把数据重新导入pushStack中,防止之后的push数据,打乱数据的顺序
while(!StackEmpty(&(obj->popStack)))
{
int top = StackTop(&(obj->popStack));
StackPop(&(obj->popStack));
StackPush(&(obj->pushStack),top);
}
return QueueFront;
}
int myQueuePeek(MyQueue* obj) {
while(!StackEmpty(&(obj->pushStack)))
{
int top = StackTop(&(obj->pushStack));
StackPop(&(obj->pushStack));
StackPush(&(obj->popStack),top);
}
int QueueFront = StackTop(&(obj->popStack));
while(!StackEmpty(&(obj->popStack)))
{
int top = StackTop(&(obj->popStack));
StackPop(&(obj->popStack));
StackPush(&(obj->pushStack),top);
}
return QueueFront;
}
bool myQueueEmpty(MyQueue* obj) {
assert(obj);
//两个栈里面两个必须都为空,myQueue才能算是空
return (StackEmpty(&obj->pushStack) && StackEmpty(&obj->popStack));
}
void myQueueFree(MyQueue* obj) {
StackDestroy(&obj->pushStack);
StackDestroy(&obj->popStack);
}
2.队列OJ
(1)用队列实现栈
思路:这里的队列模拟成栈,其实很单一,因为栈和队列都是“先进”,主要的区别在“出”,这里的话就是两个队列简单的倒换,每次删除时,先把两个队列之间交换Queue - 1次,原来的填充着数据的队列就会只剩下一个元素,这个元素就是最后进入myStack的元素,这时,只需要删除这个元素就达到了栈的“后出”效果。
typedef int QTDataType;
//队列的每一个节点
typedef struct queuenode
{
QTDataType data;
struct queuenode* next;
}QueueNode;
//整个队列
typedef struct queue
{
QueueNode* front;
QueueNode* rear;
}Queue;
// 初始化队列
void QueueInit(Queue * q);
// 队尾入队列
void QueuePush(Queue* q, QTDataType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QTDataType QueueFront(Queue* q);
// 获取队列队尾元素
QTDataType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);
// 创建节点
QueueNode* BuyQueueNode(QTDataType data);
// 初始化队列
void QueueInit(Queue* q)
{
q->front = q->rear = NULL;
}
// 创建节点
QueueNode* BuyQueueNode(QTDataType data)
{
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
if (newnode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
newnode->next = NULL;
newnode->data = data;
return newnode;
}
// 队尾入队列
void QueuePush(Queue* q, QTDataType data)
{
assert(q);
QueueNode* newnode = BuyQueueNode(data);
// 两种情况
// 1. 队列为空
if (q->front == NULL)
{
q->front = q->rear = newnode;
}
else
{
q->rear->next = newnode;
q->rear = q->rear->next;
}
}
// 队头出队列
void QueuePop(Queue* q)
{
assert(q);
//如果队列只有一个节点
if (q->front == q->rear)
{
q->front = q->front->next;
free(q->rear);
q->rear = NULL;
}
//如果队列有多个节点
else
{
QueueNode* cur = q->front->next;
free(q->front);
q->front = cur;
}
}
// 获取队列头部元素
QTDataType QueueFront(Queue* q)
{
assert(q);
assert(q->front);
return q->front->data;
}
// 获取队列队尾元素
QTDataType QueueBack(Queue* q)
{
assert(q);
assert(q->rear);
return q->rear->data;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
assert(q);
QueueNode* cur = q->front;
int count = 0;
while (cur != q->rear->next)
{
count++;
cur = cur->next;
}
return count;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{
assert(q);
return q->front == NULL;
}
// 销毁队列
void QueueDestroy(Queue* q)
{
assert(q);
while (!QueueEmpty(q))
{
QueuePop(q);
}
}
typedef struct {
Queue queue1;
Queue queue2;
} MyStack;
MyStack* myStackCreate() {
MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
if(obj == NULL)
{
return NULL;
}
QueueInit(&obj->queue1);
QueueInit(&obj->queue2);
return obj;
}
void myStackPush(MyStack* obj, int x) {
assert(obj);
if(!QueueEmpty(&obj->queue1))
{
QueuePush(&obj->queue1, x);
}
else
{
QueuePush(&obj->queue2, x);
}
}
int myStackPop(MyStack* obj) {
QTDataType stackTop = 0;
QTDataType front = 0;
if(!QueueEmpty(&obj->queue1))
{
while(QueueSize(&obj->queue1) != 1)
{
front = QueueFront(&obj->queue1);
QueuePop(&obj->queue1);
QueuePush(&obj->queue2, front);
}
stackTop = QueueFront(&obj->queue1);
QueuePop(&obj->queue1);
}
else
{
while(QueueSize(&obj->queue2) != 1)
{
front = QueueFront(&obj->queue2);
QueuePop(&obj->queue2);
QueuePush(&obj->queue1, front);
}
stackTop = QueueFront(&obj->queue2);
QueuePop(&obj->queue2);
}
return stackTop;
}
int myStackTop(MyStack* obj) {
if(QueueEmpty(&obj->queue1))
{
return QueueBack(&obj->queue2);
}
else
{
return QueueBack(&obj->queue1);
}
}
bool myStackEmpty(MyStack* obj) {
assert(obj);
return QueueEmpty(&obj->queue1) && QueueEmpty(&obj->queue2);
}
void myStackFree(MyStack* obj) {
assert(obj);
QueueDestroy(&obj->queue1);
QueueDestroy(&obj->queue2);
}
(2)设计循环队列
思路:这里可以用数组来设计循环队列,也可以用循环链表来设计循环队列,这里如果用循环链表的话,就要创建一个循环链表,这样的话,在插入和删除数据的时候就非常简单,但创建循环链表需要书写许多代码,所以这里我们主要讲的是用数组来设计循环队列。
如图,因为数组为空或者是有一个元素时,tail == front,所以在判空和删除元素的时候我们都要tail == front时,到底是数组已经空了还是还剩下一个元素,这是已经十分麻烦的事,但是如果tail指向的是最后一个元素的下一块空间的话,就很好解决了
ypedef struct {
int front; //第一个元素的下标
int tail; //最后一个元素的后一个下标
int size; //队列刻意容纳的最大元素个数
int* a;
} MyCircularQueue;
bool myCircularQueueIsFull(MyCircularQueue* obj);
bool myCircularQueueIsEmpty(MyCircularQueue* obj);
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->a = (int*)malloc(sizeof(int) * (k + 1));
if(obj->a == NULL)
{
return NULL;
}
obj->size = k;
obj->front = 0;
obj->tail = 0;
return obj;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
assert(obj);
if(myCircularQueueIsFull(obj))
{
return false;
}
obj->a[obj->tail] = value;
obj->tail++;
if(obj->tail == obj->size + 1)
{
obj->tail = 0;
}
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
assert(obj);
if(myCircularQueueIsEmpty(obj))
{
return false;
}
else
{
obj->front++;
if(obj->front == obj->size + 1)
{
obj->front = 0;
}
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;
}
if(obj->tail == 0)
{
return obj->a[obj->size];
}
return obj->a[obj->tail - 1];
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
assert(obj);
return obj->tail == obj->front;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
assert(obj);
if(obj->tail == obj->size)
{
return obj->front == 0;
}
else
{
return obj->tail + 1 == obj->front;
}
}
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
obj->a = NULL;
obj->front = 0;
obj->tail = 0;
obj->size = 0 ;
}