提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


从数据结构角度看,栈和队列仍属于线性结构,具有线性结构的特征;
其个性是:栈和队列是操作受限的线性结构。
特点:后进先出或先进后出,最晚到达栈的结点最晚被删除。

基础知识

栈顶(top):表中允许进行插入和删除操作的一端。
栈底(bottom):表的另一端
进栈(Push):在栈顶位置插入元素的操作
出栈(Pop):删除栈顶元素的操作
栈溢出:当栈满时,若再有元素进栈则发生上溢;当栈空时,若再出栈发生下溢。
空栈:不含元素的空表

顺序栈

常用数组的后端表示栈顶,top常被成为栈顶指针。
在这里插入图片描述
栈空时,栈顶指针top==-1;
入栈时,栈顶指针加一,即++top;//先向后移动指针再存入元素
出栈时,栈顶指针减一,即top–;//先取出栈顶元素,再移动栈顶指针

顺序栈的类型定义
template<class T>
class seqStack
{
   private:
     T*data;//存放栈中元素的数组
     int top;//栈顶指针,指向栈顶元素
     int maxSize;//栈的大小
#define Maxsize 50//定义栈中元素的最大个数
typedef struct
{
  Elemtype data[Maxsize];//存放栈中元素
  int top;//栈顶指针
}sqStack;
初始化栈顶指针
seqStack<T>::seqStack(int initSize=100)
{
   if(initSize<=0)throw badsize();
   data=new t[initSize];//声请数组,并把首地址给data指针
   maxsize=initSize;
   tpo=-1;}
void INitStack (SqStack&s)
{
  s.top=-1;
  }
进栈
template<class T>
void seqStack<T>::push(const T&value)
{
  if(top==namSize-1)//top指针指向数组的最大下标
  {  cout<<"栈满\n";
    return ;
    }
    data[++top]=value;//栈顶指针向后,存入值为value的新元素
 }
 时间复杂度O(1),空间复杂度O(1)
bool Push(sqStack&s,Elemtype x)
{  if(s.top==-1) return false;//栈满,报错
  s.data[++s.top]=x;//指针先加一,再入栈
  return true;
  }
出栈
template<class T>
T seqStack<T>::pop()
{if(empty())   throw outOfRange();//栈空,抛出异常
return data[top--];
}
bool pop(sqStack&s,Elemtype&x)
{ if(s.top==-1)
return false;//栈空,报错
 x=s.data[s.top--];//先出栈,指针再减1
 return true;

“出栈”并不一定要带回元素,带回元素是“副产品”,
出栈的主要目的是下移指针,
是否要返回栈顶元素取决于题目要求。

取栈顶元素

仅为读取栈顶元素,并没有出栈操作,因此原栈顶元素依然保存在栈中

template<class T>
T seqStack<T>::getTop()const
{ ifenpty()) throw outOfRange();
return data[top]
bool gettop(sqStack s,elemtype&x)
{ if(s.top==-1)
      return false;
  x=s.data[s.top];
  return true;
  }

链表

template<class T>
class linkStack
{private:
   struct Node{
   T data;
   Node*next;
   Node(){next=NULL;}
   Node(const T&value,Node*p=NULL)
   {data=value;next=p;}
   };
   Node*top;
进栈

在这里插入图片描述

template<class T>
void linkStack<T>::pushu(const P&value)
{Node*p=new Node();//在栈顶插入元素
p->data=value;
p->next=top;
top=p;//p成为新的栈顶元素
}
出栈
template<class T>
T linkStack<T>::pop(){
if(empty()) throw outOfRange();///空栈,报错
Node*p=top;
T value=p->data;//value保存栈顶元素的值
top=top->next;//top指向向后移动
delete p;//删除栈顶元素
return value;
}
取栈顶元素
template<class T>
T linkStack<T>::getTop()const{
if(empty()) throw outOfRange();
return top->data;
}

只要求返回栈顶元素的值。

清空栈

遍历整个栈

template<classT>
void linkStack<T>::clear(){
  Node*p;
  while(top!=NULL){
     p=top;//p指向当前栈顶元素
     top=top->next;//top(栈顶指针)指针移向次栈顶元素
     delet p;//释放p指向的当前栈顶元素
     }
   }

时间复杂度O(n),空间复杂度O(1)

求栈中元素个数
template<class T>
int linkStack<T>::size()const{
   Node*p=top;
   int count=0;//计数器
 while(p)//遍历栈,统计元素总数
   {  count++;
    p=p->next;}
 return count;
 }

栈的总结

1.栈是一种后进先出的线性表
2.栈可以用顺序实现,也可以用链接实现
3.大部分操作只需常数时间,顺序栈和链式栈在时间效率上难分伯仲
4.实际应用中,顺序栈比链栈用得更广泛些,因为顺序栈存储开销较低,并且能够以O(1)的时间复杂度快速定位并读取栈中元素,而在链栈中读取第i个元素时需要沿着指针查找,时间复杂度O(n)。

栈的应用

中缀式求值

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
中缀表达式12(6-3.5)=求值*

在这里插入图片描述
先压栈在这里插入图片描述
在这里插入图片描述

中缀转后缀

后缀表达式的优点:
(1)后缀表达式中不包含括号﹔
(2)不必考虑运算符的优先规则﹔
(3)运算符放在两个运算对象的后面,按照运算符出现的顺序,从左向右进行计算。

示例:a+b --> ab+
(a+b)c-d ----> ab+cd-

算法思想
设一字符栈optr,并设中缀表达式和后缀表达式分别存放在字符数组infix和postfix中。从左向右扫描infix:
(1)若infixli]是‘(’,压入栈optr中 ;
(2)若infix[i]是操作数,将infix[i]直接送入postfix ;
(3)若infix[i]是运算符,且其级别比栈顶元素的级别高,则infix[i]入栈﹔否则,栈顶元素退栈,进入postfix,infix[i]再与新栈顶元素比较,重复步骤(3);(4)若infix[i]为‘)’,则将栈中元素依次送postfix,直至碰到‘(’,然后’(栈,消掉一对括号。
(5)当遇到infix的结束符‘='时,开始执行退栈操作,并将退栈元素直接存
postfix,直至栈空。最后在postfix中存入“\0’作为后缀表达式结束标志.
在这里插入图片描述

后缀式求值

思想手工模拟:
(1)设置一操作数栈opnd ;
(2)从左到右扫描后缀表达式,直到遇到结束标志“\0’;
a)若读到的是操作数,则将其进栈;
b)若读到的是运算符,则将栈顶的两个操作数出栈,后弹出的操作数为被操作数,先弹出的为操作数,将得到的操作数完成运算符所规定的运算,并将结果进栈;
c)若读到的是空格,则跳过它;
(3)表达式扫描完毕,栈中剩一个数,即表达式的值。

遇到除号,先弹出除数,后弹出被除数。如 先弹出2,后弹出6,运算结果为3.减法同上
在这里插入图片描述
过程:压12,压6,压2,遇除号,弹2,弹6,运算为3,压0.5,遇减号,弹0.5,运算为2.5,压入栈,遇到乘号,弹2.5,弹12,运算为30,30压入数字栈

中缀转后缀表达式的简单方法
(1)加括号:将中缀表达式中所有的子表达式按计算规则用嵌套括号栝起来;
(2)移运算符:将每对括号中的运算符移到相应括号的后面;
(3)删括号:删除所有括号。
例如,将中缀表达式12*(6/ 2 -0.5 )转为后缀表达式:

步骤(1) :(12*((6/ 2)-0.5));
步骤(2) :(12((6 2) / 0.5)- )*;
步骤(3) : 12 6 2 / 0.5- *,即为所求后缀表达式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值