栈的顺序存储结构
栈的顺序存储结构的定义
#include "stdafx.h"
#define MAXSIZE 100
//SElemType类型根据实际情况而定,这里假设为int
typedef int SElemType;
typedef struct
{
SElemType data[MAXSIZE];
//用于栈顶指针
int top;
}SqStack;
进栈操作
//插入元素e为新的栈顶元素
bool Push(SqStack *S, SElemType e) {
//栈满
if (S->top == MAXSIZE - 1) {
return false;
}
//栈顶指针增加1
S->top++;
//将新插入元素赋值给栈顶空间
S->data[S->top] = e;
return true;
}
出栈操作
//若栈不空,则删除S的栈顶元素,用e返回其值,并返回true,否则返回false
bool Pop(SqStack *S, SElemType *e) {
if (S->top == -1)
return false;
//将要删除的栈顶元素赋值给e
*e = S->data[S->top];
//栈顶指针减一
S->top--;
return true;
}
时间复杂度
栈的入栈和出栈的时间复杂度是O(1)。
俩栈共享空间
数组有俩个端点,俩个栈有俩个栈底,让一个栈的栈底为数组的始端,即下标为0处,另一个栈为栈的末端,即下标为数组长度n-1处。这样,俩个栈如果增加元素,就是俩端点向中间延伸。
俩栈共享空间的结构定义
//俩栈共享空间结构
typedef struct {
SElemType data[MAXSIZE];
//栈1栈顶指针
int top1;
//栈2栈顶指针
int top2;
}SqDoubleStack;
俩栈共享空间的入栈操作
//插入元素e为新的栈顶元素
bool Push(SqDoubleStack *S, SElemType e, int stackNumber) {
//栈已满,不能再push新元素
if (S->top1 + 1 ==S->top2)
return false;
//栈1有元素进栈
if (stackNumber == 1)
//若栈1则先top1+1后给数组元素赋值
S->data[++S->top1] = e;
//栈2有元素进栈
else if (stackNumber == 2)
//若栈2则先top2-1后给数组元素赋值
S->data[--S->top2] = e;
return true;
}
俩栈共享空间的出栈操作
//若栈不空,则删除S的栈顶元素,用e返回其值,并返回true,否则返回false
bool Pop(SqDoubleStack *S, SElemType *e, int stackNumber) {
if (stackNumber == 1) {
if (S->top1 == -1) {
//说明栈1已经是空栈,溢出
return false;
}
//将栈1的栈顶元素出栈
*e = S->data[S->top1--];
}
else if (stackNumber == 2) {
if (S->top2 == MAXSIZE)
{
//说明栈2已经是空栈,溢出
return false;
}
//将栈2的栈顶元素出栈
*e = S->data[S->top2++];
}
return true;
}
使用这样的数据结构,通常都是针对俩个具有相同数据类型的栈的一个设计上的技巧,且俩个栈的空间需求有相反关系时,也就是一个栈增长时另一个栈在缩短的情况。
栈的链式存储结构
栈的链式存储结构,简称链栈。
链栈的结构定义
typedef struct StackNode {
SElemType data;
struct StackNode *next;
}StackNode,*LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top;
int count;
}LinkStack;
链栈的进栈操作
#include<stdlib.h>
//插入元素e为新的栈顶元素
bool Push(LinkStack *S, SElemType e) {
LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode));
s->data = e;
//把当前的栈顶元素赋值给新结点的直接后继
s->next = S->top;
//将新的结点s赋值给栈顶指针
S->top = s;
S->count++;
return true;
}
链栈的出栈操作
//若栈不空,则删除S的栈顶元素,用e返回其值,并返回true,否则返回false
bool Pop(LinkStack *S, SElemType *e) {
LinkStackPtr p;
if (S->count==0)
return false;
*e = S->top->data;
//将栈顶结点赋值给p
p = S->top;
//使得栈顶指针下移一位,指向后一结点
S->top = S->top->next;
//释放结点p
free(p);
S->count--;
return true;
}
时间复杂度
链栈的出栈和入栈操作的时间复杂度为O(1)。
顺序栈和链栈的区别
如歌栈的使用过程中元素变化不可预测,有时很小,有时非常大,那么最好是用链栈,反之,如果它的变化在可控范围内,建议使用顺序栈会更好一些。