- 用队列实现栈
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
代码如下
#define LEN 20
typedef struct queue {
int *data;
int head;
int rear;
int size;
} Queue;
typedef struct {
Queue *queue1, *queue2;
} MyStack;
Queue *initQueue(int k) {
Queue *obj = (Queue *)malloc(sizeof(Queue));
obj->data = (int *)malloc(k * sizeof(int));
obj->head = -1;
obj->rear = -1;
obj->size = k;
return obj;
}
void enQueue(Queue *obj, int e) {
if (obj->head == -1) {
obj->head = 0;
}
obj->rear = (obj->rear + 1) % obj->size;
obj->data[obj->rear] = e;
}
int deQueue(Queue *obj) {
int a = obj->data[obj->head];
if (obj->head == obj->rear) {
obj->rear = -1;
obj->head = -1;
return a;
}
obj->head = (obj->head + 1) % obj->size;
return a;
}
int isEmpty(Queue *obj) {
return obj->head == -1;
}
MyStack *myStackCreate() {
MyStack *obj = (MyStack *)malloc(sizeof(MyStack));
obj->queue1 = initQueue(LEN);
obj->queue2 = initQueue(LEN);
return obj;
}
void myStackPush(MyStack *obj, int x) {
if (isEmpty(obj->queue1)) {
enQueue(obj->queue2, x);
} else {
enQueue(obj->queue1, x);
}
}
int myStackPop(MyStack *obj) {
if (isEmpty(obj->queue1)) {
while (obj->queue2->head != obj->queue2->rear) {
enQueue(obj->queue1, deQueue(obj->queue2));
}
return deQueue(obj->queue2);
}
while (obj->queue1->head != obj->queue1->rear) {
enQueue(obj->queue2, deQueue(obj->queue1));
}
return deQueue(obj->queue1);
}
int myStackTop(MyStack *obj) {
if (isEmpty(obj->queue1)) {
return obj->queue2->data[obj->queue2->rear];
}
return obj->queue1->data[obj->queue1->rear];
}
bool myStackEmpty(MyStack *obj) {
if (obj->queue1->head == -1 && obj->queue2->head == -1) {
return true;
}
return false;
}
void myStackFree(MyStack *obj) {
free(obj->queue1->data);
obj->queue1->data = NULL;
free(obj->queue1);
obj->queue1 = NULL;
free(obj->queue2->data);
obj->queue2->data = NULL;
free(obj->queue2);
obj->queue2 = NULL;
free(obj);
obj = NULL;
}解释如下
以下是对这段代码的详细解释:
1. 宏定义和结构体定义
#define LEN 20这行代码定义了一个宏 LEN,其值为 20。在后续代码中,这个宏可以被用来表示一个固定的长度值,例如用于初始化队列的容量等,通过使用宏可以方便地在一处修改这个长度值,而不需要在多处代码中逐个修改具体的数字。
typedef struct queue {
int *data;
int head;
int rear;
int size;
} Queue;这里定义了一个名为 Queue 的结构体。结构体中包含以下成员:
int *data:一个指向整数类型的指针,用于存储队列中的数据元素。int head:表示队列头部的索引,用于标记队列头部元素的位置。int rear:表示队列尾部的索引,用于标记队列尾部元素的位置。int size:表示队列的容量大小,即可以存储的元素个数。
typedef struct {
Queue *queue1, *queue2;
} MyStack;定义了一个名为 MyStack 的结构体,它包含两个指向 Queue 结构体的指针 queue1 和 queue2。这个结构体将用于实现一个栈的数据结构,通过两个队列来模拟栈的操作。
2. 队列相关操作函数
2.1 initQueue 函数
Queue *initQueue(int k) {
Queue *obj = (Queue *)malloc(sizeof(Queue));
obj->data = (int *)malloc(k * sizeof(int));
obj->head = -1;
obj->rear = -1;
obj->size = k;
return obj;
}这个函数用于初始化一个队列。它接受一个整数参数 k,用于指定队列的容量大小。函数内部的操作如下:
- 首先,通过
malloc函数动态分配内存来创建一个Queue结构体对象,并将其指针赋值给obj。 - 然后,再次使用
malloc函数为队列的数据存储区域(data指针所指向的区域)分配足够的内存空间,以存储k个整数类型的数据元素。 - 接着,将队列的头部索引
head和尾部索引rear都初始化为-1,表示队列初始为空。 - 最后,将队列的容量大小
size设置为传入的参数k,并返回初始化好的队列对象指针obj。
2.2 enQueue 函数
void enQueue(Queue *obj, int e) {
if (obj->head == -1) {
obj->head = 0;
}
obj->rear = (obj->rear + 1) % obj->size;
obj->data[obj->rear] = e;
}该函数用于向队列中插入一个元素。它接受一个指向 Queue 结构体的指针 obj 和一个整数元素 e 作为参数。具体操作如下:
- 首先,如果队列的头部索引
head为-1,说明队列当前为空,那么将头部索引head设置为0,表示队列即将插入第一个元素。 - 然后,通过
(obj->rear + 1) % obj->size的方式计算新的尾部索引rear。这种取模运算的方式实现了循环队列的效果,当队列尾部到达数组末尾时,会自动循环回到数组开头继续插入元素。 - 最后,将传入的元素
e存储到队列数据数组中由新的尾部索引rear所指向的位置。
2.3 deQueue 函数
int deQueue(Queue *obj) {
int a = obj->data[obj->head];
if (obj->head == obj->rear) {
obj->rear = -1;
obj->head = -1;
return a;
}
obj->head = (obj->head + 1) % obj->size;
return a;
}这个函数用于从队列中删除并返回头部的元素。它接受一个指向 Queue 结构体的指针 obj 作为参数。操作步骤如下:
- 首先,取出队列头部索引
head所指向的数据元素,并将其存储到变量a中。 - 然后,判断如果队列的头部索引
head和尾部索引rear相等,说明队列中只剩下一个元素,此时将头部索引head和尾部索引rear都重新设置为-1,表示队列再次变为空。 - 否则,如果队列中还有多个元素,就通过
(obj->head + 1) % obj->size的方式更新头部索引head,使其指向下一个元素,实现删除头部元素的效果。 - 最后,返回之前取出的头部元素
a。
2.4 isEmpty 函数
int isEmpty(Queue *obj) {
return obj->head == -1;
}这个函数用于判断队列是否为空。它接受一个指向 Queue 结构体的指针 obj 作为参数,通过检查队列的头部索引 head 是否为 -1 来判断队列是否为空,如果 head 为 -1,则表示队列中没有元素,函数返回 1(在C语言中,非零值表示真),否则返回 0(表示假)。
3. 栈相关操作函数
3.1 myStackCreate 函数
MyStack *myStackCreate() {
MyStack *obj = (MyStack *)malloc(sizeof(MyStack));
obj->queue1 = initQueue(LEN);
obj->queue2 = initQueue(LEN);
return obj;
}这个函数用于创建一个模拟栈的数据结构对象。它首先通过 malloc 函数动态分配内存来创建一个 MyStack 结构体对象,并将其指针赋值给 obj。然后,分别调用 initQueue 函数初始化 obj 结构体中的两个队列 queue1 和 queue2,并将它们的指针赋值给对应的成员变量。最后,返回创建好的模拟栈对象指针 obj。
3.2 myStackPush 函数
void myStackPush(MyStack *obj, int x) {
if (isEmpty(obj->queue1)) {
enQueue(obj->queue2, x);
} else {
enQueue(obj->queue2, x);
}
}该函数用于向模拟栈中压入一个元素。它接受一个指向 MyStack 结构体的指针 obj 和一个整数元素 x 作为参数。函数通过检查 obj 结构体中的队列 queue1 是否为空来决定将元素压入哪个队列。如果 queue1 为空,就将元素 x 压入队列 queue2;否则,将元素 x 压入队列 queue1。
3.3 myStackPop 函数
int myStackPop(MyStack *obj) {
if (isEmpty(obj->queue1)) {
while (obj->queue2->head!= obj->queue2->rear) {
enQueue(obj->queue1, deQueue(obj->queue2));
}
return deQueue(obj->queue2);
}
while (obj->queue1->head!= obj->queue1->rear) {
enQueue(obj->queue2, deQueue(obj->queue1));
}
return deQueue(obj->queue1);
}这个函数用于从模拟栈中弹出一个元素。它接受一个指向 MyStack 结构体的指针 obj 作为参数。函数首先判断队列 queue1 是否为空,如果为空,则将队列 queue2 中的元素除了最后一个之外全部转移到队列 queue1 中,然后弹出队列 queue2 的最后一个元素并返回;如果队列 queue1 不为空,则将队列 queue1 中的元素除了最后一个之外全部转移到队列 queue2 中,然后弹出队列 queue1 的最后一个元素并返回。通过这种方式实现了模拟栈的弹出操作,使得每次弹出的元素都是最后压入的元素。
3.4 myStackTop 函数
int myStackTop(MyStack *obj) {
if (isEmpty(obj->queue1)) {
return obj->queue2->data[obj->queue2->rear];
}
return obj->queue1->data[obj->queue1->rear];
}该函数用于获取模拟栈的栈顶元素。它接受一个指向 MyStack 结构体的指针 obj 作为参数。函数通过检查队列 queue1 是否为空来决定返回哪个队列的尾部元素作为栈顶元素。如果 queue1 为空,则返回队列 queue2 的尾部元素;否则,返回队列 queue1 的尾部元素。
3.5 myStackEmpty 函数
bool myStackEmpty(MyStack *obj) {
if (obj->queue1->head == -1 && obj->queue2->head == -1) {
return true;
}
return false;
}这个函数用于判断模拟栈是否为空。它接受一个指向 MyStack 结构体的指针 obj 作为参数。通过检查 obj 结构体中的两个队列 queue1 和 queue2 的头部索引是否都为 -1 来判断模拟栈是否为空。如果两个队列的头部索引都为 -1,则表示模拟栈中没有元素,函数返回 true;否则,返回 false。
3.6 myStackFree 函数
void myStackFree(MyStack *obj) {
free(obj->queue1->data);
obj->queue1->data = NULL;
free(obj->queue1);
obj->queue1 = NULL;
free(obj->queue2->data);
obj->queue2->data = NULL;
free(obj->queue2);
obj->queue2 = NULL;
free(obj);
obj = NULL;
}这个函数用于释放模拟栈所占用的内存资源。它接受一个指向 MyStack 结构体的指针 obj 作为参数。函数首先释放两个队列 queue1 和 queue2 中数据存储区域的内存,然后将对应的 data 指针设置为 NULL,以避免悬空指针。接着,释放两个队列结构体本身的内存,并将队列指针设置为 NULL。最后,释放模拟栈结构体 MyStack 本身的内存,并将模拟栈指针 obj 设置为 NULL,确保所有相关内存都被正确释放,防止内存泄漏。
2 条评论
哥哥~~~可以教一下我吗,不知道姐姐会不会生气呀,千万不要影响你和姐姐的关系呀
{!{data:image/webp;base64,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}!}