栈
栈,仅限定在栈顶(表尾)进行插入和删除的线性表。其操作特性,后进先出。
栈顶(top):表尾端,允许进行插入和删除的一端;
栈底(bottom):表头端,不允许进行插入和删除;
栈的顺序存储结构
栈的顺序存储结构,是指分配一块连续的存储单元,存放栈中的元素,并同时符设一个变量(top)指向当前栈顶的元素。
#define MAXSIZE 20
typedef struct {
Elemtype data[MAXSIZE];
int top;
}SqStack;
栈顶指针:S.top,初始化时为-1,栈顶元素为S.data[S.top]
进栈操作:栈不满是,栈顶指针加1,在将值送人栈顶位置;
出栈操作:栈不空时,先取栈顶指针数据,然后再将栈顶指针减1;
栈空条件:S.top = -1
栈满条件:S.top = MAXSIZE - 1
栈长: S.top + 1
初始化代码:
s.top = -1;
判断栈空代码:
if(s.top == -1)
return true;
else
return false;
进栈操作:
if(S.top == MAXSIZE - 1)
return false;
S.data[++S.top] = x;
出栈操作:
if(S.top == -1)
return false;
x = S.data[S.top--];
栈顶指针指向的元素就是栈顶元素,所以进栈的时候操作是S.data[++S.top] = x; 出栈的时候操作是X = S.data[S.top --];
/************************************************************************************************
顺序栈和链栈的时间复杂度都一样是O(1)。
对于空间性能:
顺序栈需要事先确定固定的长度,肯能出现内存浪费的问题,但是其存取时定位很方便。
链栈则要求每个元素都有指针域,这同时也增加了内存开销,但是链栈可用于长度未知,或无限。
如果栈的使用过程中元素变化不可预料,有时会很小,有时会很大,那么最好是链栈。
反之,如果是在可控范围内,那么建议使用顺序栈会好些。
************************************************************************************************/
#define MAXSIZE 20 //存储空间初始分配量
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
/************************************************************************************************
链栈:栈的链式存储结构(把栈顶放在单链表的头部,通常链栈不需要头结点)
对于链栈,基本上不存在栈满情况,除非内存已经没有可以使用的空间,如果真的发生,此时的操作系统面临死机崩溃的情况。
而不是链栈是否溢出的问题。
对于空栈来说,链表原定义是头指针指向空,那么链栈为空则为top=NULL;
************************************************************************************************/
#include <stdlib.h>
typedef int SElemType; //SElemType 数据类型
typedef int Status;
typedef struct
{
SElemType data;
struct StackNode *next;
}StackNode, *LinkStackPtr;
typedef struct
{
LinkStackPtr top;
int count;
}LinkStack;
// 链栈的进栈操作 O(1)
// 栈顶插入元素,不用判断栈满
Status Push(LinkStack *S, SElemType e)
{
LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode));
s->data = e;
s->next = S->top; // 把当前栈顶元素赋值给新结点的直接后继
S->top = s; // 将新的结点s赋值给栈顶指针
S->count++; // 站内元素个数增加
return OK;
}
// 链栈的出栈操作 O(1)
// 若栈不为空,则删除S的栈顶元素,并返回其值,并返回OK,否则Error
Status Pop(LinkStack *S, SElemType *e)
{
LinkStackPtr p;
if(StackEmpty(*S)) // S->top == NULL
return ERROR;
*e = S->top->data; // 暂存定点元素
p = S->top; // 将栈顶结点赋值给p
S->top = S->top->next; // 把栈顶指针下移一位,指向后一结点
free(p); // 释放结点P,原栈顶指针
S->count--; // 栈总数减1
return OK;
}