栈
栈是线性表,是一种只能在一端进行插入删除的线性表
术语:空栈,栈顶,栈底
示意图
如上图,进栈顺序为1,2,3,4,5
如果要进行出栈,该栈的出栈顺序只能为,4,3,2,1.
栈的特性后进先出,只能从栈顶方向进行插入和删除操作。
在图中,进栈只能从进栈方向插入,出栈只能将栈顶元素删除。
元素进栈出栈只能在栈顶进行操作
同时,栈可以使用两种存储结构实现,顺序栈和链式栈。
常见操作
Initstack(&s):初始化一个空栈S。
StackEmpty(S):判断一个栈是否为空,若栈s为空则返回 true,否则返回 false。
Push(&s,x):进栈,若栈s未满,则将x加入使之成为新栈顶。
Pop(&S,&x):出栈,若栈S非空,则弹出顶元素,并用x返回。
GetTop(S,&x):读栈顶元素,但不出,若栈s非空,则用x返回顶元素。
DestroyStack(&S):销毁栈,并释放栈s占用的存储空间(“&”表示引用调用)。
顺序栈
定义
typedef struct
{
int data[MaxSize];
int top;//指针,指向位置
} SqStack;
采用顺序存储的方式的栈称为顺序栈,利用一组地址连续的存储单元存放自栈底到栈顶的数据元素,同时附加一个指针(top)指向当前元素的位置。
相关操作
初始化
void InitStack(SqStack &S)
{
S.top = -1;
}
初始化只需要让指针指向-1即可
判空操作
bool StackEmpty(SqStack S)
{
if (S.top == -1)
return true;
else
return false;
}
判断指针
插入操作(入栈)
bool Push(SqStack &S, int x)
{
if (S.top == MaxSize - 1)
return false;
S.top = S.top + 1;
S.data[S.top] = x;
return true;
}
首先判断栈是否还有位置,如果有,则在栈顶下一个位置存放元素。
删除操作(出栈)
bool Pop(SqStack &S, int &x)
{
if (S.top == -1)
return false;
x = S.data[S.top];
S.top = S.top - 1;
return true;
}
首先判断栈内是否为空,如不为空,则可进行出栈,这里将出栈元素赋给x,然后指针后移一位
获取栈顶元素
和出栈相似,但不修改指针,只获得x即可
共享栈
利用栈底位置相对不变的特性,可让两个顺序栈共享一个一维数组空间,将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间的中间延伸
两个栈的栈顶指针都指向栈顶元素,top0=-1时0号栈为空,top1=Maxsize时1号栈为空;仅当两个栈顶指针相邻**(top1-top0=1)**时,判断为满。当0号栈进栈时top0先加1再赋值,1号栈进栈时 top1 先减1再赋值;出栈时则刚好相反。
共享栈是为了更有效地利用存储空间,两个栈的空间相互调节,只有在整个存储空间被占满时才发生上溢。其存取数据的时间复杂度均为 0(1),所以对存取效率没有什么影响。
链栈
使用链式存储结构,通常使用单链表实现。
优点是便于多个栈共享存储空间和提高效率,且不存在栈满上溢的情况。
通常使用单链表实现,并规定所有在表头实现(栈顶),这里规定链栈没有头节点,Lhead指向栈顶元素。
相关操作
定义
typedef struct Linknode
{
int data;
struct Linknode *next;
} *LiStack;
初始化
// 初始化栈
bool InitStack(LiStack &S)
{
S = (Linknode *)malloc(sizeof(Linknode));
if (S == NULL)
return false;
S->next = NULL;
return true;
}
入栈
// 压栈
bool Push(LiStack &S, int e)
{
Linknode *newNode = (Linknode *)malloc(sizeof(Linknode));
if (newNode == NULL)
{
return false; // 内存分配失败
}
newNode->data = e;
newNode->next = S;
S = newNode; // 栈顶指针指向新节点
return true;
}
出栈
// 弹栈
bool Pop(LiStack &S, int &e)
{
if (S == NULL)
{
return false; // 栈空
}
Linknode *p = S;
e = p->data;
S = S->next; // 栈顶指针指向下一个节点
free(p); // 释放弹出的节点
return true;
}
获取栈顶元素
// 获取栈顶元素
bool GetTop(LiStack S, int &e)
{
if (S == NULL)
{
return false; // 栈空
}
e = S->data;
return true;
}