当前位置: 首页 > news >正文

数据结构基础内容(第三篇:堆栈)

# 堆栈 Stack  

具有一定操作约束的线性表,只在一端(栈顶,Top)做 插入、删除  

操作集:长度为MaxSize的堆栈S 属于 Stack,堆栈元素item 属于 ElementType  

1. Stack CreateStack( int MaxSize ): 生成空堆栈,其最大长度为MaxSize;

2. int IsFull( Stack S, int MaxSize ):判断堆栈S是否已满;

3. void Push( Stack S, ElementType item ):将元素item压入堆栈;

4. int IsEmpty ( Stack S ):判断堆栈S是否为空;

5. ElementType Pop( Stack S ):删除并返回栈顶元素;

##  栈的顺序存储实现

栈的顺序存储结构通常由一个一维数组和一个记录.栈顶元素位置的变量组成。

```c

#define MaxSize <储存数据元素的最大个数>

typedef struct SNode *Stack;  //结构指针

struct SNode{

    ElementType Data[MaxSize];  //数组

    int Top; // 栈顶位置的数组下标

};

```

* 入栈 Push  

```c

void Push( Stack PtrS, ElementType item )  // stack这个类型的指针

{

    if ( PtrS->Top == MaxSize-1 ) // 判断满不满。从 0 到 MaxSize-1

    {

        printf(“堆栈满”);

        return;

    }else

    {

        PtrS->Data[++(PtrS->Top)] = item;

        /* 相当于:

        (PtrS->Top)++;

        PtrS->Data[PtrS->Top] = item;

        */

        return;

    }

}

```

* 出栈 Top  

```c

ElementType Pop( Stack PtrS )

{

    if ( PtrS->Top == -1 )

    {

         printf(“堆栈空”);

         return ERROR;  //ERROR是ElementType的特殊值,标志错误

    } else

    {

        return ( PtrS->Data[(PtrS->Top)--] ); // return 出下标为top的这个值,同时Top-1

    }

}

```

 [例] 请用一个数组实现两个堆栈,要求最大地利用数组空间,使 数组只要有空间入栈操作就可以成功。  

【分析】 一种比较聪明的方法是使这两个栈分别从数组的两头开始 向中间生长;当两个栈的栈顶指针相遇时,表示两个栈都满了。  

```c

#define MaxSize <存储数据元素的最大个数>

struct DStack {

    ElementType Data[MaxSize];

    int Top1; /* 堆栈1的栈顶指针 */

    int Top2; /* 堆栈2的栈顶指针 */

} S;

S.Top1 = -1; // 左边这个设为空

S.Top2 = MaxSize; // 右边设为空(已经超出了MaxSize -1)

```

入栈

```c

void Push( struct DStack *PtrS, ElementType item, int Tag )

{ /* Tag作为区分两个堆栈的标志,取值为1和2 */

    if ( PtrS->Top2 – PtrS->Top1 == 1) /* 堆栈满, 两个指针相邻啦 */

    {

        printf(“堆栈满”);

        return ;

    }

    if ( Tag == 1 ) /* 对第一个堆栈操作 */

        PtrS->Data[++(PtrS->Top1)] = item;  // 放在第一个元素后面一位

    else /* 对第二个堆栈操作 */

        PtrS->Data[--(PtrS->Top2)] = item;  // 放在最后一个元素的前面一位

}

```

出栈

```c

ElementType Pop( struct DStack *PtrS, int Tag )

{ /* Tag区分两个堆栈*/

    if(Tag==1) /*对第一个堆栈操作 */

    {

        if ( PtrS->Top1 == -1 )  /*堆栈1空 */

        {

            printf(“堆栈1空”);

            return NULL;

        } else

            return PtrS->Data[(PtrS->Top1)--]; // 先抛出再对top-1

    } else /* 对第二个堆栈操作 */

    {

        if ( PtrS->Top2 == MaxSize )  /*堆栈2空 */

        {        

            printf(“堆栈2空”);

            return NULL;

        }

        else

            return PtrS->Data[(PtrS->Top2)++]; // 先抛出再对top+1

    }

}

```

