个人主页:欢迎大家光临——>沙漠下的胡杨
各位大帅哥,大漂亮
如果觉得文章对自己有帮助
可以一键三连支持博主
你的每一分关心都是我坚持的动力
☄: 本期重点:力扣225 力扣232
希望大家每天都心情愉悦的学习工作。
用队列实现栈(力扣225):
代码实现:
插入:
初始化:
入栈:
删除栈顶元素并返回值:
返回栈顶元素:
判断栈是否为空:
栈的销毁:
整体代码(包含队列的创建):
用栈实现队列(力扣 232):
代码实现:
队列的创建,初始化和销毁
判断队列是否为空:
队列的插入:
从队列的开头移除并返回元素:
返回队列开头元素:
整体代码:
在前几天学习了栈和队列,关于栈和队列的特性我们还不是很熟练,今天我们一起做两道题,分别是用队列实现栈,和用栈实现队列,来进一步强化下所学习的知识吧。
这是题目,就是在不考虑效率的情况下,使用队列模拟实现栈的性质,我们使用的语言依然是 纯C ,所以我们在这之前还是要先写出一个队列出来的,我就借用之前文章的栈和队列来实现了。(队列实现)(栈的实现)
我们分析先下如何实现呢?
队列是先进先出,我们要实现先进后出,我们可以用两个队列,一个队列用来存储数据,一个队列用来倒数据,先把数据放入一个队列中,然后再把除了最后一个数据的其他数据放入另一个队列中,使原本队列只剩一个数据,然后删除,循环倒数据即可实现栈的功能。
下面我们来实现函数接口吧:
插入:
typedef struct { Queue q1; Queue q2; } MyStack;//创建结构
创建时我们可以直接进行创建两个队列,方便倒数据。
初始化:
MyStack* myStackCreate() //初始化,并返回一个结点 { MyStack* obj = (MyStack*)malloc(sizeof(MyStack)); QueueInit(&obj->q1); QueueInit(&obj->q2); return obj; }
我们必须要 malloc 一个所谓的栈的空间,因为最后要返回这个结构的指针,这个函数要销毁,如果返回栈空间地址,地址值无效,指针就无效了。
然后在一个个初始化这个 q1和q2队列就好了。
入栈:
void myStackPush(MyStack* obj, int x)//入栈 { if(!QueueEmpty(&obj->q1)) { QueuePush(&obj->q1,x); } else { QueuePush(&obj->q2,x); } }
入栈时比较简单,我们就向队列中有元素的中存放就可以啦。如果都为空,那就无所谓。
删除栈顶元素并返回值:
int myStackPop(MyStack* obj) //删除栈顶数据,并返回 { Queue* Empty = &obj->q1; Queue* NoEmpty = &obj->q2; if(!QueueEmpty(&obj->q1)) { Empty = &obj->q2; NoEmpty = &obj->q1; } while(QueueSize(NoEmpty)>1) { QueuePush(Empty,QueueFront(NoEmpty)); QueuePop(NoEmpty); } int top = QueueFront(NoEmpty); QueuePop(NoEmpty); return top; }
我们首先使用假设法,得到为空的队列和不为空的队列,我们把这个不为空的队列向为空的队列中插入,然后pop掉不为空队列的首元素,一直到这个队列元素数量为 1 时停止,最后我们把原先不为空的队列的元素的唯一一个元素取出来,然后在pop掉,这样原来不为空的队列就为空了,其他的元素也通过插入放入了原来不为空的队列中了。
返回栈顶元素:
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); }
因为我们创建时就是创建的 obj 的空间,在逐步创建的q1 和 q2 的空间,所以我们在释放时,我们也该先释放q1 和 q2的空间,如果先释放 obj ,那么就找不到q1 q2了。
typedef int QDataType; typedef struct QueueNode { QDataType data; struct QueueNode* next; }QNode; typedef struct Queue { QNode* head; QNode* tail; }Queue; void QueueInit(Queue* qp);//初始化 void QueueDestroy(Queue* qp);//队列的销毁 void QueuePush(Queue* qp,QDataType x);//队列插入 void QueuePop(Queue* qp);//队列删除 QDataType QueueFront(Queue* qp);//取出队列首元素 QDataType QueueBack(Queue* qp);//取出队列末尾元素 bool QueueEmpty(Queue* qp);//判断队列是否为空 int QueueSize(Queue* qp);//返回队列的元素个数 void QueueInit(Queue* qp)//初始化 { assert(qp); qp->head = qp->tail = NULL; } void QueueDestroy(Queue* qp)//队列的销毁 { assert(qp); QNode* cur = qp->head; while (cur) { QNode* next = cur->next; free(cur); cur = next; } qp->head = qp->tail = NULL; } void QueuePush(Queue* qp,QDataType x)//队列插入 { assert(qp); QNode *newnode = (QNode*)malloc(sizeof(QNode)); if (newnode == NULL) { perror("malloc fail\n"); exit(-1); } newnode->next = NULL; newnode->data = x; if (qp->head == NULL) { qp->head = qp->tail = newnode; } else { qp->tail->next = newnode; qp->tail = newnode; } } void QueuePop(Queue* qp)//队列删除 { assert(qp); assert(!QueueEmpty(qp)); if (qp->head->next == NULL) { qp->head = qp->tail = NULL; } else { QNode* next = qp->head->next; free(qp->head); qp->head = next; } } QDataType QueueFront(Queue* qp)//取出队列首元素 { assert(qp); assert(!QueueEmpty(qp)); return qp->head->data; } QDataType QueueBack(Queue* qp)//取出队列末尾元素 { assert(qp); assert(!QueueEmpty(qp)); return qp->tail->data; } bool QueueEmpty(Queue* qp)//判断队列是否为空 { assert(qp); return qp->head == NULL; } int QueueSize(Queue* qp)//返回队列的元素 { assert(qp); int size = 0; QNode* cur = qp->head; while (cur) { ++size; cur = cur->next; } return size; } typedef struct { Queue q1; Queue q2; } MyStack;//创建结构 MyStack* myStackCreate() //初始化,并返回一个结点 { MyStack* obj = (MyStack*)malloc(sizeof(MyStack)); 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* Empty = &obj->q1; Queue* NoEmpty = &obj->q2; if(!QueueEmpty(&obj->q1)) { Empty = &obj->q2; NoEmpty = &obj->q1; } while(QueueSize(NoEmpty)>1) { QueuePush(Empty,QueueFront(NoEmpty)); QueuePop(NoEmpty); } int top = QueueFront(NoEmpty); QueuePop(NoEmpty); 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); }
下面我们看下它的兄弟题目
我们是使用栈来模拟实现队列相关的操作,和上面的类似,我们也要有两个栈,但是我们不需要频繁的倒数据,我们创建一个Push栈,一个Pop栈,Push栈就插入数据,Pop栈就是出数据,如果Pop栈为空,那么我们就先Push栈中要数据,就是把Push栈的数据倒过来就好2了,其他和上面题类似。
入数据:
该出数据时:
在插入数据,删除数据
还是要先写一个栈,然后在进行操作。
队列的创建,初始化和销毁
typedef struct //初始化 { ST Pushst; ST Popst; } MyQueue; MyQueue* myQueueCreate() //初始化 { MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue)); StackInit(&obj->Pushst); StackInit(&obj->Popst); return obj; } void myQueueFree(MyQueue* obj)//销毁 { StackDestroy(&obj->Pushst); StackDestroy(&obj->Popst); free(obj); }
这些都和上面的类似不在赘述。
判断队列是否为空:
bool myQueueEmpty(MyQueue* obj) //判空 { return StackEmpty(&obj->Pushst) && StackEmpty(&obj->Popst); }
也是和上面类似,只有两个栈为空,队列才是空的。
队列的插入:
void myQueuePush(MyQueue* obj, int x)//插入 { StackPush(&obj->Pushst,x); }
队列的插入,只要插入Push栈就可以啦。
从队列的开头移除并返回元素:
int myQueuePop(MyQueue* obj)//从队列的开头移除并返回元素 { if(StackEmpty(&obj->Popst)) { while(!StackEmpty(&obj->Pushst)) { StackPush(&obj->Popst,StackTop(&obj->Pushst)); StackPop(&obj->Pushst); } } int top = StackTop(&obj->Popst); StackPop(&obj->Popst); return top; }
这个只需要判断Pop栈是否为空,如果为空就从Push栈倒数据,不为空就直接保存Pop栈的头元素,然后Pop掉,接着返回就好了。
返回队列开头元素:
int myQueuePeek(MyQueue* obj) { if(StackEmpty(&obj->Popst)) { while(!StackEmpty(&obj->Pushst)) { StackPush(&obj->Popst,StackTop(&obj->Pushst)); StackPop(&obj->Pushst); } } return StackTop(&obj->Popst); }
同上,比起上面的是我们不需要Pop栈顶元素,所以可以直接返回。
typedef int STDataType; typedef struct Stack { STDataType* a; int top; int capacity; }ST; void StackInit(ST* ps);//初始化 void StackDestroy(ST* ps);//销毁 void StackPush(ST* ps, STDataType x);//插入(入栈),栈的插入是尾插。 void StackPop(ST* ps);//删除(出栈),从尾部删除。 STDataType StackTop(ST* ps);//读出栈顶 bool StackEmpty(ST* ps);//判断栈是否为空 int StackSize(ST* ps);//栈中的元素个数 void StackInit(ST* ps)//初始化 { assert(ps); ps->a = NULL; ps->capacity = ps->top = 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->capacity == ps->top) { int NewCapaticy = ps->capacity == 0 ? 4 : ps->capacity * 2; STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType)*NewCapaticy); if (tmp == NULL) { perror("realoc fail\n"); exit(-1); } ps->a = tmp; ps->capacity = NewCapaticy; } ps->a[ps->top] = x; ps->top++; } void StackPop(ST* ps)//删除(出栈),从尾部删除。 { assert(ps); assert(!StackEmpty(ps)); ps->top--; } STDataType StackTop(ST* ps)//读出栈顶 { assert(ps); assert(!StackEmpty(ps)); return ps->a[ps->top-1]; } bool StackEmpty(ST* ps)//判断栈是否为空 { assert(ps); return ps->top == 0; } int StackSize(ST* ps)//栈中的元素个数 { assert(ps); return ps->top; } typedef struct //初始化 { ST Pushst; ST Popst; } MyQueue; MyQueue* myQueueCreate() { MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue)); StackInit(&obj->Pushst); StackInit(&obj->Popst); return obj; } void myQueuePush(MyQueue* obj, int x) { StackPush(&obj->Pushst,x); } int myQueuePop(MyQueue* obj) { if(StackEmpty(&obj->Popst)) { while(!StackEmpty(&obj->Pushst)) { StackPush(&obj->Popst,StackTop(&obj->Pushst)); StackPop(&obj->Pushst); } } int top = StackTop(&obj->Popst); StackPop(&obj->Popst); return top; } int myQueuePeek(MyQueue* obj) { 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) { return StackEmpty(&obj->Pushst) && StackEmpty(&obj->Popst); } void myQueueFree(MyQueue* obj)//销毁 { StackDestroy(&obj->Pushst); StackDestroy(&obj->Popst); free(obj); }
本期到这里结束啦,明天再见!