栈实现队列 & 队列实现栈

目录

栈与队列

两个栈实现一个队列结构

两个队列实现一个栈结构


                    

栈与队列

栈是一种“FILO”(先进后出)的数据结构

队列是一种“FIFO”(先进先出)的数据结构

     

有了以上信息后,我们就可以实现用栈来实现队列&用队列实现栈的操作了


两个栈实现一个队列结构

由于队列是先入先出的结构,而栈是先入后出的结构。

所以我们选择用两个栈,来使数据形成一个翻转

这样翻转后的结构,便可以轻松用pop出掉最先进来的元素。

当stack2中的元素pop完时,我们就再进行一个翻转,将所有压进stack1的元素再次翻转到stack2中,便又可以进行出栈了。

所以我们就需要一个变量来判断栈是否为空。以下在定义结构体时,增加了一个整形size变量,来记录栈内的元素个数。

而push就是正常的入栈,一个劲往stack1中入就行。

如下是代码实现

typedef struct Stack{
struct Stack*next;
struct Stack*tail;
int size;//这里设置size来判断该栈是否为空
int data;
}MyStack;

typedef struct {
MyStack*q1;
MyStack*q2;
}MyQueue;

/*创建队列*/
MyQueue* myQueueCreate() {
MyQueue*Queue=(MyQueue*)malloc(sizeof(MyQueue));
Queue->q1=(MyStack*)malloc(sizeof(MyStack));//创建哨兵位
Queue->q2=(MyStack*)malloc(sizeof(MyStack));
Queue->q1->next=NULL;//初始化栈
Queue->q2->next=NULL;
Queue->q1->tail=NULL;
Queue->q2->tail=NULL;
Queue->q1->size=0;
Queue->q2->size=0;
Queue->q1->data=0;
Queue->q2->data=0;
return Queue;
}

/*尾插队列*/
void myQueuePush(MyQueue* obj, int x) {
assert(obj);
MyStack*newnode=(MyStack*)malloc(sizeof(MyStack));//开辟新结点
newnode->data=x;
newnode->next=NULL;
MyStack*cur=obj->q1->size==0?obj->q1:obj->q1->tail;
obj->q1->tail=newnode;//链接新结点
cur->next=obj->q1->tail;
obj->q1->size++;
}

void StackMove(MyStack*sorc,MyStack*dest){
while(sorc->size)
{
    MyStack*curq1=sorc;
    MyStack*curq2=dest;
    while(curq1->next!=sorc->tail)
    {
        curq1=curq1->next;
    }
curq1->next=NULL;
curq2=dest->size==0?dest:dest->tail;
dest->tail=sorc->tail;
curq2->next=dest->tail;
dest->size++;
sorc->tail=curq1;
sorc->size--;
}
}

/*头删队列*/
int myQueuePop(MyQueue* obj) {
assert(obj);
assert(obj->q1->size || obj->q2->size);
if(obj->q2->size==0)
{
    StackMove(obj->q1,obj->q2);
}
MyStack*cur=obj->q2;
while(cur->next!=obj->q2->tail)
{
    cur=cur->next;
}
int ret=obj->q2->tail->data;
free(obj->q2->tail);
cur->next=NULL;
obj->q2->tail=cur;
obj->q2->size--;
return ret;
}

/*返回队列开头元素*/
int myQueuePeek(MyQueue* obj) {
assert(obj);
assert(obj->q1->size || obj->q2->size);
if(obj->q2->size==0)
{
    return obj->q1->next->data;
}
else
return obj->q2->tail->data;
}

/*判空*/
bool myQueueEmpty(MyQueue* obj) {
if(obj->q1->size || obj->q2->size)
{
    return false;
}
return true;
}

/*释放空间*/
void myQueueFree(MyQueue* obj) {
assert(obj);
StackMove(obj->q1,obj->q2);
free(obj->q1);
MyStack*cur=obj->q2->next;
MyStack*node=obj->q2->next;
while(cur)
{
    cur=cur->next;
    free(node);
    node=cur;
    obj->q2->size--;
}
free(obj->q2);
free(obj);
}

        


两个队列实现一个栈结构

我们选用两个队列,实现一个”无用数据”的”转移“ 。

