数据结构(堆栈)

堆栈和队列:
堆栈的定义:堆栈和队列是两种在操作上受限制的线性表。有的书上,称堆栈和队列为限定性数据结构。
堆栈的概念及其操作:
堆栈(stack)简称为栈。它是一种只允许在表的一端进行插入和删除操作的线性表。允许操作的一端称为栈顶,栈顶元素的位置由一个称为栈顶指针的变量(不妨用top命名该变量)给出。另一端称为栈底。当表中没有元素时称为空栈。
栈的插入操作称为入栈或进栈,删除操作称为出栈或退栈。
元素进入堆栈或者退出堆栈是按照”后进先出“的原则进行的,也称堆栈为后进先出表或者下推表。
堆栈的基本操作:
1.初始化一个堆栈
2.测试堆栈是否为空栈
3.测试堆栈是否已经满了
4.在堆栈的顶端位置插入一个新的数据元素,简称进栈或者入栈。
5.删除堆栈的栈顶元素,简称出栈或者退栈。
6.取当前栈顶元素
堆栈的顺序存储结构:一般采用顺序存储结构的堆栈简称为顺序堆栈。
堆栈的基本算法:
#define M 100
ElemType stack[M]
Int top;
1.初始化一个堆栈
Void initials(int &top)
{
return top=-1;
}
2.测试堆栈是否为空
Int emptys(int top)
{
return top==-1;
}
3.测试堆栈是否已满
Int Fulls(int top)
{
return top==M-1;
}
4.取当前栈顶元素
将当前栈顶元素取出送出变量item,该操作的前提是堆栈不空。
Int gettops(elemType stack[],int top,elemType &item)
{
If(Fulls(top))
return 0;
else
{
item =Stack[top];
Return 1
}
}
5.插入(进栈)
Int push(elemType stack[],int &top,elemType item)
{
If(Fulls(top))
return 0;
else
{
stack[++top]=item ;
Return 1
}
}

