栈与队列例题解析c语言版(提高篇)

本文介绍如何通过两个队列实现栈的功能,并利用两个栈实现队列的功能。通过具体的代码实现展示了这两种数据结构间的转换方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.用队列实现栈。力扣

先明确一下队列和栈的性质:

队列:先进先出;栈:后进先出。

再实现一下队列的基本函数接口(这里选用链表队列):

这里再次实现链表队列是因为对于仍给一个队列可能是链表实现的也可能是顺序表实现的,这无法确定,但是使用队列的人可以通过调用这些函数实现他们想要的功能,从而忽略具体的不重要的这些操作的实现。

typedef int QNDataType;
//定义队列节点
typedef struct QueueNode
{
    QNDataType a;
    struct QueueNode*next;
}QN;
//定义两个指针的结构体维护队列
typedef struct Queue
{
    QN*front;
    QN*rear;
}QL;
//初始化
void QLInit(QL*pq)
{
    assert(pq);
    pq->front = NULL;
    pq->rear = NULL;
}
//销毁
void QLDestory (QL*pq)
{
    assert(pq);
    QN*cur = pq->front;
    while(cur)
    {
        QN*next = cur->next;
        free(cur);
        cur = next;
    }
    pq->front = pq->rear = NULL;
}
//入队
void QLPush(QL*pq,QNDataType x)
{
    assert(pq);
    QN*newnode = (QN*)malloc(sizeof(QN));
    assert(newnode);
    newnode->a = x;
    newnode->next = NULL;
    if(pq->front == NULL)
    {
        pq->front = pq->rear = newnode;
    }
    else
    {
        pq->rear->next = newnode;
        pq->rear = newnode;
    }
}
//出队
void QLPop(QL*pq)
{
    assert(pq);
    assert(pq->front);
    QN*next = pq->front->next;
    free(pq->front);
    pq->front = next;
    if(pq->front==NULL)
    {
        pq->rear = NULL;
    }
}
//计算队列的元素个数
int QLSize(QL*pq)
{
    assert(pq);
    QN*cur = pq->front;
    int num = 0;
    while(cur)
    {
        num++;
        cur = cur->next;
    }
    return num;
}
//返回队列的队首值
QNDataType QLFront(QL*pq)
{
    assert(pq);
    assert(pq->front);
    return pq->front->a;
}
//返回队列的队尾值
QNDataType QLRear(QL*pq)
{
    assert(pq);
    assert(pq->rear);
    return pq->rear->a;
}
//判断队列是不是为空
bool QLEmpity(QL*pq)
{
    assert(pq);
    return pq->front==NULL;
}

下面进入本题:

typedef struct {

} MyStack;

这一步中可以选择创建结构体:

typedef struct {

    QL q1;

    QL q2;

} MyStack;

也可以选择创建指针: 

typedef struct {

    QL *q1;

    QL *q2;

} MyStack;

区别在于下面的函数调用时传的参数不同,以MyStack* myStackCreate() {}为例 看一看两种实现的方法:

定义结构体,对结构体的初始化要传递(&obj->q1),因为在队列的功能接口中参数时地址,而且也只有传地址才可以改变结构体的内容。

定义结构体指针,对结构体指针的初始化之前还要动态开辟一块空间,因为当MyStack被开辟的时候里面的指针是指向随机的一块地方,所以还要对队列指针动态开辟一块空间,然后初始化,传递obj->q1即可。

//定义结构体:

typedef struct {

    QL q1;

    QL q2;

} MyStack;

MyStack* myStackCreate() {

    MyStack*obj = (MyStack*)malloc(sizeof(MyStack));

    QLInit(&obj->q1);

    QLInit(&obj->q2);

    return obj;

}

//定义指针

typedef struct {

    QL* q1;

    QL* q2;

} MyStack;

MyStack* myStackCreate() {

    MyStack*obj = (MyStack*)malloc(sizeof(MyStack));

    obj->q1 = (QL*)malloc(sizeof(QL));

    obj->q2 = (QL*)malloc(sizeof(QL));

    QLInit(obj->q1);

    QLInit(obj->q2);

    return obj;

}

本文采用创立队列结构体的方法。

void myStackPush(MyStack* obj, int x) {

    assert(obj);

// 如果有一个队列不是空的就把元素入队,建立两个结构体变量就可以解决

    QL*noempity = &obj->q1,*empity = &obj->q2;

    if(QLEmpity(&obj->q1))

    {

        noempity = &obj->q2;

        empity = &obj->q1;

    }

    QLPush(noempity,x);

}