我们有两个队列,一个空,一个非空。

出队列:将非空队列的n-1个元素入到空队列中,剩下一个没有移动的元素直接从原队列头删。

入队列:只向非空队列入数据

因此,实现该功能的核心内容是判断空与非空队列并进行元素转移

实现代码如下:

typedef struct Queue
{
struct Queue*next;
int data;
int size;
}Queue;

typedef struct {
Queue*q1;
Queue*q2;
} MyStack;

/*创建结构体*/
MyStack* myStackCreate() {
MyStack*Stack=(MyStack*)malloc(sizeof(MyStack));//开辟含有两个队列的结构体

Stack->q1=(Queue*)malloc(sizeof(Queue));//开辟第一个结构体,并初始化,附加哨兵位
Stack->q1->next=NULL;
Stack->q1->data=0;
Stack->q1->size=0;

Stack->q2=(Queue*)malloc(sizeof(Queue));//开辟第二个结构体,并初始化,附加哨兵位
Stack->q2->next=NULL;
Stack->q2->data=0;
Stack->q2->size=0;
return Stack;//返回开辟含有队列的结构体的指针
}

/*存放数据*/
void myStackPush(MyStack* obj, int x) {
    assert(obj); //判断stack是否为空
    Queue* newnode=(Queue*)malloc(sizeof(Queue));//创建要尾插的新结点,并赋值该结点
    newnode->data=x;
    newnode->next=NULL;
    Queue* notemptynode=NULL;//判断q1,q2哪个是非空链表,若都为空则默认q1
    if(obj->q2->size!=0)
    {
        notemptynode=obj->q2;
    }
    else
    {
        notemptynode=obj->q1;
    }
    Queue*cur=notemptynode;
    while(cur->next)//找尾
    {
        cur=cur->next;
    }
    cur->next=newnode;//链接尾结点和新结点
    notemptynode->size++;
}


/*将第一个队列的值转移到第二个队列中*/
void myStackMove(Queue*notemptynode,Queue*emptynode,int count)
{
    if(notemptynode->size!=1)
    {
    emptynode->next=notemptynode->next;
    }
    Queue*cur=notemptynode->next;
    Queue*tailnode=notemptynode->next;
    while(--count)//留下一个值,用来pop;  找尾
    {
        cur=tailnode;
        tailnode=tailnode->next;
        notemptynode->size--;
        emptynode->size++;
    }
    notemptynode->size--;
    notemptynode->next=tailnode;
    cur->next=NULL;
}


/*出队列*/
int myStackPop(MyStack* obj) {
    assert(obj->q1->next||obj->q2->next);
Queue*emptynode=obj->q2;
Queue*notemptynode=obj->q1;
if(obj->q1->size==0)//判断谁是空队列
{
    emptynode=obj->q1;
    notemptynode=obj->q2;
}
int count=notemptynode->size;//计算非空队列长度,用来下一步转移数据
myStackMove(notemptynode,emptynode,count);   //转移队列数据,留下一个用来pop
int cur=notemptynode->next->data;//保存要pop的结点的值
free(notemptynode->next);//释放pop的结点
notemptynode->next=NULL;
return cur;
}

/*返回栈顶元素*/
int myStackTop(MyStack* obj) {
    assert(obj->q1->size||obj->q2->size);//确保两个队列其中一个有数据
    Queue*cur=NULL;
if(obj->q1->size!=0)
{
    cur=obj->q1;
    while(cur->next)
    {
        cur=cur->next;
    }
}
else
{
    cur=obj->q2;
    while(cur->next)
    {
        cur=cur->next;
    }
}
return cur->data;
}


/*判断两队列是否都为空*/
bool myStackEmpty(MyStack* obj) {
if(obj->q1->size==0 && obj->q2->size==0)
{
    return true;
}
else
return false;
}

/*释放内存*/
void myStackFree(MyStack* obj) {
assert(obj);
Queue*cur1=obj->q1;
Queue*cur2=obj->q2;
while(cur1)
{
    cur1=cur1->next;
    free(obj->q1);
    obj->q1=cur1;
}
while(cur2)
{
    cur2=cur2->next;
    free(obj->q2);
    obj->q2=cur2;
}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值