(二)线性结构:堆栈实现线性表的基本操作

堆栈的用途:函数调用、递归、回溯算法、表达式求值

例1:计算机如何进行表达式求值?对算术表达式(中缀表达式)5+6/2-3*4(等价于后缀表达式562/+34*-),正确理解:                           5+6/2-3*4=5+3-3*4=8-3*4=8-12=-4

 例2:求后缀表达式62/3-42*+=??从左往右扫描,先记数,再看其后的运算符,找对应放入数。

62/3-42*+=6/2 3-42*+=3 3-42*+=3-3 42*+=0+4*2=8

由两类对象构成:运算数和运算符号(不同运算符号优先级不一样)

结论:需要有种存储方法,能顺序的存储运算数,并在需要的时候“倒序”输出,此时堆栈就起作用了。

 堆栈的抽象数据类型描述

定义:具有一定操作约束的线性表,只在一端(栈顶,Top)做插入(入栈Push)、删除(出栈Pop),后入先出(Last In First Out,LIFO)

数据对象集:一个有0个或多个元素的又穷线性表

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

线性表的基本操作(堆栈实现):

  1. Stack CreateStack(int MaxSize):生成一个最大长度为MaxSize的空堆栈
  2. int IsFull(Stack S,int MaxSize):判断堆栈S是否已满
  3. void Push(Stack S,ElementType item):在堆栈中压入item元素
    #include <stdio.h>
    
    typedef int ElementType;
    #define MaxSize 100
    #define ERROR
    typedef struct SNode *Stack;
    struct SNode{
    	ElementType Data[MaxSize];
    	int Top;
    };
    
    void Push(Stack PtrS, ElementType item)
    {
    	if (PtrS->Top == MaxSize - 1)     //判断堆栈是否还能放进去元素
    	{
    		printf("堆栈满");
    		return;
    	}
    	else
    	{
    		PtrS->Data[++(PtrS->Top)] = item; //将数据插入到堆栈的上面一个位置
    		return;
    	}
    }
    

     

  4. int IsEmpty(Stack S):判断堆栈S是否为空
  5. ElementType Pop(Stack S):删除并返回栈顶元素
    ElementType Pop(Stack PtrS)
    {
    	if (PtrS->Top == -1)
    	{
    		printf("堆栈空");          //判断堆栈是否为空
    		return ERROR;        //标志错误
    	}
    	else
    		return (PtrS->Data[(PtrS->Top)--]);  //将元素自上而下一个个弹出
    }

     

栈的顺序存储(数组方式)实现:通常由一个一维数组和一个记录栈顶元素位置的变量组成。

例:用一个数组实现两个堆栈,使数组有空间进行入栈操作。(提示:将一个数组分成两个部分,都从左边压入元素,可能会造成一个堆栈满了,另外一个堆栈空着。因此此时将一个数组分成两个部分,分别从两头往中间压入元素,当两个栈头相遇时,表示两个栈满了)

struct DStack{
	ElementType Data[MaxSize];
	int Top1;   //当Top1等于-1时,数组1为空
	int Top2;   //当Top2等于MaxSize时,数组2为空
}S;

void Push(struct DStack *PtrS, ElementType item, int Tag)
{
	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, ElementType item, int Tag)
{
	if (Tag == 1){
		if (PtrS->Top1 == -1){
			printf("堆栈1为空");
			return NULL;
		}
		else
			return PtrS->Data[(PtrS->Top1)--];    //从前往后弹出元素
	}
	else
	{
		if (PtrS->Top2 == MaxSize){
			printf("堆栈2为空");
			return NULL;
		}
		else
			return PtrS->Data[(PtrS->Top2)++];     //从后往前弹出元素
	}
}

 

 栈的链式存储(链表方式)实现:即单链表,叫链栈。插入和删除操作只能在链栈顶进行。栈顶指针Top应在链表的头部

  1. 堆栈初始化,建立空栈
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef int ElementType;
    #define MaxSize 100
    #define ERROR
    typedef struct SNode *Stack;
    struct SNode{
    	ElementType Data;
    	struct SNode *Next;
    };
    
    Stack CreateStack()      //堆栈初始化,建立空栈
    {
    	Stack S;
    	S = (Stack)malloc(sizeof(struct SNode));
    	S->Next = NULL;
    	return S;
    }
    
    int IsEmpty(Stack S)    //判断栈是否为空
    {
    	return (S->Next == NULL);
    }

     

  2. 堆栈元素的插入
    void Push(ElementType item, Stack S)   //插入元素
    {
    	struct SNode *TmpCell;
    	TmpCell = (struct SNode *)malloc(sizeof(struct SNode));
    	TmpCell->Data = item;
    	TmpCell->Next = S->Next;
    	S->Next = TmpCell;
    }
    

     

  3. 堆栈元素的删除
    ElementType Pop(Stack S)
    {
    	struct SNode *FirstCell;
    	ElementType TopElem;
    	if (IsEmpty(S)){
    		printf("堆栈空");
    		return NULL;
    	}
    	else{
    		FirstCell = S->Next;
    		S->Next = FirstCell->Next;
    		TopElem = FirstCell->Data;
    		free(FirstCell);
    		return TopElem;
    	}
    }

     

 堆栈的应用:中缀表达式求值。首先将中缀表达式转换为后缀表达式,从头到尾读取中缀表达式的每个对象,对不同对象按不同的情况处理。

转换法则:

1.运算数:直接输入

2.左括号:压入堆栈

3.右括号:将栈顶的运算符弹出并输出,直到遇到左括号(出栈,不输出)

4.运算符:如果优先级大于栈顶运算符时,则把他压栈;

               如果优先级小于栈顶运算符时,将栈顶运算符弹出并输出;再比较新的栈顶运算符,知道该运算符大于栈顶运算符优先级为止

5.如果各对象处理完毕,则把堆栈中存留的运算符一并输出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值