int myStackPop(MyStack* obj) {

     assert(obj);

//先找到非空的那个队列

    QL*noempity = &obj->q1,*empity = &obj->q2;

    if(QLEmpity(&obj->q1))

    {

        noempity = &obj->q2;

        empity = &obj->q1;

    }

//把非空的队列依次出队再入队到另一个空队列直到最后一个

    while(QLSize(noempity)>1)

    {

        QLPush(empity,QLFront(noempity));

        QLPop(noempity);

    }

//记录下最后一个的值,出队销毁,返回值

    int top = QLRear(noempity);

    QLPop(noempity);

    return top;

}

 

int myStackTop(MyStack* obj) {

    assert(obj);

//找到不是空的队列,返回他的尾值

    if(QLEmpity(&obj->q1))

    {

        return QLRear(&obj->q2);

    }

    else

    {

        return QLRear(&obj->q1);

    }

}

bool myStackEmpty(MyStack* obj) {

    assert(obj);

//两个队列都为空才为空

    return QLEmpity(&obj->q1)&&QLEmpity(&obj->q2);

}

void myStackFree(MyStack* obj) {

    assert(obj);

//先销毁两个结构体队列,再毁掉obj,不然可能会导致内存泄漏

    QLDestory(&obj->q1);

    QLDestory(&obj->q2);

    free(obj);

}

2.用栈实现队列。力扣 

 

建立两个栈一个专门入栈(pushST),一个专门出栈(popST)。popST中的元素是空的时候要从pushST中拿元素,这个过程是必须的。

其余的与上面的方法类似,不再赘述。

typedef int STDataType;
typedef struct stack
{
    STDataType* a;
    int top;
    int capacity;
}ST;
void STInit(ST*ps)
{
    assert(ps);
    ps->a = NULL;
    ps->top = 0;
    ps->capacity = 0;
}
void STDestory(ST*ps)
{
    assert(ps);
    free(ps->a);
    ps->a = NULL;
    ps->top = 0;
    ps->capacity = 0;
}
void STPush(ST*ps,STDataType x)
{
    assert(ps);
    if(ps->top==ps->capacity)
    {
        ps->capacity = ps->capacity==0?4:ps->capacity*2;
        ps->a = (STDataType*)realloc(ps->a,sizeof(STDataType)*ps->capacity);
    }
    ps->a[ps->top]=x;
    ps->top++;
}
void STPop(ST*ps)
{
    assert(ps);
    //assert(ps->top>0);
    ps->top--;
}
STDataType STTop(ST*ps)
{
    assert(ps);
    return ps->a[ps->top-1];
}
int STSize(ST*ps)
{
    assert(ps);
    return ps->top;
}
bool STEmpity(ST*ps)
{
    assert(ps);
    return ps->top==0;
}


typedef struct {
    //一个结构体里建两个栈(结构体)来维护,一个专门入队列,一个专门出队列
    ST pushST;
    ST popST;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue*obj = (MyQueue*)malloc(sizeof(MyQueue));
    STInit(&obj->pushST);
    STInit(&obj->popST);
    return obj;
}

void myQueuePush(MyQueue* obj, int x) {
    assert(obj);
    //进队列,放到进栈
    STPush(&obj->pushST,x);
}

int myQueuePop(MyQueue* obj) {
    assert(obj);
    //如果popST是NULL就把pushST里的数据拿到popST中
    if(STEmpity(&obj->popST))
    {
        while(!STEmpity(&obj->pushST))
        {
            STPush(&obj->popST,STTop(&obj->pushST));
            STPop(&obj->pushST);
        }
    }
    int front = STTop(&obj->popST);
    STPop(&obj->popST);
    return front;
}

int myQueuePeek(MyQueue* obj) {
       assert(obj);
    //如果popST是NULL就把pushST里的数据拿到popST中
    if(STEmpity(&obj->popST))
    {
        while(!STEmpity(&obj->pushST))
        {
            STPush(&obj->popST,STTop(&obj->pushST));
            STPop(&obj->pushST);
        }
    }
    return STTop(&obj->popST);
}

bool myQueueEmpty(MyQueue* obj) {
    assert(obj);
    return STEmpity(&obj->popST)&&STEmpity(&obj->pushST);
}

void myQueueFree(MyQueue* obj) {
    assert(obj);
    STDestory(&obj->popST);
    STDestory(&obj->pushST);
    free(obj);
}   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值