PTA 6-7 在一个数组中实现两个堆栈 (20 分)-Top的取值怎么回事?

本文介绍了如何在一个数组内实现两个堆栈,详细讲解了创建、插入(压栈)和删除(出栈)的函数实现,并通过示例代码展示了其工作原理。在实现过程中,提出了初始化堆栈顶位置的两种不同方式,一种是Top1设为-1,Top2设为MaxSize,另一种是Top1设为0,Top2设为MaxSize-1。作者在PTA平台上遇到程序超时问题,经VS测试功能正常,但未解决超时原因。
摘要由CSDN通过智能技术生成

综述:

        本博客将讲述如何在一个数组内实现两个堆栈的思路,并一步步带大家实现函数的三个接口:创建、插入、删除。并在后文提出一个关于TOP取值的问题,我会分析一下两种初始取值方法,然后留一个疑问(给博主说明白私信我发个小小小红包~~)。


目录

综述:

题目:

函数接口定义:

裁判测试程序样例:

输入样例: 

输出样例: 

函数接口1-创建堆栈:

CreateStack(int MaxSize)-代码:

函数结构2-插入元素:

Push(Stack S, ElementType X, int Tag)-代码: 

函数接口3-删除元素:

Pop(Stack S, int Tag)-代码:

PTA检验结果: 

问题(有明白的解答发个小红包): 

问题代码:

VS测试程序:

VS 测试结果: 

提交程序结果超时:

总结:


题目:

本题要求在一个数组中实现两个堆栈。 

函数接口定义:

Stack CreateStack( int MaxSize );
bool Push( Stack S, ElementType X, int Tag );
ElementType Pop( Stack S, int Tag ); 

其中Tag是堆栈编号,取1或2;MaxSize堆栈数组的规模;Stack结构定义如下: 

typedef int Position;
struct SNode {
    ElementType *Data;
    Position Top1, Top2;
    int MaxSize;
};
typedef struct SNode *Stack;

注意:如果堆栈已满,Push函数必须输出“Stack Full”并且返回false;如果某堆栈是空的,则Pop函数必须输出“Stack Tag Empty”(其中Tag是该堆栈的编号),并且返回ERROR。 

裁判测试程序样例:

#include <stdio.h>
#include <stdlib.h>

#define ERROR 1e8
typedef int ElementType;
typedef enum { push, pop, end } Operation;
typedef enum { false, true } bool;
typedef int Position;
struct SNode {
    ElementType *Data;
    Position Top1, Top2;
    int MaxSize;
};
typedef struct SNode *Stack;

Stack CreateStack( int MaxSize );
bool Push( Stack S, ElementType X, int Tag );
ElementType Pop( Stack S, int Tag );

Operation GetOp();  /* details omitted */
void PrintStack( Stack S, int Tag ); /* details omitted */

int main()
{
    int N, Tag, X;
    Stack S;
    int done = 0;

    scanf("%d", &N);
    S = CreateStack(N);
    while ( !done ) {
        switch( GetOp() ) {
        case push: 
            scanf("%d %d", &Tag, &X);
            if (!Push(S, X, Tag)) printf("Stack %d is Full!\n", Tag);
            break;
        case pop:
            scanf("%d", &Tag);
            X = Pop(S, Tag);
            if ( X==ERROR ) printf("Stack %d is Empty!\n", Tag);
            break;
        case end:
            PrintStack(S, 1);
            PrintStack(S, 2);
            done = 1;
            break;
        }
    }
    return 0;
}

/* 你的代码将被嵌在这里 */

输入样例: 

5
Push 1 1
Pop 2
Push 2 11
Push 1 2
Push 2 12
Pop 1
Push 2 13
Push 2 14
Push 1 3
Pop 2
End

输出样例: 

Stack 2 Empty
Stack 2 is Empty!
Stack Full
Stack 1 is Full!
Pop from Stack 1: 1
Pop from Stack 2: 13 12 11


