介绍:
栈是计算机编程里面一种较为简单,基础的数据结构类型,又名堆栈。同线性表一样,栈的存储方式也分为顺序存储和链式存储。
(以单端栈为例)其大概示意图如下:
1.栈只能从一端进入,一端出去,也就是说栈是一个半封闭的数据结构。
2.栈遵循先进先出的原则。
3.出栈和入栈只能发生在栈顶,而不能发生在栈底。
4.入栈:外部数据从栈顶进入栈里
5.出栈:栈顶数据从栈顶方向弹出
一. 顺序栈
介绍:
他的结构体存储类型:
typedef int ElementType;
typedef struct
{
ElementType *array; //存放栈数据
int top; //栈顶
int capacity; //容量
} SeqStack;
1. 创建
请设计SeqStack* createStack(int capacity)函数。
该函数创建一个空的顺序栈,并返回栈指针。
参数capacity为已分配的栈空间大小(栈可用空间为array[0,…capacity-1])。
SeqStack* createStack(int capacity)
{
SeqStack *s;
s=(SeqStack *)malloc(sizeof(SeqStack));
if(s==NULL) return NULL;
s->top=-1; //初始栈顶下标为-1
s->capacity=capacity;
s->array=(ElementType *)malloc(capacity*sizeof(ElementType));
return s;
}
2. 判满
请设计int full(SeqStack *S)函数。 该函数判断栈S是否满,
如果栈满则返回1,否则返回0。
int full(SeqStack *S)
{
if(S->top == S->capacity-1)
return 1;
return 0;
}
3. 入栈
入栈操作的前提是栈未满,而且入栈的方向是栈顶,此时栈的top应该+1;
请设计int push(SeqStack *S, ElementType x)函数。
该函数将数据x压入栈顶,如果入栈成功返回1,否则返回0。
int push(SeqStack *S, ElementType x)
{
if(S->top < S->capacity-1) //判断栈是否为满
{
S->top++; //栈顶下标数据+1
S->array[S->top]=x;
return 1;
}
return 0;
}
4. 出栈
出栈的前提是栈未空,出栈的方向仍然是栈顶,此时的top应该-1
请设计int pop(SeqStack *S)函数。
该函数将栈顶数据出栈,如果成功返回1;否则返回0。
int pop(SeqStack *S)
{
if(S->top>-1) //判断不为空
{
S->top--; //栈顶下标数据--
return 1;
}
return 0;
}
5. 栈顶数据
输出栈顶数据,但是栈顶数据不出栈
请设计ElementType top(SeqStack *S)函数。
该函数该函数把返回栈顶数据(不出栈),已知栈非空。
ElementType top(SeqStack *S)
{
if(S->top > -1) //不为空的栈
{
return S->array[S->top]; //返回栈顶数据但不出栈
}
}
6. 清空栈
栈顶清空操作就是将所有已入栈的数据全部清空,但保留最后的空栈
请设计void clearStack(SeqStack *S)函数。
该函数清空栈中数据(保留数据空间)。
void clearStack(SeqStack *S)
{
while(S->top > -1) //直到栈顶下标数据为-1,代表栈已清空
{
S->top--;
}
}
7. 销毁
销毁所创建的栈
请设计void destroyStack(SeqStack *S)函数。
该函数销毁栈。
void destroyStack(SeqStack *S)
{
free(S->array);
free(S);
S = NULL;
}
二. 链栈(下面的图可能没贴好,海涵)
链式栈的存储结构体类型
typedef int ElementType;
typedef struct Node
{
ElementType data; //数据域
struct Node *next; //指针域
} Node, *LinkStack;
typedef struct
{
LinkStack top; //指向栈顶结构体的指针
LinkSatck base; //指向栈底结构体的指针
}LinkStackTop;
下面列举一个链栈的例子
1. 创建空链栈
请设计LinkStackTop* createStack()函数。
该函数创建一个不带头结点的空链栈。
因为是不带头结点空链栈,所以此时栈内的结构体是不存在的,就只需要创建包含top指针和base指针的结构体就可以
LinkStackTop* createStack()
{
LinkStackTop *p=(LinkStackTop*)malloc(sizeof(LinkStackTop));
if(p == NULL) return NULL;
p->top = NULL;
p->base = NULL;
return p;
}
2. 入栈
链式栈的入栈需要注意:入栈后记得改变top指针的指向,如果原栈为空,还要考虑栈底指针
请设计int push(LinkStackTop* S, ElementType x)函数。
该函数把x压入S的栈顶,并返回1,(已知S是不带头结点的链栈),如果申请空间失败返回0。
int push(LinkStackTop* S, ElementType x)
{
if(S == NULL) return 0;
LinkStack stack = (LinkStack)malloc(sizeof(Node));
if(stack == NULL) return 0;
stack->data = x;
stack->next = NULL;
if(S->base == NULL) //起初是空链栈的时候
{
S->top = S->base = stack;
return 1;
}
S->top->next = stack;
S->top = stack;
return 1;
}
3. 获取栈顶数据
请设计ElementType Top(LinkStackTop* S)函数。
该函数返回不带头节点的链栈S的栈顶数据(不出栈)。
栈为空什么也不做
ElementType Top(LinkStackTop* S)
{
if(S->base != NULL) //判断栈不为空
{
return S->top->data;
}
}
4. 出栈
请设计int pop(LinkStackTop* S)函数。
已知S是不带头结点的链栈。
该函数把链栈S栈顶元素出栈,如果S已空,则什么都不做。
如果出栈成功返回1,否则返回0。
int pop(LinkStackTop* S)
{
if(S->base!=NULL)
{
LinkStack mid = S->base;
LinkStack pre = NULL; //mid的前驱
while(1)
{
if(mid == S->top)
{
if(mid == S->base) S->base = pre; //如果栈内只有一个数据
else pre->next = S->top->next;
S->top = pre;
free(mid); //销毁栈顶
return 1;
}
pre = mid;
mid = mid->next;
}
}
return 0;
}
5. 清空栈
请设计void clearStack(LinkStackTop* S)函数。
该函数删除链栈中的所有数据节点,清除后为空链栈。
void clearStack(LinkStackTop* S)
{
LinkStack mid = S->base;
LinkStack pre;
while(mid) //从 base 到 top 全部清空
{
pre=mid;
free(pre);
mid=mid->next;
}
S->base = S->top = NULL;
}
6. 销毁栈
请设计void destroyStack(LinkStackTop* S)函数。
该函数销毁链栈S,已知S是不带头结点的链栈。
(S不一定是空链)
void destroyStack(LinkStackTop* S)
{
LinkStack mid = S->base;
LinkStack pre;
while(mid) //从 base 到 top 全部清空
{
pre=mid;
free(pre);
mid=mid->next;
}
free(S);
S = NULL;
}
是不是感觉又学到了东西,hhhh,评论区已经划好,有问题欢迎留言!
制作不易,感谢支持,望不喜勿喷!