严蔚敏《数据结构》3.1 栈

代码是参考的康建伟老师的: https://www.cnblogs.com/kangjianwei101/p/5221816.html,以及用copilot做了一些改进

下面主要记录一些问题(核心代码附在最后)

  • 对有一些边界条件有疑惑,整理了一下

    函数名if 条件判断条件含义
    InitStackif (S == NULL)检查栈指针是否为空,避免对空指针进行操作
    InitStackif ((*S).base == NULL)检查分配内存是否成功,若不成功则退出程序
    DestroyStackif (S == NULL)检查栈指针是否为空,避免对空指针进行操作
    ClearStackif (S == NULL ||(*S).base == NULL)检查栈指针是否为空,以及栈是否已经初始化
    StackEmptyif (S.top == S.base)检查栈顶指针是否与栈底指针相等,以判断栈是否为空
    StackLengthif (S.base == NULL)检查栈是否已经初始化
    GetTopif (S.base == NULL ||( S.top == S.base)检查栈是否已经初始化,以及栈是否为空
    Pushif (S == NULL ||( (*S).base == NULL)检查栈指针是否为空,以及栈是否已经初始化
    Pushif ((*S).top - (*S).base >= (*S).stacksize)检查栈是否已满,若满则需要扩容
    Popif (S == NULL ||( (*S).base == NULL)检查栈指针是否为空,以及栈是否已经初始化
    Popif ((*S).top == (*S).base)检查栈是否为空,若为空则不能进行弹栈操作
    StackTraverseif (S.base == NULL)检查栈是否已经初始化,未初始化则不能遍历
  • 关于遍历函数StackTraverse
    StackTraverse 函数的主要目的是遍历顺序栈 S 并对栈中的每个元素执行一个特定的操作。这个操作由传递给 StackTraverse 的函数指针 Visit 定义。

    Status StackTraverse(SqStack S, void(Visit)(SElemType))
    

    Visit 参数是一个函数指针,允许将函数作为参数传递给另一个函数。这里的 Visit 函数必须符合特定的格式:它需要是一个接受单个 SElemType 类型参数的函数。在遍历栈时,StackTraverse 函数会对栈中的每一个元素调用 Visit 函数。

    康建伟老师的程序中,PrintElem 函数被用作 Visit 函数,它的作用是打印一个整数元素:

    void PrintElem(SElemType e)
    {
        printf("%d ", e);
    }
    

    这样调用 StackTraverse 函数时:

    StackTraverse(S, PrintElem);
    
  • 核心代码主要就是下面这些
    (严书上用的是引用,这里用的是指针,能看懂就OK)

    /**
     * 初始化
     *
     * 构建一个空栈S。初始化成功则返回OK,否则返回ERROR。
     */
    Status InitStack(SqStack *S)
    {
        // 如果S为NULL,返回ERROR
        if (S == NULL)
        {
            return ERROR;
        }
        // 为顺序栈分配一个大小为STACK_INIT_SIZE的数组空间
        (*S).base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
    
        if ((*S).base == NULL)
        {
            // 存储分配失败
            exit(OVERFLOW);
        }
    
        // 设置栈顶指针为栈底指针
        (*S).top = (*S).base;
    
        // 设置栈的最大容量
        (*S).stacksize = STACK_INIT_SIZE;
    
        return OK;
    }
    
    /*
     * 销毁(结构)
     *
     * 释放顺序栈所占内存。
     */
    Status DestroyStack(SqStack *S)
    {
        // 如果S为NULL,返回ERROR
        if (S == NULL)
        {
            return ERROR;
        }
    
        // 释放顺序栈所占内存
        free((*S).base);
    
        // 栈底指针、栈顶指针置空
        (*S).base = NULL;
        (*S).top = NULL;
    
        // 栈的最大容量置为0
        (*S).stacksize = 0;
    
        return OK;
    }
    
    /*
     * 清空(内容)
     *
     * 只是清理顺序栈中存储的数据,不释放顺序栈所占内存。
     */
    Status ClearStack(SqStack *S)
    {
        // 如果S为NULL或者S本身就是空栈,则返回ERROR
        if (S == NULL || (*S).base == NULL)
        {
            return ERROR;
        }
        (*S).top = (*S).base;
        return OK;
    }
    
    /**
     * 判空
     *
     * 判断顺序栈中是否包含有效数据。
     */
    Status StackEmpty(SqStack S)
    {
        // 如果栈顶指针和栈底指针重合,则说明栈为空
        if (S.top == S.base)
        {
            return TRUE;
        }
        else
        {
            return FALSE;
        }
    }
    
    /**
     * 计数
     *
     * 返回顺序栈包含的有效元素的数量。
     */
    int StackLength(SqStack S)
    {
        if (S.base == NULL)
        {
            return 0;
        }
    
        return (int)(S.top - S.base);
    }
    
    /**
     * 取值
     *
     * 获取栈顶元素,并通过e返回。
     */
    Status GetTop(SqStack S, SElemType *e)
    {
    
        if (S.base == NULL || S.top == S.base)
        {
            return ERROR;
        }
        *e = *(S.top - 1);
    }
    
    /**
     * 压栈
     *
     * 将元素e压入到栈顶。
     */
    Status Push(SqStack *S, SElemType e)
    {
        if (S == NULL || (*S).base == NULL)
        {
            return ERROR;
        }
    
        // 如果栈满,则追加存储空间
        if ((*S).top - (*S).base >= (*S).stacksize)
        {
            // 为顺序栈追加空间
            (*S).base = (SElemType *)realloc((*S).base, ((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
    
            if ((*S).base == NULL)
            {
                // 存储分配失败
                exit(OVERFLOW);
            }
    
            // 栈容量加上增量
            (*S).top = (*S).base + (*S).stacksize;
    
            (*S).stacksize += STACKINCREMENT;
        }
    
        // 入栈先赋值,栈顶指针再加1
        *(S->top) = e; // 也可以写成:*((*S).top)=e;
        S->top++;
    }
    
    /**
     * 弹栈
     *
     * 将栈顶元素弹出,并通过e返回。
     */
    Status Pop(SqStack *S, SElemType *e)
    {
        if (S == NULL || (*S).base == NULL)
        {
            return ERROR;
        }
    
        // 如果栈为空,则返回ERROR
        if ((*S).top == (*S).base)
        {
            return ERROR;
        }
    
        // 栈顶指针减1,将栈顶元素赋值给e
        (*S).top--;
        *e = *((*S).top);
    
        return OK;
    }
    
    /**
     * 遍历
     *
     * 用visit函数访问顺序栈S
     */
    Status StackTraverse(SqStack S, void(Visit)(SElemType))
    {
        if (S.base == NULL)
        {
            return ERROR;
        }
    
        SElemType *p = S.base;
    
        while (p < S.top)
        {
            Visit(*p++);
        }
    
        printf("\n");
    
        return OK;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值