##  堆栈的链式存储实  

栈的链式存储结构实际上就是一个单链表,叫做链栈。插入和删 除操作只能在链栈的栈顶进行。  

```c

typedef struct SNode *Stack; struct SNode{

    ElementType Data;

    struct SNode *Next;

};

```

初始化(建立空栈)

```c

Stack CreateStack()

{ /* 构建一个堆栈的头结点,返回指针 */

    Stack S;

    S =(Stack)malloc(sizeof(struct SNode));

    S->Next = NULL;

    return S;

}

```

判断堆栈S是否为空

```c

int IsEmpty(Stack S) /*判断堆栈S是否为空,若为空函数返回1,否则返回0 */

{

   return ( S->Next == NULL );

}

```

* 入栈 Push  

```c

void Push( ElementType item, Stack S) /* 将元素item压入堆栈S */

{

    struct SNode *TmpCell;

    TmpCell=(struct SNode *)malloc(sizeof(struct SNode))

    TmpCell->Element = item;

    TmpCell->Next = S->Next;  // 插到头结点的后面

    S->Next = TmpCell;

}

```

* 出栈 Top  

```c

ElementType Pop(Stack S)  /* 删除并返回堆栈S的栈顶元素 */

{

   struct SNode *FirstCell;

   ElementType TopElem;

   if( IsEmpty( S ) )

    {

        printf(“堆栈空”);

        return NULL;

    }

    else

    {

        FirstCell = S->Next;

        S->Next = FirstCell->Next;

        TopElem = FirstCell ->Element; // 获得被删除的这个值,return出去

        free(FirstCell);

        return TopElem;

    }

}

```

## 应用:表达式求值  

* 运算数相对顺序不变  

* 运算符号顺序发生改变: 需要存储“等待中”的运算符号,要将当前运算符号与“等待中”的最后一个运算符号比较

    * 如果最后一个符号的优先级比较高,则出栈

    * 如果最后一个符号的优先级更低,则等待  

括号怎么办?  

左括号(优先级比乘号*高.但左括号(在堆栈中优先级就降到最低, 左括号(优先级比加号+低.

碰到右括号)后,括号内的计算结束,把堆栈内的抛出来,直到遇到左括号(.

http://www.dtcms.com/a/301469.html

相关文章:

  • 深度解析 inaSpeechSegmenter:高效音频语音分割与检测开源工具
  • Epoll事件EPOLLRDHUP详解
  • springboot基于Java与MySQL库的健身俱乐部管理系统设计与实现
  • C51:使用超声波测量距离
  • C#.NET dapper 详解
  • MySQL 中的 BufferPool 和 ChangeBuffer
  • Amazon Relational Database Service (Amazon RDS)入门课
  • 量子力学的基本假设
  • 【Java】图书管理系统设计详解
  • 《 集成异步任务与定时调度:线程池与任务中心设计》
  • C++--继承
  • 设计模式(六)创建型:单例模式详解
  • VINS外参精确自标定飘的问题
  • 2025.7.22总结-幸福的力量
  • 模型评估的介绍
  • 探秘CommonJS:Node.js模块化核心解析
  • macOS配置 GO语言环境
  • Python测试框架之pytest(一)
  • 数学基础薄弱者的大数据技术学习路径指南
  • 一、搭建springCloudAlibaba2021.1版本分布式微服务-父工程搭建
  • LeetCode 76:最小覆盖子串
  • 分布式事务:二阶段提交和三阶段提交底层原理
  • AI时代,我们更需要自己的开发方式与平台
  • java--函数式接口全面总结与使用场景指南
  • LeetCode 611.有效三角形的个数
  • python---eval函数
  • Ashampoo Background Remover(照片去背景工具) v2.0.2 免费版
  • Oracle EBS 库存期间关闭状态“已关闭未汇总”处理
  • 【成功经验分享】Github Education (Github学生认证)认证
  • 【NLP实践】一、中文短句情感二分类实现并提供RestfulApi服务调用