目录
- 括号匹配问题
- 思路
- 代码
- 用队列实现栈
- 思路
- 注意点
- 代码
- 用栈实现队列
- 思路
- 代码
- 设计循环队列
- 思路
- 数组实现代码
- 链表实现代码
括号匹配问题
OJ链接
思路
是左括号则入栈,是右括号则出栈然后两两比较
代码
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
#include<string.h>
typedef char STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
void STInit(ST* pst);
void STDestroy(ST* pst);
void STPush(ST* pst,STDataType x);
void STPop(ST* pst);
STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);
void STInit(ST* pst)
{
assert(pst);
pst->a = NULL;
pst->top = 0;//top指向栈顶元素的下一个位置
pst->capacity = 0;
}
void STDestroy(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->capacity = pst->top = 0;
}
void STPush(ST* pst, STDataType x)
{
assert(pst);
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)
{
//printf("error: %s\n", strerror(errno));
perror("realloc fail\n");
return;
}
pst->a = tmp;
pst->capacity = newcapacity;
}
pst->a[pst->top++] = x;
}
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];
}
bool STEmpty(ST* pst)
{
assert(pst);
return pst->top == 0;
}
int STSize(ST* pst)
{
assert(pst);
return pst->top;
}
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;
}
int top=STTop(&st);
STPop(&st);
if(*s == '}' && top != '{'
|| *s == ')' && top != '('
|| *s == ']' && top != '[')
{
STDestroy(&st);
return false;
}
}
s++;
}
bool ret=STEmpty(&st);
STDestroy(&st);
return ret;
}
用队列实现栈
OJ链接
思路
push数据的时候push到非空的那个队列
pop数据的时候把非空队列的数据转移到空的队列,直到只剩最后一个,然后pop
注意点
局部结构体变量出了作用域销毁,还去返回它的地址,就是野指针了,所以这样写是不对的
应该malloc一个节点后再返回
不要为了不想把&obj->q1传递给Init而在MyStack中写成队列的指针,这时候这两个指针没有初始化,到Init函数中就有野指针问题。如果实在想在MyStack中写成队列的指针,可以q1和q2再去malloc
只free(obj)那么链表中的节点就会出现内存泄漏的问题
代码
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int QDataType;
//链表队列
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QNode;
//为了方便尾插头插和个数的记录
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
//初始化队列
void QueueInit(Queue* pq);
//入队列,尾插
void QueuePush(Queue* pq, QDataType x);
//出队列,头删
void QueuePop(Queue* pq);
//销毁
void QueueDestroy(Queue* pq);
//获取队列中有效元素个数
int QSize(Queue* pq);
//检测队列是否为空
bool QueueEmpty(Queue* pq);
//取队头元素
QDataType QueueFront(Queue* pq);
//取队尾元素
QDataType QueueBack(Queue* pq);
//初始化队列
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
pq->size = 0;
}
//入队列,尾插
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* tmp = (QNode*)malloc(sizeof(QNode));
if (tmp == NULL)
{
perror("malloc fail\n");
return;
}
tmp->data = x;
tmp->next = NULL;
if (pq->tail == NULL)
{
pq->head = pq->tail = tmp;
}
else
{
pq->tail->next = tmp;
pq->tail = tmp;
}
pq->size++;
}
//出队列,头删
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
pq->size--;
}
//销毁
void QueueDestroy(Queue* pq)
{
assert(pq);
//while (!QueueEmpty(pq))
//{
// QNode* next = pq->head->next;
// free(pq->head);
// pq->head = next;
//}
QNode* cur = pq->head;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
//获取队列中有效元素个数
int QSize(Queue* pq)
{
assert(pq);
return pq->size;
}
//检测队列是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return 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;
}
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack* ST=(MyStack*)malloc(sizeof(MyStack));
if(ST==NULL)
{
perror("malloc fail\n");
return NULL;
}
QueueInit(&ST->q1);
QueueInit(&ST->q2);
return ST;
}
void myStackPush(MyStack* obj, int x) {
assert(obj);
//插入非空的那个队列,两个都空则无所谓
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1,x);
}
else
{
QueuePush(&obj->q2,x);
}
}
int myStackPop(MyStack* obj) {
assert(obj);
Queue* EmptyQ=&obj->q1;
Queue* NonEmptyQ=&obj->q2;
if(!QueueEmpty(EmptyQ))
{
NonEmptyQ=&obj->q1;
EmptyQ=&obj->q2;
}
//将非空队列的元素放到空队列,留下一个,然后Pop
while(QSize(NonEmptyQ)>1)
{
QueuePush(EmptyQ,QueueFront(NonEmptyQ));
QueuePop(NonEmptyQ);
}
int top=NonEmptyQ->head->data;
QueuePop(NonEmptyQ);
return top;
}
int myStackTop(MyStack* obj) {
assert(obj);
if(!QueueEmpty(&obj->q1))
{
return QueueBack(&obj->q1);
}
else
{
return QueueBack(&obj->q2);
}
}
bool myStackEmpty(MyStack* obj) {
assert(obj);
return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj) {
assert(obj);
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}
用栈实现队列
OJ链接
思路
一个栈负责push
一个栈负责pop
push时放进pushst
pop时如果popst为空,则将pushst中数据都放入popst,然后对popst中数据进行pop
如果popst不为空,则直接对popst中数据进行pop
代码
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
#include<string.h>
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
void STInit(ST* pst);
void STDestroy(ST* pst);
void STPush(ST* pst,STDataType x);
void STPop(ST* pst);
STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);
void STInit(ST* pst)
{
assert(pst);
pst->a = NULL;
pst->top = 0;//top指向栈顶元素的下一个位置
pst->capacity = 0;
}
void STDestroy(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->capacity = pst->top = 0;
}
void STPush(ST* pst, STDataType x)
{
assert(pst);
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\n");
return;
}
pst->a = tmp;
pst->capacity = newcapacity;
}
pst->a[pst->top++] = x;
}
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];
}
bool STEmpty(ST* pst)
{
assert(pst);
return pst->top == 0;
}
int STSize(ST* pst)
{
assert(pst);
return pst->top;
}
typedef struct {
ST s1;//第一个栈用来存数据
ST s2;//第二个栈用来出数据
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
if(obj==NULL)
{
perror("malloc fail\n");
return NULL;
}
STInit(&obj->s1);
STInit(&obj->s2);
return obj;
}
void myQueuePush(MyQueue* obj, int x) {
assert(obj);
//放到存数据的栈
STPush(&obj->s1,x);
}
int myQueuePop(MyQueue* obj) {
int front=myQueuePeek(obj);
STPop(&obj->s2);
return front;
}
int myQueuePeek(MyQueue* obj) {
//如果用来出数据的栈(s2)为空,那么将s1栈中数据移动到s2的栈
if(STEmpty(&obj->s2))
{
while(STSize(&obj->s1)>0)
{
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) {
STDestroy(&obj->s1);
STDestroy(&obj->s2);
free(obj);
}
设计循环队列
OJ链接
思路
无法确定满的时候的状态
解决方案:
1.多开一个空间。满:real+1 == front
2.增加一个size变量记录数据个数
空:size==0
满:size==8
这里展示多开一个空间的方案
循环队列可以用链表实现也可以用数组实现
链表实现思路:
空:front == rear
满:rear->next == front
由于需要获取队尾元素,
解决思路有:1.双向链表 2.增加一个prev指针 3.遍历获得队尾数据
数组实现思路:
空:front == real
满:(rear+1)%(k+1) == front
相比来说数组实现会简单一些,因为链表实现起来结构更复杂
数组实现代码
typedef struct {
int* a;
int front;
int real;
int k;
} MyCircularQueue;
bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->a=(int*)malloc(sizeof(int)*(k+1));//多开一个空间方便判满
obj->front=0;
obj->real=0;
obj->k=k;
return obj;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(myCircularQueueIsFull(obj))
return false;
obj->a[obj->real++]=value;
obj->real%=(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;
if(obj->real==0)
return obj->a[obj->k];
else
return obj->a[obj->real-1];
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->front==obj->real;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return (obj->real+1)%(obj->k+1)==obj->front;
}
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
obj->real=obj->front=obj->k=0;
free(obj);
}
链表实现代码
typedef struct QueueNode
{
struct QueueNode*next;
int data;
}QNode;
typedef struct {
QNode*front;
QNode*real;
QNode*prev;
} MyCircularQueue;
bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);
QNode* QueueInit(int k)
{
QNode*phead=(QNode*)malloc(sizeof(QNode));
QNode*cur=phead;
while(k--)
{
QNode*next=(QNode*)malloc(sizeof(QNode));
cur->next=next;
cur->data=0;
next->next=phead;
cur=next;
}
return phead;
}
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
if(obj==NULL)
{
perror("malloc fail\n");
return NULL;
}
QNode*phead=QueueInit(k);
obj->front=phead;
obj->real=phead;
obj->prev=NULL;
return obj;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(myCircularQueueIsFull(obj))
return false;
obj->real->data=value;
obj->prev=obj->real;//记录前一个
obj->real=obj->real->next;
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return false;
obj->front=obj->front->next;
return true;
}
int myCircularQueueFront(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return -1;
return obj->front->data;
}
int myCircularQueueRear(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
return -1;
return obj->prev->data;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return obj->front==obj->real;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
return obj->real->next==obj->front;
}
void myCircularQueueFree(MyCircularQueue* obj) {
QNode*cur=obj->front;
QNode*next=cur->next;
while(next!=obj->front)
{
free(cur);
cur=next;
next=cur->next;
}
free(cur);
obj->front=NULL;
obj->real=NULL;
obj->prev=NULL;
free(obj);
}