栈的定义
栈是限定尽在表尾进行插入和删除操作和删除操作的线性表
允许插入和删除的一端定义为栈顶,另一端定义为栈底 不含任何元素的栈称为空栈。栈又称为先进先出的线性表LIFO (last input first output).
理解进栈出栈变化形式
栈的抽象数据类型
Data同线性表 原民俗具有相同的类型,相邻元素具有前驱和后继关系。
operation:InitStack(*S)://初始化操作 建立一个空栈S
DestroyStack(*S)// 若栈存在就销毁他
ClearStack(*S)://将栈清空
StackEmpty(S)://若栈为空返回ture
GetTop(S,*e)://若栈存在且非空 用e返回栈顶元素
Push(*S,e)://若S存在,插入新元素e到栈S中并成为栈顶元素
Pop(*S,*e)://删除栈S中的栈顶元素 并用e返回其值
StackLength(S)://返回S的元素个数
栈的顺序存储结构及实现
栈的顺序存储结构
Status Push (SqStack *S,SElemType e)
{
if(S->top==MAXSIZE-1)
{
return ERROR;
}
S->top++;
S->data[S->top]=e;
return OK;
}
Status Pop(SqStack *S,SElemType *e)
{
if(S->top==-1)
return ERROR;
*e=S->data[S->top];
S->top--;
return OK;
}
两栈共享空间
用一个数组来存储两个栈
关键思路是 他们是在数组的两端 向中间靠拢 栈空:top1=-1,top2=n;
栈1满 top1=n-1 当栈2满 top2=0
栈的链式存储结构及实现
吧栈顶放在单链表的头部 单链表中比较常用的头结点也就失去了意义 。
对于链栈来说基本不存在栈满的情况 链栈的结构代码
typedef struct StackNode
{
SElemType data;
struct StackNode *next;
}StackNode,*LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top;
int count;
}LinkStack;
栈的应用–递归
递归: 把直接调用自己或通过一系列的调用语句直接地调用自己地函数称为递归函数
每个递归定义必须至少有一个条件,满足时递归不再进行,即不再引用自身,而是返回值退出。
栈地应用 四则运算表达式
后缀表示法定义
不需要括号地后缀表达法,逆波兰RPN (reverse polish notation)所有符号都是在要运算数字地后面出现。初始换一个空栈 对要运算的数字进出使用 遇到符号 将前两个数字进行计算 将结果放在栈顶。以此类推到计算结束。
队列的定义
队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表(FIFO)。
循环队列
线性表有顺序存储和链式存储,栈也是线性表,所以有这两种存储方式队列作为一种特殊的线性表,同样存在这两种存储方式。
队列线性存储的不足
为了避免当只有一个元素时,队尾和队头重合使处理变得麻烦,所以引入两个指针,front指针指向队头元素,rear指针指向队尾的下一位置,这样当front等于rear时时空队列。
定义:吧队列这种头尾相接的顺序存储结构称为循环队列。
当队空时rear等于front 队满时rear也等于front 设置一个标志变量flag
通用计算队列公式为(rear-front+QueueSize)%QueueSize
队列的链式存储结构及实现
typedef int QElemType;
typedef struct QNode
{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front,rear;
}LinkQueue;
队列的链式存储结构
入队 直接将Q->rear->next=s; Q->rear=s;
出队 若队列不空 删除Q的队头元素 用e返回其值 否则返回ERROR
p=Q->front->next; //将与删除的队头结点暂存给p
*e=p->data;//赋值给e
Q->front->next=p->next;
if(Q->rear==p)//如果队头等于队尾 删除后将rear指向头结点
{
Q->rear=Q->front;}
free(p);
return OK;
}