《栈》
Posted xiangzhong-com
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《栈》相关的知识,希望对你有一定的参考价值。
《栈》
目录:
1.栈的定义
2.栈的抽象数据类型
3.顺序栈
4.链栈
1.栈的定义
- 栈(Stack)是限定仅在表尾进行插入和删除的线性表。
- 我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom)。
- 不含任何数据元素的栈称为空栈。
- 栈为后进先出(Last In First Out)的线性表,简称LIFO结构。(如图1所示)
图1
- 栈的插入操作,叫做压入栈(push),或压栈。
- 栈的删除操作,叫做弹出栈(pop),或弹栈。
2.栈的抽象数据类型
类型名称:堆栈(Stack).
数据的对象集合:一个有0个或多个的元素的有求线性表。
操作集:对于一个具体的长度为正整数MaxSize的堆栈S属于Stack,记堆栈中的任意一个元素X属于ElementType,堆栈的基本操作主要有:
Stack CreateStack(int MaxSize);生成空堆栈,其最大长度为MaxSize。
bool IsFull(Stack S);判断堆栈S是否已满。
bool IsEmpty(Stack S); 判断堆栈S是否是空。
bool Push(Stack S,ElementType X);入栈。
ElementType Pop(Stack S);出栈。
3.顺序栈
一. 栈的顺序存储实现
#include<stdio.h>
#include<stdlib.h>
#define true 1
#define ERROR 0
#define false 0
typedef int bool;
typedef int ElementType;
typedef int Position;
typedef struct SNode* PtrToSNode;
typedef PtrToSNode Sequence_Stack;
struct SNode
{
ElementType* Data;//存储元素的数组
Position top;//栈顶指针
int MaxSize;//顺序栈的最大容量
};
Sequence_Stack CreateStack(int MaxSize);
bool IsFull(Sequence_Stack S);
bool IsEmpty(Sequence_Stack S);
bool Push(Sequence_Stack S,ElementType X);
ElementType Pop(Sequence_Stack S);
int main()
{
printf("请您输入您要输入多少数!\\n");
int n = 0;
int i = 0;
scanf("%d", &n);
Sequence_Stack S = CreateStack(n);
int m = 0;
while(i < n)
{
scanf("%d", &m);
Push(S,m);
i++;
}
i = 0;
while(i < n)
{
printf("%d\\n", Pop(S));
i++;
}
return 0;
}
Sequence_Stack CreateStack(int MaxSize)
{
Sequence_Stack S = (Sequence_Stack)malloc(sizeof(struct SNode));
S->Data = (ElementType*)malloc(MaxSize*sizeof(ElementType));
S->top = -1;
S->MaxSize = MaxSize;
return S;
}
bool IsEmpty(Sequence_Stack S)
{
if(S->top == -1)
{
return true;
}
else
{
return false;
}
}
bool IsFull(Sequence_Stack S)
{
if(S->top == S->MaxSize-1)
{
return true;
}
else
{
return false;
}
}
bool Push(Sequence_Stack S, ElementType X)
{
if(IsFull(S))
{
printf("顺序栈满!\\n");
return false;
}
else
{
S->top++;
S->Data[S->top] = X;
//简洁版:S->Data[++(S->top)] = X;
return true;
}
}
ElementType Pop(Sequence_Stack S)
{
if(IsEmpty(S))
{
printf("顺序栈空!\\n");
return false;
}
else
{
S->top--;
return S->Data[S->top+1];
//简洁版:return S->Data[(S->top)--];
}
}
二. 栈的共享顺序存储实现
通常,当两个栈的空间需求有相反关系时,也就是一个栈增长时另一个栈在缩短的情况下,可以使用两栈共享空间。
#include<stdio.h>
#include<stdlib.h>
#define true 1
#define ERROR 0
#define false 0
typedef int bool;
typedef int ElementType;
typedef int Position;
typedef struct SNode* PtrToSNode;
typedef PtrToSNode Sequence_Share_Stack;
struct SNode
{
ElementType* Data;//存储元素的数组
Position top1;//堆栈1的栈顶指针
Position top2;//堆栈2的栈顶指针
int MaxSize;//顺序栈的最大容量
};
Sequence_Share_Stack CreateStack(int MaxSize);
bool Push(Sequence_Share_Stack S, ElementType X, int Tag);
ElementType Pop(Sequence_Share_Stack S, int Tag);
int main()
{
//请读者根据自己的需求来完善代码,这里已经把共享栈搭建好了!
return 0;
}
Sequence_Share_Stack CreateStack(int MaxSize)
{
Sequence_Share_Stack S = (Sequence_Share_Stack)malloc(sizeof(struct SNode));
S->Data = (ElementType*)malloc(MaxSize*sizeof(ElementType));
S->top1 = -1;
S->top2 = S->MaxSize;
S->MaxSize = MaxSize;
return S;
}
bool Push(Sequence_Share_Stack S, ElementType X, int Tag)
{
if(S->top2 - S->top1 == 1)
{
printf("共享栈满!\\n");
return false;
}
else
{
if(Tag == 1)
{
S->Data[++(S->top1)] = X;
}
else
{
S->Data[--(S->top2)] = X;
}
return true;
}
}
ElementType Pop(Sequence_Share_Stack S, int Tag)
{
if(Tag == 1)
{
if(S->top1 == -1)
{
printf("栈1空\\n");
}
else
{
return S->Data[(S->top1)--];
}
}
else
{
if(S->top2 == S->MaxSize)
{
printf("栈2空\\n");
}
else
{
return S->Data[(S->top2)++];
}
}
}
4.链栈
栈的链式存储实现
//链栈基本结构已搭建好了,用斐波那契函数来完善了链栈的实现
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
typedef int bool;
typedef int SElemType;
typedef struct StackNode
{
SElemType data;
struct StackNode *next;
}StackNode,*LinkStackPtr;
typedef struct
{
LinkStackPtr top; /*栈顶指针*/
int count; /* 链栈元素个数*/
}LinkStack;
LinkStack* InitStack();
bool Push(LinkStack *S,SElemType e);
bool Pop(LinkStack *S,SElemType *e);
int Fbi(int i);
void Fbistore();
int main()
{
Fbistore();
return 0;
}
LinkStack* InitStack()
{
LinkStack* s = (LinkStack*)malloc(sizeof(LinkStack));
if(!s)
{
printf("内存分配失败!\\n");
return NULL;
}
memset(s, 0x00, sizeof(LinkStack));
return s;
}
//进栈
bool Push(LinkStack *S,SElemType e)
{
LinkStackPtr s=(LinkStackPtr)malloc(sizeof(StackNode));
s->data=e;
s->next=S->top; /* 把当前的栈顶元素赋值给新结点的直接后继,见图中① */
S->top=s; /* 将新的结点s赋值给栈顶指针,见图中② */
S->count++;
return OK;
}
//出栈
bool Pop(LinkStack *S,SElemType *e)
{
LinkStackPtr p;
if(S->count == NULL)
return ERROR;
*e=S->top->data;
p=S->top; /* 将栈顶结点赋值给p,见图中③ */
S->top=S->top->next; /* 使得栈顶指针下移一位,指向后一结点,见图中④ */
free(p); /* 释放结点p */
S->count--;
return OK;
}
int Fbi(int i) /* 斐波那契的递归函数 */
{
if( i < 2 )
return i == 0 ? 0 : 1;
/* 这里Fbi就是函数自己,等于在调用自己 */
return Fbi(i - 1) + Fbi(i - 2);
}
void Fbistore()
{
//初始化一个空栈
LinkStack* s = InitStack();
int a = 0;
int m = 0, i = 0;
scanf("%d", &m);
while(i <= m)
{
Push(s, Fbi(i));
i++;
}
while(s->count != 0)
{
Pop(s, &a);
printf("%d ", a);
}
printf("\\n");
}
接下来将发布栈的几个具体应用(表达式求值 迷宫问题)
以上是关于《栈》的主要内容,如果未能解决你的问题,请参考以下文章
虚拟内存[02] Linux 中的各种栈:进程栈 线程栈 内核栈 中断栈
Android UICanvas 画布 ① ( Canvas 状态栈 | Canvas 状态栈入栈与出栈 | 获取 Canvas 状态栈容量 | Canvas 状态栈原点数据 )