函数接口1-创建堆栈:

        题目要求在一个数组内实现两个堆栈,这俩个堆栈用结构体指针维护,结构体成员有4个,第一个MaxSize,它标识堆栈数组的规模,第二个成员是一个数组,数组开辟空间大小为MaxSize个数组元素类型大小的字节数,第三个第四个成员Top1Top2标识两个堆栈栈顶的位置初始,其中,Top1初始值为-1Top2初始值为MaxSize,这两个初始值讨论的问题放到后面的问题部分~

CreateStack(int MaxSize)-代码:

Stack CreateStack(int MaxSize)
{
    Stack s = (Stack)malloc(sizeof(struct SNode));
    s->Data = (ElementType*)malloc(sizeof(ElementType) * MaxSize);
    s->MaxSize = MaxSize;
    s->Top1 = -1;
    s->Top2 = MaxSize;
    return s;
}

函数结构2-插入元素:

        堆栈的的性质就是先进后出,插入元素叫压栈,数组实现堆栈还是很容易的,首先是一个数组实现一个堆栈怎么办?具体如下图:

 

         一个数组实现一个堆栈非常简单,但是一个数组实现两个堆栈该如何操作呢?我们直到堆栈1的栈底可以放在数组的开头位置,可堆栈2的栈底应该放在哪里呢?有三个位置可以考虑:一是和栈1一样也放到数组开头位置,二是放在数组中间位置,三是放到数组结尾位置。

       假设栈2的底也放到开头的位置,当栈1的先压栈,然后栈2压栈几个元素,然后这样交叉几下,你会发现,这个程序变的巨复杂,同样放到中间位置也是有这样的问题。

        我们期望的是栈1和栈2的底都在固定的位置,那么栈1在数组开始,栈2在数组尾刚刚合适两个栈可以双向奔赴,程序就变的简单起来。

 

         栈底位置确定好之后,下一个问题就是什么时候栈满了,栈满了就是数组元素满了,有三种可能。

 

 :不知道大家有没有发现,其实这三种数组满的情况,top2-top1的值都==1,由此可以推出当前栈满时的条件。

         了解了栈满的条件后就简单了,Push函数首先要判断是栈1还是栈2,然后Top1加加往后走,Top2--往前走,Top位标识的是栈底当前的位置,拿Top1举例,开始-1,表明栈为空,压栈,Top1++,变为0 然后使得数组的Top1位插入数据也就是数组的0位置。同理栈2也一样。

Push(Stack S, ElementType X, int Tag)-代码: 

bool Push(Stack S, ElementType X, int Tag)
{
    if (S->Top2 - S->Top1 == 1)
    {
        printf("Stack Full\n");
        return false;
    }
    if (Tag == 1)
    {
         (S->Top1)++;
        S->Data[S->Top1] = X;
       
    }
    else
    { 
        (S->Top2)--;
        S->Data[S->Top2] = X;
       
    }
    return true;

}

函数接口3-删除元素:

        删除元素就是出栈,那无论是栈1还是栈2出栈的时候第一步还是要判断是不是空栈,如果栈1空栈还要pop栈1,那就返回ERROR,同理栈2也一样。栈1空栈的是Top1为-1,栈2空栈时Top2MaxSize,如果不是空栈的话就特别简单了,如果Pop栈1只需要Top1--就ok,而之前位置里面的数据不用管,下次压栈就直接覆盖了。

Pop(Stack S, int Tag)-代码:

ElementType Pop(Stack S, int Tag)
{
    if (Tag == 1)
    {
        if (S->Top1 == -1)
        {
            printf("Stack %d Empty\n", Tag);
            return ERROR;
        }
        int ret = S->Data[S->Top1];
        S->Top1--;
        return ret;

    }
    else
    {
        if (S->Top2 == S->MaxSize)
        {
            printf("Stack %d Empty\n", Tag);
            return ERROR;
        }
        int ret = S->Data[S->Top2];
        S->Top2++;
        return ret;
    }
}

PTA检验结果: 


问题(有明白的解答发个小红包): 

说明:我们知道Top位可以标识栈顶,只拿栈1举例,本文正确程序初始化Top1=-1,我开始做这个题初始化是0,但是提交总是程序超时,我把程序粘到VS上测试,发现是能够实现压栈出栈的功能的,但是只要提交PTA就程序超时,实在是无语~

 