6.删除(退栈)
Int pop(elemType stack[],int &top,elemType &item)
{
If(emptys(top))
return 0;
else
{
item=stack[top–] ;
Return 1;
}
}
多个栈共享连续的空间:
栈共享示意图
栈1 共享空间 栈2
栈一是从栈底开始的,而栈二是从栈顶开始(其实都是栈底)栈一的位置为stack[0],栈二为stack[MaxSize-1];通过观察,只有当栈一和栈二的栈顶指针相遇时,这两个栈才满了,溢出来了。
忘了交代一下,这两个栈的栈顶指针相加正好为MaxSize-1;
将item插入第i个堆栈的算法:
int push2(ElemType stack[], int top[], int i, ElemType item)
{
if (top[0] == top[1] - 1)
{
return 0;//堆栈已经满了,插入失败
}
else {
if (i == 1)
top[0]++;
else
top[1]++;
stack[top[i - 1]] = item;//插入新的数据元素
return 1;//插入成功
}
}
删除第i个元素:
int pop2(ElemType stack[], int top[], int i, ElemType item)
{
if (i == 1)
{
if (top[0] == -1)
return 0;//堆栈1为空,删除失败
else {
item = stack[top[0]–];
return 1;//堆栈1非空,删除成功
}
}
else
{
if (top[1] == M)
return 0;
else {
item = stack[top[1]++];
return 1;
}
}
}
堆栈的链式存储结构:
通常称为链接堆栈,简称为链栈。
链接堆栈的构造:
链接堆栈就是采用一个线性链表实现一个堆栈结构
链式堆栈的定义类型:
Typedef sturct node{
SElemTypedef data;
Struct node *link;
}STNode,*STLink
链接堆栈的基本算法
1.链接堆栈初始化
Void initialSlink(STLink &top)
{
Top=null;
}
2.测试链接堆栈是否为空
Int emptyslink(STLink top)
{
Return (top==null);
}
3.取当前栈顶元素
Int GettopSLink(STLink top,SElemType &item)
{
//top指向栈顶元素所在的链接点
If(EmptySLink(top))
Return 0;//堆栈为空
Else {
Item=top->data;
Return 1;
}
}
4.链接堆栈的插入:
#define LEN sizeof(STNode)
Int pushLink(STLink &top,SElemTypy item)
{
//top指向栈顶元素所在的链接点
STLink p;
If(!(p=(STLink)malloc(LEN)))
Return 0;
Else{
P->data=item;
p->link=top;
top=p;
return 1;
}
}
6.链接堆栈删除:
Int POPLink(STLink &top,SElemType &item)
{
//top指向栈顶元素所在的链接点
STLink p;
If(emptyslink(top))
return 0;//堆栈为空,返回失败
else{
P=top;
Item=p->data;//保存被删除节点的信息
top=top->link;
free§;//释放被删除节点a
return 1;//堆栈非空,删除成功返回1
}
}
堆栈的应用举例:
1.符号匹配检查
核心思想:
首先创建一个空的堆栈,依次读入字符直到文件末尾
如果读取的字符为左花括号或者左圆括号,则将其压入堆栈,如果读取的字符为右花括号或者右圆括号,而此时堆栈为空,则出现不匹配现象,报告错误;否则退出当前栈顶元素。如果退出的栈顶符号不是对应的左括号或者左圆括号,则出现不匹配,报告错误,读到文件末尾,若堆栈非空,则报告错误。
2.数值转换
把一个十进制数转化为八进制过程可以是反复执行以下操作:
1.将num除以8,取其余数
2.判断商是否为0,若商为0,则转换到此结束,若商不为0,则将商送nun,并转到第一步。
堆栈采用顺序存储结构,则算法如下:
Void Conversion(int num)
{
Int stack[M],top=-1;
do{
Stack[++top]=num%8;
Num=num/8;
}while(num!=0);
}
While(toq>0)
{
Printf(“%d”,stack[top–]);
}
若堆栈采用链式存储结构,则算法如下:
Void Conversion(int num)
{
STLink p,top=null;
do{
P=(STLink)malloc(sizeof(STNode));
P->data=num%8;
P->link=top;
top=p;
num=num/8;
}while(num!=0);
While(top!=Null)
{
P=top;
Printf(“%d”,p->data);
top=top->link;
free§;
}
}
堆栈在递归中的应用:
在算法设计程序过程中,把一个通过算法调用语句直接或间接调用自己的算法称为递归算法。
一个递归的定义必须具有确切的含义。
递归过程的实现:
1.保存调用信息,其中主要是返回地址信息和实参信息
2.分配调用过程中需要的数据区
3.把控制转移到被调用的过程入口
当被调用算法运行结束需要返回到调用算法时,一般也分为以下三个步骤:
1.保存返回时的有关信息,如计算结果等。
2.释放被调用算法占用的数据区
3.把执行控制按调用时保存的返回地址转移到调用算法中调用语句的下一条语句。
表达式的计算:
后缀表达式的特点:
1.后缀表达式与中缀表达式中运算对象的先后次数相同,只是所读到的运算符的先后次序可能有所变化。
2.后缀表达式不出现括号。
三.趣味游戏——迷宫
#define MaxN 100
#define MaxMN 10000
int Mazepath(int maze[][MaxN], int m, int n)
{
int stack[MaxMN][3];
int move[8][2] = { {-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
int p, i,j, k, g, h, top = 0;
maze[1][1] = 2;//maze[1][1]置一个非零非1的整数
stack[0][0] = 1;
stack[0][1] = 1;
stack[0][2] = 1;
while (top >= 0)
{
i = stack[top][0];
j = stack[top][1];
k = stack[top–][2] + 1;//k 为方向数,初值为2(东)
while (k < 8)
{
g = i + move[k][0];
h = j + move[k][1];
if (g == m - 2 && h == n - 2 && maze[g][h] == 0)//若到了迷宫出口处
{
printf(“找到一条通路”);
for ( p = 0; p <=top; p++)
{
printf("%3d %3d",stack[p][0],stack[p][1]);
}
printf("%3d %3d",i,j);
printf("%3d %3d", m-1, n-1);
return 1;
}
if (maze[g][h] == 0)
{
maze[g][h] = 2;
stack[++top][0] = i;
stack[top][1] = j;
stack[top][2] = k;
i = g;//获得一个新位置
j = h;
k = 0;
}
k++; //试试下一个方向
}
}
printf(“没有发现通路”);
return 0;//没有找到通路
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值