栈和队列用对方来实现自己

用两个队列来实现栈

我们知道队列和栈的出数据是完全逆置的关系,那么如何用两个队列来实现栈呢?

肯定要将数据在两个队列里面来回增换,那么我们就在其中某个时刻进行操作就可以完成要求了。

首先我们定义两个队列分别为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题)

  • 41
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值