1.1栈的定义和特点
栈:是限定在表尾进行插入和删除的线性表。
对于栈来说,表尾为栈顶,表头为栈底;不含元素的为空栈(注意空栈的判断)
特点:后进先出,从上往下逐个取用。
1.2栈的类型定义
基本操作:
Initstack(&S)//构造空栈
DestroyStack(&S)//销毁一个栈
ClearStack(&S)//将栈变为空栈
StackEmpty(S)//判断栈是否为空栈
StackLength(S)//查询栈的长度
GetTop(S)//返回栈顶的元素
Push(&S,e)//插入新的栈顶元素
Pop(&S,&e)//删除栈顶元素,并用e返回其值
StackTraverse(s)//对栈中的元素进行依次访问
1.3栈的表示和实现
1顺序表
1)存储定义
#define MAXSIZE 100
#define OVERFLOW 0
#define OK 1
#define ERROR -1
typedef struct
{
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
2)初始化
分配一个大容量的存储空间,栈底与栈定相同。
Status Initstack(SqStack &S)//构造一个空栈;每次之前都先考虑是否为空
{
S.base=new SElemType[MAXSIZE];//给顺序栈分配一个最大容量
if(!S.base)//空的话返回错误
{
exit(OVERFLOW);
}
S.top=S.base;//注意栈顶与栈低的关系
S.stacksize=MAXSIZE;
return OK;
}
3)入栈
就是在栈顶插入新的元素。
//入栈(在栈顶插入新的元素)
Status Push(SqStack &S,SElemType e)
{
if(S.top-S.base==S.stacksize)//首先得判断栈是否是满的
{
return ERROR;
}
*S.top=e;//这里与前面栈顶与栈底的关系有关
S.top=S.top+1;
}
4)出栈
就是将栈顶元素删除。
Status Pop(SqStack &S,SElemType &e)
{
if(S.base==S.top)//判断栈是否为空
{
return ERROR;
}
S.top=S.top-1;//栈顶现在是空的,需要退回栈顶的前一个元素
e=*S.top;
return OK;
}
5)取栈顶元素
其实就是将栈顶元素返回就行。
//取栈顶元素
Status GetTop(SqStack S)
{
if(S.base==S.top)//判断栈是否为空
{
return ERROR;
}
else
{
return *(S.top-1);
}
}
其实顺序栈跟顺序表优缺点特别相似,容易受大容量限制。
2链表
1)存储结构(跟单链表特别类似)
typedef struct StackNode
{
ElemType data;
struct StackNode *next;
}StackNode,*LinkStack;
2)初始化(构造一个空栈)
Status Initstack(LinkStack &S)
{
S=NULL;//将指针指为空
return OK;
}
3)入栈(涉及到链表或者链栈的时候画两个表格更容易理解)
Status Push(LinkStack &S,SElemType e)//这个不需要判断栈是否为满
{
p=new StackNode;
p->data=e;
p->next=S;//这个是在S的前面插入的;我感觉在他的后面插入也可以S->data=p,p->next=NULL=S;
S=p;
return OK;
}
4)出栈
Status Pop(LinkStack &s,SElemType &e)
{
if(S==NULL)
{
return ERROR;
}
e=S->data;
p=S;
S=S->next;//这个跟从面插入是有关系的,方便出栈;
delete p;//c中free
return OK;
}
5)取栈顶元素
SElemType GetTop(LinkStack S)
{
if(S!=NULL)//判断栈是否为空
return S->data;//这个跟顺序表中位置不一样,控制栈顶指针S保持不变
}
顺序栈与链栈的优缺点可以参考顺序表与链表,两者大致相似,只是在于栈与表的本质特点上略有差别。
以上就是栈的相关定义、特点和算法。