前两天实现了栈和队列,现在做两道经典的例题来巩固所学的知识。
题目链接:
目录
一、用栈实现队列
思路:
①构建两个栈实现队列。一个栈为input栈,只存入数据;一个栈为output栈,只负责出数据。
②当出数据时,先判断output栈是否为空(StackEmpty(&output)),如果为空,要把input栈中的数据全部导入到output栈中,然后再出output栈顶元素,再删除一个output栈中的数据。
这时我们来分析为什么要让output为空时才倒数据。
注意了!栈是先进后出哦!只有当output为空的时候才能倒数据,要不然后插入的数据会将出栈的顺序打乱。
因为我们是使用C语言做这道题,我们要自己创建栈,这点是比较麻烦的,好在是前两天我们实现了一个栈,直接拿来使用即可。
源码较长,我放在最后,可以通过目录跳转。
二、用队列实现栈
思路:
①一个队列存放输入的数据,一个队列专门为空,在出数据时用于保存数据。这两个队列每出一次数据时会进行功能的倒换。
②出数据时,要将存数据的队列中数据导入到空队列中,直到只留下一个数据。然后将此数据输出,如果是Pop型,输出后则将数据删除,如果是Top型,则将数据输出后再插入到倒数据队列。
步骤:
一、插入数据
如果q1为空,则q1是用于倒数据的队列,所以放入q2,反之亦然,q2为空放数据插入q1。
二、取数据
1.将除了最后一个数据之外的剩下数据全部导入到倒数据队列,然后将剩下这最后一个数据输出。
2.如果要求是Pop型,输出后则将该数据删除;如果是Top型,则将数据输出后再插入到倒数据队列。
三、源码
因为C语言没有这些结构的库,我们只能手搓出栈和队列,好在前两天我们实现过栈和队列,这时我们直接将其拷贝过来然后套用既可,所以代码有点多。
3.1 栈-->队列 源码
#include <stdio.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
typedef int STDateType;
typedef struct Stack
{
STDateType* a;
int top; //标识栈顶的数据
int capacity; //动态性的 可以扩容
}ST;
void StackInit(ST* ps);
void StackDestory(ST* ps);
void StackPush(ST* ps, STDateType x);
void StackPop(ST* ps);
STDateType StackTop(ST* ps); //取栈顶的元素
bool StackEmpty(ST* ps); //判断栈是否为空
int StackSize(ST* ps); //得知栈的大小
void StackInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
void StackDestory(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
void StackPush(ST* ps, STDateType x)
{
assert(ps);
if (ps->capacity == ps->top)
{
int NewCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDateType* temp = (STDateType * )realloc(ps->a, sizeof(STDateType) * NewCapacity);
if (temp == NULL)
{
printf("realloc fail");
exit(-1);
}
ps->a = temp;
ps->capacity = NewCapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
STDateType 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 input; //input栈
ST output; //output栈
} MyQueue;
//将队列创建好 并返回
MyQueue* myQueueCreate() {
//开辟一个结构体变量的空间
//表示我们自己创建的结构体 MyQueue
MyQueue* obj =(MyQueue*)malloc(sizeof(MyQueue));
//注意,在创建一个MyQueue中,我们是创建了一个栈,如果我们调用了栈的函数,是需要将该栈的地址传入函数才能符合其类型
StackInit(&obj->input);
StackInit(&obj->output);
return obj;
}
void myQueuePush(MyQueue* obj, int x) {
//将数据放入input栈
StackPush(&obj->input,x);
}
int myQueuePop(MyQueue* obj) {
//将数据弹出
//如果output空,则表示出数据栈为空,则要导数据
if(StackEmpty(&obj->output))
{
//直到input为空
while(!StackEmpty(&obj->input))
{
//将input的数据放入output
//插入一个 Pop一个
StackPush(&obj->output,StackTop(&obj->input));
StackPop(&obj->input);
}
}
int ret=StackTop(&obj->output);
StackPop(&obj->output);
return ret;
}
bool myQueueEmpty(MyQueue* obj) {
//两个栈为空,即队列为空
return (StackEmpty(&obj->input)&& StackEmpty(&obj->output));
}
int myQueuePeek(MyQueue* obj) {
//如果队列为空
if (myQueueEmpty(obj))
{
return -1;
}
if(StackEmpty(&obj->output))
{
while(!StackEmpty(&obj->input))
{
//将input的数据放入output
StackPush(&obj->output,StackTop(&obj->input));
StackPop(&obj->input);
}
}
return StackTop(&obj->output);
}
void myQueueFree(MyQueue* obj) {
StackDestory(&obj->input);
StackDestory(&obj->output);
free(obj);
}
3.2 队列-->栈 源码
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
}Queue;
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
}
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* Dest = pq->head;
while (Dest)
{
QNode* temp = Dest->next;
free(Dest);
Dest = temp;
}
pq->head = pq->tail = NULL;
}
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
//创建一个节点
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
//判断pq是不是一个空结点
//如果是 则将newnode置为当前队列的第一个结点
//如果不是 则将newnode链接到pq的下一个位置
if (pq->tail == NULL)
{ //两个节点都指向newnode 表示此时队列中就一个元素
pq->head = pq->tail = newnode;
}
else
{
//1.将newnode链接到tail的后面
pq->tail->next = newnode;
//2.将newnode置换为新的tail
pq->tail = newnode;
}
}
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL;
}
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
//额外判断一下,解决如果仅剩一个结点了,pop的话导致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;
}
}
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
QDataType QueueBck(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail ->data;
}
int QueueSize(Queue *pq)
{
assert(pq);
int count = 0;
QNode* cur = pq->head;
while (cur)
{
cur = cur->next;
count++;
}
return count;
}
typedef struct {
Queue q1; //队列1
Queue q2; //队列2
} MyStack;
MyStack* myStackCreate() {
MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
if (obj == NULL)
{
return 0;
}
//初始化这两个队列
QueueInit(&obj->q1);
QueueInit(&obj->q2);
return obj;
}
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}
void myStackPush(MyStack* obj, int x) {
//如果q1为空,则往q2里放数据
if (QueueEmpty(&obj->q1))
{
QueuePush(&obj->q2, x);
}
else
{
QueuePush(&obj->q1, x);
}
}
int myStackPop(MyStack* obj) {
//如果q1为空,就要从q2往q1里导数据
if (QueueEmpty(&obj->q1))
{
while (!((&obj->q2)->head->next == NULL))
{
QueuePush(&obj->q1, QueueFront(&obj->q2));
QueuePop(&obj->q2);
}
int ret = QueueFront(&obj->q2);
QueuePop(&obj->q2);
return ret;
}
else
{
while (!((&obj->q1)->head->next == NULL))
{
QueuePush(&obj->q2, QueueFront(&obj->q1));
QueuePop(&obj->q1);
}
int ret = QueueFront(&obj->q1);
QueuePop(&obj->q1);
return ret;
}
}
int myStackTop(MyStack* obj) {
//如果q1为空,则是存放除栈顶数据的位置
if (QueueEmpty(&obj->q1))
{
while (!((&obj->q2)->head->next == NULL))
{
QueuePush(&obj->q1, QueueFront(&obj->q2));
QueuePop(&obj->q2);
}
int ret = QueueFront(&obj->q2);
QueuePush(&obj->q1,ret);
QueuePop(&obj->q2);
return ret;
}
else
{
while (!((&obj->q1)->head->next == NULL))
{
QueuePush(&obj->q2, QueueFront(&obj->q1));
QueuePop(&obj->q1);
}
int ret = QueueFront(&obj->q1);
QueuePush(&obj->q2,ret);
QueuePop(&obj->q1);
return ret;
}
}
void myStackFree(MyStack* obj) {
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}