用队列实现栈
首先引用上一篇博客中的队列的相关操作
typedef int QDatatype;
typedef struct QueueNode
{QDatatype data;struct QueueNode* next;
}QueueNode;typedef struct Queue
{QueueNode* head;QueueNode* tail;int size;
}Queue;void QueueInit(Queue* pq)
{assert(pq);pq->size = 0;pq->head = pq->tail = NULL;
}void QueuePush(Queue* pq, QDatatype x)
{assert(pq);QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){perror("malloc fail!");exit(1);}newnode->data = x;newnode->next = NULL;if (pq->head == NULL){pq->head = pq->tail = newnode;}else{pq->tail->next = newnode;pq->tail = pq->tail->next;}pq->size++;
}bool QueueEmpty(Queue* pq)
{assert(pq);return pq->head == NULL;
}void QueuePop(Queue* pq)
{assert(pq);assert(!(QueueEmpty(pq)));if (pq->head == pq->tail){free(pq->head);pq->head = pq->tail = NULL;}else{QueueNode* next = pq->head->next;free(pq->head);pq->head = next;}pq->size--;
}//取队头数据
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);return pq->size;
}//销毁队列
void QueueDestroy(Queue* pq)
{assert(pq);QueueNode* pcur = pq->head;while (pcur){QueueNode* next = pcur->next;free(pcur);pcur = next;}pq->head = pq->tail = NULL;pq->size = 0;
}
初始化
- 因为需要两个队列来实现,因此在定义时定义两个队列
- 在初始化时分别将两个队列进行初始化
typedef struct {Queue q1;Queue q2;
} MyStack;MyStack* myStackCreate() {MyStack* pst=(MyStack*)malloc(sizeof(MyStack));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);}
}
出栈
- 寻找不为空的队列
- 将不为空的队列中的数据入队到另一个队列中,并将入队的元素进行出队的操作,直到该队列只剩一个元素
- 将该元素返回并进行出队操作
bool myStackEmpty(MyStack* obj) {return QueueEmpty(&(obj->q1)) && QueueEmpty(&(obj->q2));
}
int myStackPop(MyStack* obj) {MyStack* emq=&obj->q1;MyStack* fuq=&obj->q2;if(!QueueEmpty(&obj->q1)){emq=&obj->q2;fuq=&obj->q1;}while(QueueSize(fuq) >1){int front=QueueFront(fuq);QueuePush(emq,front);QueuePop(fuq);}int tmp=QueueFront(fuq);QueuePop(fuq);return tmp;
}
寻找栈顶元素
寻找不为空的队列,将该队列的队尾元素进行返回
int myStackTop(MyStack* obj) {if(!QueueEmpty(&obj->q1)){return QueueBack(&obj->q1);}else{return QueueBack(&obj->q2);}
}
销毁栈
将两个队列分别进行销毁,并将obj
进行free
并且置空
void myStackFree(MyStack* obj) {QueueDestroy(&obj->q1);QueueDestroy(&obj->q2);free(obj);obj=NULL;
}
用栈实现队列
首先引用上上篇博客中栈的相关操作
typedef int STDatatype;typedef struct stack
{STDatatype* arr;int capacity;int top;
}ST;//初始化
void STInit(ST* ps)
{assert(ps);ps->arr = NULL;ps->capacity = ps->top = 0;
}void STDestory(ST* ps)
{assert(ps);if (ps->arr)free(ps->arr);ps->arr = NULL;ps->capacity = ps->top = 0;
}void STPush(ST* ps, STDatatype x)
{assert(ps);if (ps->capacity == ps->top){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDatatype* tmp = (ST*)realloc(ps->arr, newcapacity * sizeof(ST));if (tmp == NULL){perror("realloc fail!");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}ps->arr[ps->top++] = x;
}bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}void STPop(ST* ps)
{assert(ps);assert(!(StackEmpty(ps)));ps->top--;
}//取栈顶元素
STDatatype StackTop(ST* ps)
{assert(ps);assert(!(StackEmpty(ps)));return ps->arr[ps->top-1];
}int STSize(ST* ps)
{assert(ps);return ps->top;
}
初始化
- 定义两个栈,一个用于模拟入队的操作,一个用于模拟出队的操作
- 初始化两个栈
typedef struct {ST pushST;ST popST;
} MyQueue;MyQueue* myQueueCreate() {MyQueue* pst=(MyQueue*)malloc(sizeof(MyQueue));STInit(&pst->pushST);STInit(&pst->popST);return pst;
}
入队
直接进行入栈操作即可
void myQueuePush(MyQueue* obj, int x) {STPush(&obj->pushST,x);
}
出队
- 判断出栈的栈是否为空
1)为空,则将入栈的栈中的元素传入出栈的栈中
2)不为空,则进行出栈的操作,并将出栈的元素的值返回
bool myQueueEmpty(MyQueue* obj) {return StackEmpty(&obj->pushST) && StackEmpty(&obj->popST);
}int myQueuePop(MyQueue* obj) {if(StackEmpty(&obj->popST)){while(!StackEmpty(&obj->pushST)){STPush(&obj->popST,StackTop(&obj->pushST));STPop(&obj->pushST);}}int tmp=StackTop(&obj->popST);STPop(&obj->popST);return tmp;
}
寻找队头元素
思路同出队方法,只是不需要进行出栈的操作,直接返回栈顶元素的值
int myQueuePeek(MyQueue* obj) {if(StackEmpty(&obj->popST)){while(!StackEmpty(&obj->pushST)){STPush(&obj->popST,StackTop(&obj->pushST));STPop(&obj->pushST);}}return StackTop(&obj->popST);
}
销毁队
销毁两个栈,并将obj
进行free
并且置空
void myQueueFree(MyQueue* obj) {STDestory(&obj->pushST);STDestory(&obj->popST);free(obj);obj=NULL;
}
设计循环队列
初始化
本题可以借助数组作为底层的结构,因此在初始化时,动态开辟一个数组,并将数组的头尾和数组大小进行记录
typedef struct {int* arr;int front;int rear;int capacity;
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* pst=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));pst->arr=(int*)malloc(sizeof(int)*(k+1));pst->front=pst->rear=0;pst->capacity=k;return pst;
}
插入队列元素
- 需要先判断数组是否已经满了
1)若已满,则直接返回false
2)若不满,则在数组的尾部插入数据,并将rear++,注意需要对rear取capacity+1的余数,因为该队列是循环的,最后返回true
bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->rear+1)%(obj->capacity+1)==obj->front;
}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if(myCircularQueueIsFull(obj)){return false;}else{obj->arr[obj->rear++]=value;obj->rear %=obj->capacity+1;return true;}
}
删除队列元素
- 判断队列是否为空
1)为空,则返回false
2)不为空,则front++,注意队列的循环,将front取capacity+1的余数,并返回true
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->rear == obj->front;
}bool myCircularQueueDeQueue(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj)){return false;}else{obj->front++;obj->front %=obj->capacity+1;return true;}
}
寻找队头元素
- 判断队列是否为空
- 为空则返回-1,不为空则返回队头元素
int myCircularQueueFront(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj)){return -1;}return obj->arr[obj->front];
}
寻找队尾元素
- 判断队列是否为空
- 为空则返回-1,不为空则返回队尾元素,需要注意rear-1才是真正的队尾,注意队列的循环
int myCircularQueueRear(MyCircularQueue* obj) {if(myCircularQueueIsEmpty(obj)){return -1;}int prev=obj->rear-1;if(obj->rear == 0){prev=obj->capacity;}return obj->arr[prev];
}
销毁循环队列
void myCircularQueueFree(MyCircularQueue* obj) {free(obj->arr);free(obj);obj=NULL;
}