一、有效的括号
题解
此题思路和栈很契合,遇到左括号压栈,遇到右括号就取栈顶元素匹配。
需要注意两个情况,全部都是右括号和遍历结束后栈里还有元素。
还有提前返回false时没有销毁栈造成内存泄露的情况。
typedef char STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
bool STEmpty(ST* pst)//判断是否为空
{
assert(pst);
return pst->top == 0;//比较运算符,等于0为真,非0为假
}
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->capacity = 0;
pst->top = 0;
}
void STPush(ST* pst, STDataType x)//入栈
{
if (pst->capacity == pst->top)
{
int tmp = pst->capacity == 0 ? 4 : pst->capacity * 2;
STDataType* arr = (STDataType*)realloc(pst->a, tmp * sizeof(STDataType));
if (arr == NULL)
{
perror("STPush");
}
pst->capacity = tmp;
pst->a = arr;
}
pst->a[pst->top] = x;
pst->top++;
}
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;
}
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((*s == ']' && top != '[') || (*s == '}' && top != '{') || (*s == ')' && top != '('))
{
STDestroy(&st);
return false;
}
}
s++;
}
bool ret = STEmpty(&st);
STDestroy(&st);
return ret;
}
二、队列实现栈
题解
因为队列是先进先出,栈是先进后出,所以我们可以创建两个队列,保持一个队列一直为空,把有数据的队列的元素出到空队列直到只剩一个元素。再出栈剩下的那个数据,此时出栈数据就是栈顶数据。
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode* ptail;
QNode* phead;
int size;
}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);
bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);
void QueueInit(Queue* pq)
{
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->phead;
while (cur)
{
QNode* behind = cur->next;
free(cur);
cur = behind;
}
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("QueuePush");
}
newnode->data = x;
newnode->next = NULL;
if (pq->phead == NULL)
{
assert(pq->ptail == NULL);
pq->phead = newnode;
pq->ptail = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = newnode;
}
pq->size++;
}
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
if (pq->phead->next == NULL)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else
{
QNode* cur = pq->phead;
pq->phead = pq->phead->next;
free(cur);
}
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;
}
bool QueueEmpty(Queue* pq)
{
assert(pq);
return (pq->phead == NULL && pq->ptail == NULL);
}
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
typedef struct
{
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate()
{
MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
if(obj == NULL)
{
perror("MyStack");
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(pNonEmptyQ->size > 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)
{
assert(obj);
return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj)
{
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}
三、栈实现队列
题解
栈是先入后出,队列是先入先出,我们可以创建两个栈PushST,PopST,用来入队列和出队列。
1.入队列
直接把数据放到PushST里。
2.出队列
如果PopST中没数据则把PushST中数据导入到PopST,若有数据直接出栈。
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;
pst->capacity = 0;
}
void STDestroy(ST* pst)//销毁
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->capacity = 0;
pst->top = 0;
}
void STPush(ST* pst, STDataType x)//入栈
{
if (pst->capacity == pst->top)
{
int tmp = pst->capacity == 0 ? 4 : pst->capacity * 2;
STDataType* arr = (STDataType*)realloc(pst->a, tmp * sizeof(STDataType));
if (arr == NULL)
{
perror("STPush");
}
pst->capacity = tmp;
pst->a = arr;
}
pst->a[pst->top] = x;
pst->top++;
}
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;//比较运算符,等于0为真,非0为假
}
int STSize(ST* pst)
{
assert(pst);
return pst->top;
}
typedef struct
{
ST pushst;
ST popst;
} MyQueue;
MyQueue* myQueueCreate()
{
MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
if(obj == NULL)
{
perror("MyQueue");
}
STInit(&obj->pushst);
STInit(&obj->popst);
return obj;
}
void myQueuePush(MyQueue* obj, int x)
{
STPush(&obj->pushst,x);
}
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);
}
int myQueuePop(MyQueue* obj)
{
int top = myQueuePeek(obj);
STPop(&obj->popst);
return top;
}
bool myQueueEmpty(MyQueue* obj)
{
return (STEmpty(&obj->pushst) && STEmpty(&obj->popst));
}
void myQueueFree(MyQueue* obj)
{
STDestroy(&obj->popst);
STDestroy(&obj->pushst);
free(obj);
}
四、设计循环队列
题解
队列大小是固定的,空间可以重复利用,当放置完最后一个数据后rear需要回到头部。我们开空间时还需要多开一个空间给rear
typedef struct QList
{
int data;
struct QList* next;
}QList;
typedef struct
{
QList* phead;
QList* ptail;
int con;
int size;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k)
{
MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->con = k;
obj->size = 0;
obj->phead = obj->ptail = NULL;
return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
return obj->size == 0;
}
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
return obj->size == obj->con;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
if(myCircularQueueIsFull(obj))
{
return false;
}
QList* plist = (QList*)malloc(sizeof(QList));
plist->next = NULL;
plist->data = value;
if(myCircularQueueIsEmpty(obj))
{
obj->phead = obj->ptail = plist;
}
else
{
obj->ptail->next = plist;
obj->ptail = obj->ptail->next;
}
obj->size++;
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
{
return false;
}
QList* plist = obj->phead;
obj->phead = obj->phead->next;
free(plist);
obj->size--;
return true;
}
int myCircularQueueFront(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->phead->data;
}
int myCircularQueueRear(MyCircularQueue* obj)
{
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->ptail->data;
}
void myCircularQueueFree(MyCircularQueue* obj)
{
while(obj->phead)
{
QList* plist = obj->phead;
obj->phead = obj->phead->next;
free(plist);
}
free(obj);
}