此处的堆栈仅仅指数据结构中的堆栈,而非在程序存储时的堆和栈。
堆栈(Stack)可以认为是一种有一定约束的线性表。插入和删除操作都只能在栈顶进行。比如在洗碗时放碗的时候,新洗完的碗都放在顶部,取走碗时也是从顶部取走。
因为堆栈有此特性,所以将其称为“后入先出”(Last In First Out)表。
一、堆栈的抽象数据类型描述
数据对象集:一个有多个或零个元素的有穷线性表
操作集:生成空堆栈、判断堆栈是否已满、压入堆栈、判断堆栈是否为空、删除并返回栈顶元素
二、栈的顺序存储(顺序栈)
栈的顺序存储结构通常是由一个一维数组和一个记录栈顶元素位置的变量组成的。Top指向-1时表示空栈,Top指向Maxsize-1时表示满栈。
typedef struct{
ElementType Data[MaxSize];
int Top;
}Stack;
(1)入栈(Push)
操作步骤:
判断栈是否已满
若不满,Top加1
将新元素放入Data数组的Top分量中
代码实现:
void Push(Stack *PtrS, ElementType item)
{
if ( PtrS -> Top == MaxSize - 1) //判断栈是否已满
{
printf("堆栈已满") ;
return ;
}
else
{
PtrS -> Data[ ++ ( PtrS -> Top )] = item; //将新元素放入对应的Data数组中
return ;
}
}
(2)出栈(Pop)
操作步骤:
判断栈是否为空
若不空返回Data[Top],同时将Top减1
代码实现:
void Pop(Stack *PtrS)
{
if ( PtrS -> top == -1) //判断栈是否为空
{
printf("堆栈空");
return ERROR;
}
else
{
PtrS -> Data[ ( PtrS -> Top ) --]; //将栈顶元素删除
return;
}
}
三、堆栈的链式存储(链栈)
链栈与单向链表相似,只是操作受限,只能在链栈的栈顶进行插入或删除操作。有时为了方便链栈也可以附带一个空的表头结点,表头结点后面的第一个结点就是链栈的栈顶结点,栈中其他结点通过他们的指针next链接起来,栈底结点的next为NULL
代码实现:
typedef struct SNode *PtrToSNode;
struct SNode {
ElementType Data;
PtrToSNode Next;
};
typedef PtrToSNode Stack;
Stack CreateStack( )
{ /* 构建一个堆栈的头结点,返回该结点指针 */
Stack S;
S = (Stack)malloc(sizeof(struct SNode));
S->Next = NULL;
return S;
}
bool IsEmpty ( Stack S )
{ /* 判断堆栈S是否为空,若是返回true;否则返回false */
return ( S->Next == NULL );
}
bool Push( Stack S, ElementType X )
{ /* 将元素X压入堆栈S */
PtrToSNode TmpCell;
TmpCell = (PtrToSNode)malloc(sizeof(struct SNode));
TmpCell->Data = X;
TmpCell->Next = S->Next;
S->Next = TmpCell;
return true;
}
ElementType Pop( Stack S )
{ /* 删除并返回堆栈S的栈顶元素 */
PtrToSNode FirstCell;
ElementType TopElem;
if( IsEmpty(S) ) {
printf("堆栈空");
return ERROR;
}
else {
FirstCell = S->Next;
TopElem = FirstCell->Data;
S->Next = FirstCell->Next;
free(FirstCell);
return TopElem;
}
}