问题代码:

Stack CreateStack(int MaxSize)
{
    Stack s = (Stack)malloc(sizeof(struct SNode));
    s->Data = (ElementType*)malloc(sizeof(ElementType) * MaxSize);
    s->MaxSize = MaxSize;
    s->Top1 = 0;
    s->Top2 = MaxSize-1;
    return s;
}
bool Push(Stack S, ElementType X, int Tag)
{
    if (S->Top1 - S->Top2 == 1)
    {
        printf("Stack Full\n");
        return false;
    }
    if (Tag == 1)
    {
        S->Data[S->Top1] = X;
        (S->Top1)++;
    }
    else
    { 
        S->Data[S->Top2] = X;
         (S->Top2)--;
    }
    return true;

}
ElementType Pop(Stack S, int Tag)
{
    if (Tag == 1)
    {
        if (S->Top1 == 0)
        {
            printf("Stack %d Empty\n", Tag);
            return ERROR;
        }
        int ret = S->Data[S->Top1-1];
        S->Top1--;
        return ret;

    }
    else
    {
        if (S->Top2 == S->MaxSize-1)
        {
            printf("Stack %d Empty\n", Tag);
            return ERROR;
        }
        int ret = S->Data[S->Top2+1];
        S->Top2++;
        return ret;
    }
}

VS测试程序:

我根据PTA的测试用例在VS上搞的测试代码:

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>

#define ERROR 1e8
typedef int ElementType;
typedef enum { push, pop, end } Operation;
typedef enum { false, true } bool;
typedef int Position;
struct SNode {
    ElementType* Data;
    Position Top1, Top2;
    int MaxSize;
};
typedef struct SNode* Stack;

Stack CreateStack(int MaxSize);
bool Push(Stack S, ElementType X, int Tag);
ElementType Pop(Stack S, int Tag);

Operation GetOp();  /* details omitted */
void PrintStack(Stack S, int Tag); /* details omitted */

int main()
{
    Stack L = CreateStack(5);
    Push(L, 1, 1);
    Pop(L, 2);
    Push(L, 11, 2);
    Push(L, 2, 1);
    Push(L, 12, 2);
    Pop(L, 1);

    Push(L, 13, 2);
  
    Push(L, 14, 2);
    Push(L, 3, 1);


    Pop(L, 2);

    return 0;
}
/* 你的代码将被嵌在这里 */
Stack CreateStack(int MaxSize)
{
    Stack s = (Stack)malloc(sizeof(struct SNode));
    s->Data = (ElementType*)malloc(sizeof(ElementType) * MaxSize);
    s->MaxSize = MaxSize;
    s->Top1 = 0;
    s->Top2 = MaxSize - 1;
    return s;
}
bool Push(Stack S, ElementType X, int Tag)
{
    if (S->Top1 - S->Top2 == 1)
    {
        printf("Stack Full\n");
        return false;
    }


    if (Tag == 1)
    {
        S->Data[S->Top1] = X;
        S->Top1++;
    }
    else
    {
        S->Data[S->Top2] = X;
        S->Top2--;
    }
    return true;

}
ElementType Pop(Stack S, int Tag)
{
    if (Tag == 1)
    {
        if (S->Top1 == 0)
        {
            printf("Stack %d Empty\n", Tag);
            return ERROR;
        }
   
        S->Top1--;
    
    }
    else
    {
        if (S->Top2 == S->MaxSize - 1)
        {
            printf("Stack %d Empty\n", Tag);
            return ERROR;
        }
        S->Top2++;
       
    }
}

VS 测试结果: 

        结果可以看出来,Top2的位置为1,那么栈顶元素位置为2,栈2的元素就为13、12、11和预期结果一致,Top1位置为1,那么栈1栈顶元素为0,那么栈1只有一个元素1,与预期结果一致。

提交程序结果超时:


总结:

        求大佬指点,1块钱红包作为报酬!

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芝士就是菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值