堆栈
栈是一种特殊的线性表,具有LIFO(LAST IN FIRST OUT)的性质,栈或许是除了数组之外应用最广的数据结构了。许多操作都需要借助栈来实现:浏览网站的“后退”键;WORD、PS中的撤销(CTRL+Z)等等——限定在表尾进行插入(入栈)、删除(出栈)操作的线性表。
堆栈的顺序存储实现
定义:
typedef int Position;
typedef struct SNode * PtrToSNode;
struct SNode {
ElementType *Data;
Position Top;
int MaxSize;
};
typedef PtrToSNode Stack;
在栈的定义中,不理解的地方在于为什么不直接用
Data[MaxSize]
这样的格式来直接定义栈中的数据区,而要用如上所示的首地址来表达数组。
2020/02/25编辑:Data[MaxSize]在ANSI C的标准中不被允许,原因是变量名不能用在数组的定义中(即Maxsize不能用在方括号中)。
自然的另一种定义方式:
#define MaxSize
typedef int Position;
typedef struct SNode * PtrToSNode;
struct SNode{
ElementType Data[MaxSize]
Position Top;
};
typedef struct PtrToSNode Stack;
数组长度由MaxSize决定,在开头由用户自定义。
初始化
//在第一种定义前提下,此初始化可以申请动态数组,或许这就是第一种定义方式的用意所在吧。
Stack CreateStack(int MaxSize)
{
Stack S=(Stack)malloc(sizeof(struct SNode));
S->Data=(ElementType*)malloc(MaxSize*sizeof(ElementType));/*此操作是申请动态数组*/
S->Top=-1;
S->MaxSize=MaxSize;
return S;
}
入栈(PUSH)
在入栈之前首先要判断栈区是否已满,如果不满,把Top+1,再将新元素放入Data数组的Top位置。
bool IsFull(Stack S)
{
return(S->Top==MaxSize-1);
}
bool Push(Stack S,ElementType X)
{
if(IsFull(Stack S)){
printf("堆栈已满");
return false;
}
else{
(S->Top)=(S->TOP)+1;
S->Data[(S->Top)]=X;
return true;
}
}
出栈(POP)
和入栈一样,在执行出栈操作之前首先要判断栈区是否为空,若不空,可以直接让程序返回Data[Top],再将Top-1,否则返回一个错误标志,这个值必须是正常的栈元素数据不可能取到的值。
bool IsEmpty(Stack S)
{
return (S->Top==-1);
}
ElementType Pop(Stack S)
{
if(IsEmpty(Stack S))
{
printf("堆栈空了");
return ERROR;
}
else { //以下语句可以用:return (S->Data[(S->Top)--]); 代替。
ElementType s=S->Data[(S->Top)];
(S->Top)=(S->Top)-1;
return s;
}
}
用一个数组实现两个堆栈的例子
一个思想是让这两个栈分别从数组的两头开始往中间生长,这样可以尽可能的提高空间利用率。
双堆栈的定义
typedef int Position;
typedef struct SNode* PtrToSNode;
struct SNode{
ElementType* Data;
Position Top1;
Position Top2;
int MaxSize;
};
typedef PtrToSNode Stack;
双堆栈的创建
Stack CreateDoubleStack(int MaxSize)
{
Stack S=(Stack)malloc(sizeof(struct SNode));
S->Data=(ElementType*)malloc(MaxSize*sizeof(ElementType));
S->Top1=-1;
S->Top2=MaxSize-1;
S->MaxSize=MaxSize;
return S;
}
双堆栈的主要操作
//入栈
//C语言在C99之后新引入了bool这个关键字,只要在开头添加stdbool.h这个头文件就可以和C++一样使用bool了
bool Push(Stack S,ElementType X, int Tag)
{
if(S->Top1+1==S->Top2){
printf("堆栈满了\n");
return false;
}
else {
if(Tag==1)
S->Data[++(S->Top1)]=X;
else
S->Data[--(S->Top2)]=X;
return true;
}
}
//出栈
ElementType Pop(Stack S,int Tag)
{
if(Tag==1){
if(S->Top1==-1){
printf("堆栈1已经空了\n");
return ERROR;
}
else
return(S->Data[(S->Top1)--]);
}
else{
if(S->Top2==MaxSize){
printf("堆栈2已经空了\n");
return ERROR;
}
else
return(S->Data[(S->Top2)++]);
}
}