1. 栈的定义:
限定仅在表尾进行插入或删除的线性表(后进先出LIFO:Last in , First out)。表头端称为栈底,表尾端称为栈顶。不含元素的空表称为空栈。
2. 栈的建立以及初始化
栈类似于线性表,有两种存储表示方法:顺序栈和链栈。
顺序栈 : 利用一组地址连续的存储单元依次存放字栈底到栈顶的元素,同时附设指针top指示栈顶元素在顺序栈中的位置,top=0为空栈。(栈所需大小难以估计,通常先分派一个基本容量,不够时再追加)
顺序栈的定义:建立一个结构体,包含栈底,栈顶,当前分配的内存空间
typedef struct
{
SDataType *top; //栈顶
SDataType *base; //栈底
int StackSize; //当前已分配的内存空间,以元素为单位
}SqStrack; //此结构体的小名是strack
栈的初始化:
使用 == malloc()==函数,base是栈底指针,始终指向栈底(s.top=s.base为栈空)。top为栈顶指针,top初值指向栈底,每当插入一个元素时top+1,弹出一个元素时top-1,所以,非空栈中的栈底指针始终在栈顶元素的下一个位置。
顺序栈初始化,构造一个空栈
Status InitStack(SqStrack &S)
{
S.base=(SdataType *)malloc(STACK_INI_SIZE*sizeof(SDataType));//给栈分配内存空间
if(!S.base)
{
return OVERFLOW; //如果分配失败,则返回error
}
S.top=S.base; //起初S.base指向S.top的位置,为空栈,之后有元素入栈,top向后移,base永远不变
S.StrackSize=STACK_INIT_SIZE;// 表示栈的内存大小
return OK;
}
3. 判断是否为空栈
当弹出栈顶元素时,需要判断一下栈是否为空防止下溢。(s.top=s.base为栈空标志)
void JudgeNull(SqStack &s)
{
if(s.top==s.base)
printf("此栈为空");
else
printf("此栈不为空");
}
4. 判断是否为满栈
元素入栈前要判断栈是否满栈,防止上溢。StackSize表示当前已经分配的内存空间,可以用s.top-s.base来算当前使用的栈空间,即当s.top-s.base=s.StrackSize时表示满栈。(s.top永远不指向值,s.top指向存储最后一个值的下一个,比如给栈申请了100个空间,s.top指向101,所以栈里存放了100个值)
void JudgeFull(SqStrack &S)
{
if(s.top-s.base==s.StrackSize)
printf("栈满!");
else
printf("栈未满");
}
5. 栈的遍历
void StackPrint(strack *p)
{
while(p->top!=p->base) //栈不为空
{
printf("%c",p->data[p->top-1]); //输出每一个数据
p->top--; //栈顶-1,直到栈为空
}
}
6. 入栈
入栈前判断是否满栈,如果满栈,我们要追加存储空间,元素才能入栈
Status Push(SqStrack &s,SdataType e)
{
SDataType *p;
if(s.top-s.base==s.StackSize)
{
p=(SDataType *)realloc(s.base,(STRACK_INIT_SIZE+STRACKINCREMENT)*sizeof(SDataType));
if(!p)
{
return OVERFLOW;
}
s.base=p;
s.top=s.base+s.StackSize;
s.StackSize+=STACKINCREMENT;
}
*(s.top)=e;
s.top++;
return OK;
}
7. 出栈
出栈时判断栈是否为空栈,若栈已经为空,则返回error。
Status Pop(SqStack &s,SDataType &e)
{
if(s.top!=s.base)
{
s.top--;
e=*(s.top);
}
else return 0;
return e;
}
8. 实现栈:
#include<stdio.h>
#include<malloc.h>
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define OK 1
#define OVERFLOW -2
typedef int SDataType;
typedef int Status;
typedef struct
{
SDataType* base; //栈底
SDataType* top; //栈顶
int StackSize; //当前已分配的内存空间
}SqStack;
Status InitStack(SqStack &S)
{
S.base = (SDataType*)malloc(STACK_INIT_SIZE * sizeof(SDataType));
if (!S.base)
{
return OVERFLOW;
}
S.top = S.base;
S.StackSize = STACK_INIT_SIZE;
return OK;
}
Status Push(SqStack &s, SDataType e)
{
SDataType* p;
if (s.top - s.base == s.StackSize)
{
p = (SDataType*)realloc(s.base, (STACKINCREMENT + STACK_INIT_SIZE) * sizeof(SDataType));
if (!p)
{
return OVERFLOW;
}
s.base = p;
s.top = s.base + s.StackSize;
s.StackSzie += STACKINCREMENT;
}
*(s.top) = e;
s.top++;
return OK;
}
Status Pop(SqStack &s, SDataType &e)
{
if (s.top != s.base)
{
s.top--;
e = *(s.top);
}
else
{
return 0;
}
return e;
}
void judgeNull(SqStack& s)
{
if (s.top == s.base)
printf("此栈为空栈");
else printf("此栈不为空栈");
}
void judgeFull(SqStack& s)
{
if (s.top - s.base == s.StackSize)
printf("栈满");
else printf("栈未满");
}
int main()
{
SqStack s;
SDataType element;
InitStack(s);
for (int i = 1; i <= 10; i++)
{
Push(s, i);
}
judegeNull(s);
judgeFull(s);
printf("出栈:");
while (s.top != s.base)
{
Pop(s, element);
printf("%d ", element);
}
printf("\n");
judgeNull(s);
return 0;
}
还有一种更易理解的方式
#include<stdio.h>
#include<malloc.h>
#include<string.h> //计算所输入数据的长度
//定义栈
typedef struct
{
char data[100];
int top;
int base;
}stack; //给结构体起的小名
//建立栈
stack *StackCreate()
{
stack *p=(stack*)malloc(sizeof(stack)); //分配空间
if(p==NULL)
{
printf("建立失败!");
return 0;
}
else p->base=p->top=0; //分配成功
return p;
}
//入栈
void StackInput(stack *p,char str)
{
p->data[p->top]=str; //数据进栈
p->top++; //栈顶向上走
}
//出栈
char StackOutput(stack *p,char str)
{
if(p->top!=p->base) //栈非空
{
str=p->data[p->top]; //栈顶的数据先出栈
p->top--; //栈顶-1
return str; //返回所出栈的元素
}
}
//输出
void StackPrint(stack *p)
{
while(p->top!=p->base)
{
printf("%c",p->data[p->top-1]); //栈顶不存放数据,p->top-1存放栈的最后一个数据
p->top--;
}
}
//主函数
int main()
{
stack *p;
char a[10]="abcde";
p=StackCreate(); //调用建立栈的函数
for(int i=0;i<strlen(a);i++)
{
StackInput(p,a[i]); //元素入栈
}
printf("输出栈中的所有字符:");
StackPrint(p); //调用输出栈的函数
return 0;
}