数据结构笔记2 堆栈(堆栈的顺序存储、链式存储、表达式求值) |
您所在的位置:网站首页 › 表达式求值总结的方法有哪些 › 数据结构笔记2 堆栈(堆栈的顺序存储、链式存储、表达式求值) |
文章目录
堆栈的抽象数据类型描述堆栈的顺序存储实现堆栈的链式存储实现堆栈应用:中缀表达式转后缀表达式源代码汇总
堆栈的抽象数据类型描述
中缀表达式:运算符号位于两个运算数之间。如 ,a+b*c-d / e 后缀表达式:运算符号位于两个运算数之后。如, abc *+de / - 后缀表达式求值,需要有种存储方法,能顺序存储运算数,并在需要时“倒序”输出。这就引入了堆栈。 堆栈(Stack):具有一定操作约束的线性表 只在一端(栈顶,Top)做 插入、删除 插入数据:入栈(Push) 删除数据:出栈(Pop) 后入先出:Last In First Out(LIFO) 类型名称: 堆栈(Stack) 数据对象集:一个有0个或多个元素的有穷线性表。 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 ):删除并返回栈顶元素; 堆栈的顺序存储实现栈的顺序存储结构通常由一个一维数组和一个记录栈顶元素位置的变量组成。 #define MaxSize typedef struct SNode *Stack; struct SNode{ ElementType Data[MaxSize]; int Top; };1、入栈 void Push( Stack PtrS, ElementType item ) {if ( PtrS->Top == MaxSize-1 ) { printf(“堆栈满”); return; } else { PtrS->Data[++(PtrS->Top)] = item; return; } }PtrS->Data[++(PtrS->Top)] = item这个语句做了两件事情: (PtrS->Top)++; PtrS->Data[PtrS->Top] = item;2、出栈 ElementType Pop( Stack PtrS ) { if ( PtrS->Top == -1 ) { printf(“堆栈空”); return ERROR; /* ERROR是ElementType的特殊值,标志错误*/ } else return ( PtrS->Data[(PtrS->Top)--] ); }例:请用一个数组实现两个堆栈,要求最大地利用数组空间,使数组只要有空间入栈操作就可以成功。 分析:一种比较聪明的方法是使这两个栈分别从数组的两头开始向中间生长;当两个栈的栈顶指针相遇时,表示两个栈都满了。 #define MaxSize struct DStack { ElementType Data[MaxSize]; int Top1; /* 堆栈1的栈顶指针 */ int Top2; /* 堆栈2的栈顶指针 */ } S; S.Top1 = -1; S.Top2 = MaxSize; 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; } ElementType Pop( struct DStack *PtrS, int Tag ) { /* Tag作为区分两个堆栈的标志,取值为1和2 */ if ( Tag == 1 ) { /* 对第一个堆栈操作 */ if ( PtrS->Top1 == -1 ) { /*堆栈1空 */ printf(“堆栈1空”); return NULL; } else return PtrS->Data[(PtrS->Top1)--]; } else { /* 对第二个堆栈操作 */ if ( PtrS->Top2 == MaxSize ) { /*堆栈2空 */ printf(“堆栈2空”); return NULL; } else return PtrS->Data[(PtrS->Top2)++]; } } 堆栈的链式存储实现栈的链式存储结构实际上就是一个单链表,叫做链栈。插入和删除操作只能在链栈的栈顶进行。 栈顶指针Top应该在链表的哪一头? 若用单向链表实现一个堆栈,链表的头可以作为top,链尾不行(删除时找不到前一个结点)。 typedef struct SNode *Stack; struct SNode{ ElementType Data; struct SNode *Next; } ;(1) 堆栈初始化(建立空栈) (2) 判断堆栈S是否为空 主要靠这俩个语句: TmpCell->Next = S->Next; S->Next = TmpCell;(数组需要判别满不满,链表不需要) 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; free(FirstCell); return TopElem; } }(记得释放空间 free(FirstCell)) 堆栈应用:中缀表达式转后缀表达式从头到尾读取中缀表达式的每个对象,对不同对象按不同的情况处理。 ① 运算数:直接输出; ② 左括号:压入堆栈; ③ 右括号:将栈顶的运算符弹出并输出,直到遇到左括号(出栈,不输出); ④ 运算符: • 若优先级大于栈顶运算符时,则把它压栈; • 若优先级小于等于栈顶运算符时,将栈顶运算符弹出并输出;再比较新的栈顶运算符,直到该运算符大于栈顶运算符优先级为止,然后将该运算符压栈; ⑤ 若各对象处理完毕,则把堆栈中存留的运算符一并输出。 中缀转换为后缀示例: ( 2*(9+6/3-5)+4) |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |