用两个队列来实现栈
我们知道队列和栈的出数据是完全逆置的关系,那么如何用两个队列来实现栈呢?
肯定要将数据在两个队列里面来回增换,那么我们就在其中某个时刻进行操作就可以完成要求了。
首先我们定义两个队列分别为A和B两个队列。数据可以拟定为
以队列来看(begain)1 2 3 4 5(tail)
以栈来看 (begain)5 4 3 2 1(tail)
在此之前,我们要先写一遍队列的代码。好在写模拟栈时可以更好的利用这些函数来节省时间。
队列实现
typedef int type;
typedef struct queuenode {
type data;
struct queuenode* next;
}queuenode;
typedef struct queue {
queuenode* beagain;
queuenode* tail;
}queue;
queue* queue_init() {
queue* qu = (queue*)malloc(sizeof(queue));
assert(qu);
qu->beagain = qu->tail = NULL;
return qu;
}
void queue_push(queue* q, type x) {
if (!q)return;
//新增节点的创建,判空和初始化
queuenode* cur = (queuenode*)malloc(sizeof(queuenode));
assert(cur);
cur->next = NULL;
cur->data = x;
//插入新节点
if (!q->beagain) {
q->beagain = q->tail = cur;
}
else {
q->tail->next = cur;
q->tail = q->tail->next;
}
}
void queue_pop(queue* q) {
if (!q)return;
if (!q->beagain->next) {
free(q->beagain);
q->beagain = q->tail = NULL;
return;
}
else {
queuenode* newhead = q->beagain->next;
free(q->beagain);
q->beagain = newhead;
}
}
type queue_top(queue* q) {
if (!q || !q->beagain)return;
return q->beagain->data;
}
bool queue_empty(queue* q) {
return !q || !q->beagain;
}
void queue_free(queue* q) {
if (!queue_empty(q)) {
if (!q->beagain->next) {
free(q->beagain);
free(q);
}
else {
queuenode* pnewptr = q->beagain, * newptr = pnewptr->next;
while (newptr) {
free(pnewptr);
pnewptr = newptr;
newptr = newptr->next;
}
free(pnewptr);
free(q);
}
}
}
如果是c++同学的话,直接用stl就行了。
Pop
我们向A里面push足够的数据后,在pop出给B和我们直接将这组数据push给B是一个道理。那么唯一不同的是,我们可以在A只剩最后一个数据的时候,删除这个数据不push给B,那么刚好就删除了模拟栈的最上面的数据。最后只有数据 1 2 3 4
那么这一个操作就完成了栈的pop
这个函数是最难的:
int myStackPop(MyStack* obj) {
if (myStackEmpty(obj))return EOF;
queue* empty = obj->a, * nonempty = obj->b;
if (queue_empty(nonempty)) {
empty = obj->b;
nonempty = obj->a;
}//同上
while (nonempty->beagain != nonempty->tail) {//当只有一个数据的时候就停止循环
queue_push(empty, queue_top(nonempty));//将数据push到另一个队列里面
queue_pop(nonempty);
}
int k = queue_top(nonempty);//删除并释放
queue_pop(nonempty);
return k;
}
Push
如果是栈的push,我们直接将数据插入到队列的尾部就行了。void myStackPush(MyStack* obj, type data) {
queue* empty = obj->a, * nonempty = obj->b;
if (queue_empty(nonempty)) {
empty = obj->b;
nonempty = obj->a;
}//用假设法来确定那个为空的队列,哪个为非空的队列
queue_push(nonempty, data);
}
Top
这个函数是返回栈开头的数据
那么只要返回队列末尾的数据就行了int myStackTop(MyStack* obj) {
if (myStackEmpty(obj))return;
queue* empty = obj->a, * nonempty = obj->b;
if (queue_empty(nonempty)) {
empty = obj->b;
nonempty = obj->a;
}
return nonempty->tail->data;
}
Empty
这个函数是判断栈是否为空,我们只要看两个队列是否为空就行了
bool myStackEmpty(MyStack* obj) {
return queue_empty(obj->a) && queue_empty(obj->b);
}
Free
释放栈的内存,我们只要释放两个队列的内存就行了。也就是两个链表的释放,当然还有一些结构体的内存释放。
void myStackFree(MyStack* obj) {
free(obj->a);
free(obj->b);
free(obj);
}
放到力扣里面CV一下(225题)
用两个栈来实现队列
这个相对来说比较好理解,把一个栈倒过来就是一个队列了,那么我们只要创建两个栈A,B,将数据存到A里面,然后push给B就是队列了,如果我们还要进行栈的push,那么只要再将B的数据倒回A进行push就行了了。另外我们也可以不用倒回给A,我们可以等B里面的数据pop完后再让A的数据给B,这样也可以。其中第二种是更好的。
那么在此之前我们将栈实现一下:
栈的实现
typedef int type;
typedef struct stack {
type* arr;
int size;
int capacity;
}stack;
stack* stack_init() {
stack* s = (stack*)malloc(sizeof(stack));
if (!s)return NULL;
s->arr = (type*)malloc(sizeof(type));
s->capacity = s->size = 0;
return s;
}
void stack_push(stack* s, type x) {
if (s->capacity==s->size) {
int newsize = s->capacity == 0 ? 4 : s->capacity * 2;
type *newarr= (type*)realloc(s->arr,newsize*sizeof(type));
if (!newarr)return;
else {
s->arr = newarr;
s->capacity = newsize;
}
}
s->arr[s->size++] = x;
}
type stack_top(stack* s) {
if (!s->arr)return EOF;
return s->arr[s->size - 1];
}
void stack_pop(stack* s) {
if (!s->arr)return;
s->size--;
}
bool stack_empty(stack* s) {
return !s->arr||!s->size;
}
void stack_free(stack* s) {
free(s->arr);
free(s);
}
int main() {
stack* s = stack_init();
stack_push(s, 1);
stack_push(s, 2);
stack_push(s, 3);
stack_push(s, 4);
stack_push(s, 5);
stack_push(s, 6);
while (!stack_empty(s)) {
printf("%d ", stack_top(s));
stack_pop(s);
}
return 0;
}
如果是CPP的同学,或者java的同学可以直接套用模板。
下面是两个栈来实现队列:
Pop
int myQueuePop(MyQueue* obj) {
if (myQueueEmpty(obj))return EOF;
if (stack_empty(obj->pb)) {
int size = obj->pa->size;
for (int x = 0; x < size; ++x) {
stack_push(obj->pb, stack_top(obj->pa));
stack_pop(obj->pa);
}
}
int k = stack_top(obj->pb);
stack_pop(obj->pb);
return k;
}
Push
void myQueuePush(MyQueue* obj, int x) {
//我们假设A为栈的push模拟,B是栈的pop模拟
stack_push(obj->pa,x);
}
Top
int myQueuePeek(MyQueue* obj) {
if (myQueueEmpty(obj))return EOF;
if (stack_empty(obj->pb)) {
int size = obj->pa->size;
for (int x = 0; x < size; ++x) {
stack_push(obj->pb, stack_top(obj->pa));
stack_pop(obj->pa);
}
}
return stack_top(obj->pb);
}
Empty
bool myQueueEmpty(MyQueue* obj) {
return stack_empty(obj->pa) && stack_empty(obj->pb);
}
Free
void myQueueFree(MyQueue* obj) {
stack_free(obj->pa);
stack_free(obj->pb);
free(obj);
}
放力扣里面过一下(232题)