栈
栈(Stack):是只允许在一端进行插入或删除的线性表。首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作。
栈顶(Top):线性表允许进行插入删除的那一端。
栈底(Bottom):固定的,不允许进行插入和删除的另一端。
空栈:不含任何元素的空表。
栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构
顺序栈
定义:顺序栈是指利用顺序存储结构实现的栈,即利用一组地址连续的存储单元(数组)依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置。
#define MAXSIZE 100 //顺序栈存储空间的初始分配量typedef struct
{
SElemType *base;
SElemType *top; //栈顶指针
int stacksize;
}SqStack;
说明:base为栈底指针,初始化完成后,栈底指针base始终指向栈底的位置,若base的值为NULL,则表明栈结构不存在。top为栈顶指针,其初值指向栈底。每当插入新的栈顶元素时,指针top增1;删除栈顶元素时,指针top减1。
1、顺序栈的初始化
【算法步骤】
①为顺序栈动态分配一个最大容量为MAXSIZE的数组空间,使base指向
这段空间的基地址,即栈底。
②栈顶指针top初始为base,表示栈为空。
③ stacksize置为栈的最大容量MAXSIZE。
Status InitStack(SqStack *S)
{
S->base= (SElemType *)malloc(MAXSIZE *sizeof(SElemType));
if(!S->base) return false;
S->top=S->base;
S->stacksize=MAXSIZE;
return OK;
}
2、顺序栈的入栈
【算法步骤】
①判断栈是否满,若满则返回ERROR。
②将新元素压入栈顶,栈顶指针加1。
Status Push(SqStack *S,SElemType e)
{
if(S->top-S->base==S->stacksize) return error;
*s->top=e;
S->top++;
return OK;
}
3、顺序栈的出栈
【算法步骤】
①判断栈是否空,若空则返回ERROR。
②栈顶指针减1,栈顶元素出栈。
Status Pop(SqStack *S,SElemType *e)
{
if(S->top==S->base) return error;
S->top--;
*e=*S->top;
return OK;
}
4、取栈顶元素
SElemType GetTop(SqStack S)
{
if(S->top!=S->base)
return *(S->top-1);
}
链栈
定义:采用链式存储的栈称为链栈,链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。通常采用单链表实现,并规定所有操作都是在单链表的表头进行的。
typedef struct StackNode
{
ElemType data;
struct StackNode *next;
}StackNode,*LinkStack;
1、链栈的初始化
【说明】:链栈的初始化操作就是构造一个空栈,因为没必要设头节点,所以直接将栈顶指针置空即可。
Status InitStack(LinkStack *S)
{
S=NULL;
return OK;
}
2、链栈的入栈
【算法步骤】
①为入栈元素e分配空间,用指针p指向。
②将新节点数据域置为e。
③将新节点插入栈顶。
④修改栈顶指针为p。
Status Push(LinkStack *S, SElemType e)
{
StackNode *p=(StackNode*)malloc(sizeof(StackNode));
p->data=e;
p->next=S;
S=p;
return OK;
}
3、链栈的出栈
【算法步骤】
①判断栈是否为空,若空则返回ERROR。
②将栈顶元素赋给e。
③临时保存栈顶元素的空间,以备释放。
④修改栈顶指针,指向新的栈顶元素。
⑤释放原栈顶元素的空间。
Status Pop(LinkStack *S,SElemType *e)
{
if(!S) return error;
*e=S->data;
StackNode *p=S;
S=S->next;
free(p);
return OK;
}
4、取栈顶元素
SElemType GetTop(LinkStack S)
{
if(S)
return S->data;
}
pta—栈
6-1 另类堆栈
分数 15
作者 DS课程组
单位 浙江大学
在栈的顺序存储实现中,另有一种方法是将Top定义为栈顶的上一个位置。请编写程序实现这种定义下堆栈的入栈、出栈操作。如何判断堆栈为空或者满?
函数接口定义:
bool Push( Stack S, ElementType X );
ElementType Pop( Stack S );
其中Stack
结构定义如下:
typedef int Position;
typedef struct SNode *PtrToSNode;
struct SNode {
ElementType *Data; /* 存储元素的数组 */
Position Top; /* 栈顶指针 */
int MaxSize; /* 堆栈最大容量 */
};
typedef PtrToSNode Stack;
注意:如果堆栈已满,Push
函数必须输出“Stack Full”并且返回false;如果队列是空的,则Pop
函数必须输出“Stack Empty”,并且返回ERROR。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
#define ERROR -1
typedef int ElementType;
typedef enum { push, pop, end } Operation;
typedef enum { false, true } bool;
typedef int Position;
typedef struct SNode *PtrToSNode;
struct SNode {
ElementType *Data; /* 存储元素的数组 */
Position Top; /* 栈顶指针 */
int MaxSize; /* 堆栈最大容量 */
};
typedef PtrToSNode Stack;
Stack CreateStack( int MaxSize )
{
Stack S = (Stack)malloc(sizeof(struct SNode));
S->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
S->Top = 0;
S->MaxSize = MaxSize;
return S;
}
bool Push( Stack S, ElementType X );
ElementType Pop( Stack S );
Operation GetOp(); /* 裁判实现,细节不表 */
void PrintStack( Stack S ); /* 裁判实现,细节不表 */
int main()
{
ElementType X;
Stack S;
int N, done = 0;
scanf("%d", &N);
S = CreateStack(N);
while ( !done ) {
switch( GetOp() ) {
case push:
scanf("%d", &X);
Push(S, X);
break;
case pop:
X = Pop(S);
if ( X!=ERROR ) printf("%d is out\n", X);
break;
case end:
PrintStack(S);
done = 1;
break;
}
}
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
4
Pop
Push 5
Push 4
Push 3
Pop
Pop
Push 2
Push 1
Push 0
Push 10
End
输出样例:
Stack Empty
3 is out
4 is out
Stack Full
0 1 2 5
答案:
bool Push( Stack S, ElementType X ) {
if (S->Top == S->MaxSize) {
printf("Stack Full\n");
return false;
}
S->Data[S->Top++] = X;
return true;
}
ElementType Pop( Stack S ) {
if (S->Top == 0) {
printf("Stack Empty\n");
return ERROR;
}
return S->Data[--S->Top];
}