232. 用栈实现队列 - 力扣(LeetCode)用两个栈来实现队列的功能,我们用其中一个栈来入数据,另一个来出数据,分别定义为pushst和popst,用来实现入栈时,只给pushst里面入数据,实现出栈时,只出popst里的数据,注意的是当popst为空时,要将pushst里的数据放到popst里去,再出栈。
就是用C语言的话,还得自己写个栈。
代码实现如下:
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;//栈顶位置
int capacity;//容量
}ST;
void STInit(ST* ps);//初始化
void STDestroy(ST* ps);//销毁
void STPush(ST* ps, STDataType x);//插入
void STPop(ST* ps);//删除
STDataType StackTop(ST* ps);//取栈顶元素
bool STEmpty(ST* ps);//判断栈是否为空
int StackSize(ST* ps);//有多少数据
void STInit(ST* ps)//初始化
{
assert(ps);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
void STDestroy(ST* ps)//销毁
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = 0;
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 = (STDataType*)realloc(ps->a, sizeof(STDataType) * newcapacity);
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->a = tmp;
ps->capacity = newcapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
void STPop(ST* ps)//删除
{
assert(ps);
assert(!STEmpty(ps));
ps->top--;
}
STDataType StackTop(ST* ps)//取栈顶元素
{
assert(ps);
assert(!STEmpty(ps));
return ps->a[ps->top - 1];
}
bool STEmpty(ST* ps)//判断栈是否为空
{
return ps->top == 0;//为真返回true,为假返回false
}
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
typedef struct {
ST pushst;
ST popst;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
if(obj == NULL)
{
return NULL;
}
STInit(&obj->pushst);
STInit(&obj->popst);
return obj;
}
void myQueuePush(MyQueue* obj, int x) {
STPush(&obj->pushst, x);
}
int myQueuePop(MyQueue* obj) {
if(STEmpty(&obj->popst))
{
while(!STEmpty(&obj->pushst))
{
STPush(&obj->popst, StackTop(&obj->pushst));
STPop(&obj->pushst);
}
}
int front = StackTop(&obj->popst);
STPop(&obj->popst);
return front;
}
int myQueuePeek(MyQueue* obj) {
if(STEmpty(&obj->popst))//如果pop为空,要倒数据
{
while(!STEmpty(&obj->pushst))
{
STPush(&obj->popst, StackTop(&obj->pushst));
STPop(&obj->pushst);
}
}
return StackTop(&obj->popst);
}
bool myQueueEmpty(MyQueue* obj) {
return STEmpty(&obj->pushst) && STEmpty(&obj->popst);
}
void myQueueFree(MyQueue* obj) {
STDestroy(&obj->pushst);
STDestroy(&obj->popst);
free(obj);
}
用两个队列实现栈,关键是要始终保持有一个队列是空的,这样方便后面倒数据,入队列的时候,给非空的队列里入数据,若都为空,就随便入一个,取栈顶数据时,由于队列是可以取队尾元素的,所以直接返回就行,删除栈顶元素时,先将非空队列的元素全都倒到空队列里去,再出队列就行。
代码实现如下:
typedef int QueueDataType;
typedef struct QueueNode
{
QueueDataType data;
struct QueueNode* next;
}QueueNode;
typedef struct Queue
{
QueueNode* head;
QueueNode* tail;
}Queue;
void QueueInit(Queue* pq);//初始化
void QueueDestroy(Queue* pq);//销毁
void QueuePop(Queue* pq);//弹出
void QueuePush(Queue* pq, QueueDataType x);//插入
QueueDataType QueueFront(Queue* pq);//队头数据
QueueDataType QueueBack(Queue* pq);//队尾数据
bool QueueEmpty(Queue* pq);//判空
int QueueSize(Queue* pq);//元素个数
void QueueInit(Queue* pq)//初始化
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
}
void QueueDestroy(Queue* pq)//销毁
{
assert(pq);
QueueNode* cur = pq->head;
while (cur)
{
QueueNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
}
void QueuePop(Queue* pq)//弹出
{
assert(pq);
assert(!QueueEmpty(pq));
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = NULL;
pq->tail = NULL;
}
else
{
QueueNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
}
void QueuePush(Queue* pq, QueueDataType 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->tail == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
QueueDataType QueueFront(Queue* pq)//队头数据
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
QueueDataType QueueBack(Queue* pq)//队尾数据
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
bool QueueEmpty(Queue* pq)//判空
{
assert(pq);
return pq->head == NULL;
}
int QueueSize(Queue* pq)//元素个数
{
assert(pq);
int size = 0;
QueueNode* cur = pq->head;
while (cur)
{
++size;
cur = cur->next;
}
return size;
}
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
if(obj == NULL)
{
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* emptyQ = &obj->q1;
Queue* nonEmptyQ = &obj->q2;
if(!QueueEmpty(&obj->q1))
{
emptyQ = &obj->q2;
nonEmptyQ = &obj->q1;
}
while(QueueSize(nonEmptyQ) > 1)
{
QueuePush(emptyQ, QueueFront(nonEmptyQ));
QueuePop(nonEmptyQ);
}
int top = QueueFront(nonEmptyQ);
QueuePop(nonEmptyQ);
return top;
}
int myStackTop(MyStack* obj) {
if(!QueueEmpty(&obj->q1))
{
return QueueBack(&obj->q1);
}
else
{
return QueueBack(&obj->q2);
}
}
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj) {
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}
设计循环队列,队列的实现可以是链式的,但在此题中,最好用顺序表写,开辟的时候,有K个数字,多开辟一个空间,即K+1个空间,方便判断队列已满,用下标访问,用head表示队头,用tail表示队尾,开始时,head == tail表示该队列为空。若出现tail+1 == head,就表示队列已满,但要注意处理边界,即当tail+1 == k+1,tail = 0等,注意边界就行
代码实现如下:
typedef struct {
int* a;
int k;
int head;
int tail;
} MyCircularQueue;
//记得边界一定要控制一下!
bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value);
bool myCircularQueueIsFull(MyCircularQueue* obj);
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->a = (int*)malloc(sizeof(int)*(k+1));
obj->head = obj->tail = 0;
obj->k = k;
return obj;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if(myCircularQueueIsFull(obj))
{
return false;
}
else
{
obj->a[obj->tail] = value;
obj->tail++;
}
if(obj->tail == obj->k+1)
{
obj->tail = 0;
}
return true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return false;
}
obj->head++;
if(obj->head == obj->k+1)
{
obj->head = 0;
}
return true;
}
int myCircularQueueFront(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->a[obj->head];
}
int myCircularQueueRear(MyCircularQueue* obj) {
if(myCircularQueueIsEmpty(obj))
{
return -1;
}
int prev = obj->tail-1;
if(obj->tail == 0)
prev = obj->k;
return obj->a[prev];
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
return (obj->head == obj->tail);
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
int next = obj->tail+1;
if(next == obj->k+1)
{
next = 0;
}
return next == obj->head;
}
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
free(obj);
}
水平有限,欢迎指正。