✨✨大家好呀!博主这几天正在用C语言学习简单的数据结构
刚好学习到了栈和队列,学了这么久,想着能不能找几道题来做做
虽说用C语言做题着实很痛苦,被小小地打击了一下
但也加深了博主对数据结构的理解,下面整理了几道栈和队列的题与大家分享。
山外青山楼外楼,自然探秘永无休
成功易使人陶醉,莫把百尺当尽头
前提知识:
C语言实现栈和队列
题目链接
思路分析:初始化栈,如果是左括号就入栈,如果是右括号就出栈一个左括号元素,出栈了之后与右括号进行匹配,如果不匹配就return false
,匹配就继续比。如果左右括号的数量不相等怎么办呢?只要在最后判断一下栈是否为空就行了,栈为空return true;
栈不为空,return false
;另外只有右括号时也要单独判断一下,因为只有右括号,栈就是空了,此时再出栈就越界了。
友情提醒,return之前别忘了free哦,防止内存泄漏,养成好习惯。
//C语言实现栈
/******************************************************************************************/
typedef char STDataType;
typedef struct Stack
{
STDataType* a;
int top; // 栈顶的位置
int capacity; // 容量
}ST;
void StackInit(ST* ps);
void StackDestory(ST* ps);
void StackPush(ST* ps, STDataType x);
void StackPop(ST* ps);
bool StackEmpty(ST* ps);
STDataType StackTop(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, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
ps->a = (STDataType*)realloc(ps->a, newCapacity* sizeof(STDataType));
if (ps->a == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->capacity = newCapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
void StackPop(ST* ps)
{
assert(ps);
assert(ps->top > 0);
--ps->top;
}
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
STDataType StackTop(ST* ps)
{
assert(ps);
assert(ps->top > 0);
return ps->a[ps->top - 1];
}
/******************************************************************************************/
//做题
bool isValid(char * s)
{
ST st;
StackInit(&st);
while(*s)
{
//如果是左括号就入栈
if(*s == '[' || *s == '(' || *s == '{')
{
StackPush(&st, *s);
++s;
}
else
{
//只有右括号,匹配失败
if(StackEmpty(&st))
return false;
//如果是右括号,出栈一个左括号进行匹配
char top = StackTop(&st);
StackPop(&st);
if((*s==']' && top !='[')
||(*s=='}' && top !='{')
||(*s==')' && top !='('))
{
//匹配失败,return false,return之前销毁栈防止内存泄漏
StackDestroy(&st);
return false;
}
else
{
//匹配成功,继续比
++s;
}
}
}
//栈为空,说明所有括号都匹配了
bool ret = StackEmpty(&st);
StackDestroy(&st);
return ret;
}
结构实现:
//C语言实现队列
/******************************************************************************************/
typedef int QDataType;
typedef struct QueueNode
{
QDataType data;
struct QueueNode* next;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
}Queue;
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);
bool QueueEmpty(Queue* pq);
size_t QueueSize(Queue* pq);
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
}
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
}
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
assert(newnode);
newnode->data = x;
newnode->next = NULL;
if (pq->tail == NULL)
{
assert(pq->head == NULL);
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->head && pq->tail);
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;
}
}
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL;
}
size_t QueueSize(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
size_t size = 0;
while (cur)
{
size++;
cur = cur->next;
}
return size;
}
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(pq->head);
return pq->head->data;
}
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(pq->tail);
return pq->tail->data;
}
/******************************************************************************************/
//做题
typedef struct
{
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate()
{
MyStack* pst = (MyStack*)malloc(sizeof(MyStack));
assert(pst);
QueueInit(&pst->q1);
QueueInit(&pst->q2);
return pst;
}
void myStackPush(MyStack* obj, int x)
{
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1,x);
}
else
{
QueuePush(&obj->q2,x);
}
}
int myStackPop(MyStack* obj)
{
assert(obj);
//默认q1是空队列,q2是非空队列
Queue* emptyQ = &obj->q1;
Queue* nonEmptyQ = &obj->q2;
//修正
if(!QueueEmpty(&obj->q1))
{
emptyQ = &obj->q2;
nonEmptyQ = &obj->q1;
}
//把非空队列的前N-1个数据,倒入空队列
//就实现了后进先出
while(QueueSize(nonEmptyQ)>1)
{
int front = QueueFront(nonEmptyQ);
QueuePush(emptyQ,front);
QueuePop(nonEmptyQ);
}
int top = QueueFront(nonEmptyQ);
//剩下一个删掉
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);
}
/**
* Your MyStack struct will be instantiated and called as such:
* MyStack* obj = myStackCreate();
* myStackPush(obj, x);
* int param_2 = myStackPop(obj);
* int param_3 = myStackTop(obj);
* bool param_4 = myStackEmpty(obj);
* myStackFree(obj);
*/
/*************************************C语言实现栈********************************************/
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
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->top = ps->capacity = 0;
}
void StackPush(ST* ps, STDataType x)
{
assert(ps);
//扩容
if (ps->top == ps->capacity)
{
STDataType newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
ps->a = (STDataType*)realloc(ps->a, newCapacity * sizeof(STDataType));
if (ps->a == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->capacity = newCapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
void StackPop(ST* ps)
{
assert(ps);
assert(ps->top > 0);
ps->top--;
}
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
STDataType StackTop(ST* ps)
{
assert(ps);
assert(ps->top > 0);
return ps->a[ps->top - 1];
}
/********************************************************************************************/
typedef struct {
ST pushST;
ST popST;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue*obj=(MyQueue*)malloc(sizeof(MyQueue));
assert(obj);
StackInit(&obj->pushST);
StackInit(&obj->popST);
return obj;
}
void myQueuePush(MyQueue* obj, int x) {
assert(obj);
StackPush(&obj->pushST,x);
}
int myQueuePop(MyQueue* obj) {
assert(obj);
//如果popST为空,把pushST的数据倒过来,就符合先进先出的顺序
if(StackEmpty(&obj->popST))
{
while(!StackEmpty(&obj->pushST))
{
StackPush(&obj->popST,StackTop(&obj->pushST));
StackPop(&obj->pushST);
}
}
int front = StackTop(&obj->popST);
StackPop(&obj->popST);
return front;
}
int myQueuePeek(MyQueue* obj) {
assert(obj);
//如果popST为空,把pushST的数据倒过来,就符合先进先出的顺序
if(StackEmpty(&obj->popST))
{
while(!StackEmpty(&obj->pushST))
{
StackPush(&obj->popST,StackTop(&obj->pushST));
StackPop(&obj->pushST);
}
}
return StackTop(&obj->popST);
}
bool myQueueEmpty(MyQueue* obj) {
assert(obj);
return StackEmpty(&obj->pushST)&&StackEmpty(&obj->popST);
}
void myQueueFree(MyQueue* obj) {
assert(obj);
StackDestroy(&obj->pushST);
StackDestroy(&obj->popST);
free(obj);
}
/**
* Your MyQueue struct will be instantiated and called as such:
* MyQueue* obj = myQueueCreate();
* myQueuePush(obj, x);
* int param_2 = myQueuePop(obj);
* int param_3 = myQueuePeek(obj);
* bool param_4 = myQueueEmpty(obj);
* myQueueFree(obj);
*/
Push:
为了避免空和满混淆,无法区分,多开一个空间(比如开4个空间只能存3个数据)。当front==tail
时是空,tail
的下一个位置是front
,就是满。满又分为两种情况:
1.
2.
此时已经是满了,不能再进行Push数据,必须先Pop
数据。
Pop:
只要队列不是满的,就可以继续插入数据,front == tail
就删为空。
继续Push数据:
此时队列又写满了,必须删除数据再写入数据,以此达到循环队列的目的。
typedef struct
{
int* a;
int front;
int tail;
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 = obj->tail = 0;
obj->k = k;
return obj;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
//满了就不能写入数据
if(myCircularQueueIsFull(obj))
return false;
obj->a[obj->tail] = value;
//tail走到最后一个空间,到了边界,就置回第一个位置
if(obj->tail == obj->k)
{
obj->tail = 0;
}
else
{
obj->tail++;
}
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
//空了就不能删除数据
if(myCircularQueueIsEmpty(obj))
return false;
//front走到最后一个空间,到了边界,置回第一个位置
if(obj->front == obj->k)
{
obj->front = 0;
}
else
{
obj->front++;
}
return true;
}
//取队头数据
int myCircularQueueFront(MyCircularQueue* obj)
{
//题目要求队列为空返回-1
if(myCircularQueueIsEmpty(obj))
return -1;
return obj->a[obj->front];
}
//取队尾数据
int myCircularQueueRear(MyCircularQueue* obj)
{
//题目要求,空队列返回-1
if(myCircularQueueIsEmpty(obj))
return -1;
//如果tail在第一个位置,队尾是在k
if(obj->tail == 0)
{
return obj->a[obj->k];
}
else
{
//否则队尾就是tail-1
return obj->a[obj->tail-1];
}
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
return obj->front == obj->tail;
}
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
//满的第二种情况
if(obj->tail == obj->k && obj->front == 0)
{
return true;
}
else
{
//满的第一种情况
return obj->tail+1 == obj->front;
}
}
void myCircularQueueFree(MyCircularQueue* obj)
{
free(obj->a);
free(obj);
}
/**
* Your MyCircularQueue struct will be instantiated and called as such:
* MyCircularQueue* obj = myCircularQueueCreate(k);
* bool param_1 = myCircularQueueEnQueue(obj, value);
* bool param_2 = myCircularQueueDeQueue(obj);
* int param_3 = myCircularQueueFront(obj);
* int param_4 = myCircularQueueRear(obj);
* bool param_5 = myCircularQueueIsEmpty(obj);
* bool param_6 = myCircularQueueIsFull(obj);
* myCircularQueueFree(obj);
*/