栈的由来
之前的文章中我们介绍了两种线性储存结构的特点,并且实践了两种不同存储结构实现同一功能之间的的实战,并且体会到了他之间的异同,最后我们得到一个启发,就是在线性储存结构中,无论他的储存形式是连续或者非连续,他们都是从头到尾以某一种方式连接着,这种方式可能是存储单元紧挨在一起的个体,也有可能是存储单元之间指针,他们都通过线性的这种方式来展示的,这很好的模拟了内存的物理结构,而正式这种特殊的结构,引发了关于存储单元之间顺序的思考。通过不同的产生,排列,组合所产生的顺序,总结出了在线性结构基础上的遵循不同数组操作顺序的两种特殊的存储结构,其中一种就是今天要介绍的栈
栈的定义和举例
栈的定义:
互联网:栈(Stack)是n个元素a1,a2,…an,组成的有限序列,记作S =(a1,a2,…,an),并且只能在一端插入和删除元素,n=0时称为空栈。
这是我在网上所搜到的答案,我认为这并不是很易于理解并且他概括的概念特超出栈的本质
自己总结:一种可以实现“先进后出”的存储结构
当然对于栈我还有自己的其他理解,但是现在不是和盘托出的时候
举例
栈类似于箱子,羽毛球桶。上面的东西不拿出来无法拿出下面的东西,先放进去的东西自动在底部
栈的分类
栈主要可以分类静态栈和动态栈,静态动态如果看过我之前的博客应该很好理解吧
说白了就是内存分配的方式对吧。
栈的算法
主要有两种,一种是压栈(没有夫人),一种是出栈。
压栈:类似于芳羽毛球桶种放东西
出栈:类似于从羽毛球桶中拿东西
实战-----栈(小刀拉屁股的时候到了)
实战目标:展示动态栈的构造构成,出栈和入栈的过程,对栈进行遍历的过程
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct Node
{
int data;
struct Node* pNext;
}*pnode,node;
typedef struct stack //栈 这是我们来定义我们需要的栈的储存单元
{
pnode ptop;
pnode pbottom;
}stack,*pstack;
//函数声明
void initstack(pstack ps);
void pushstack(pstack ps, int val);
void traverse(pstack ps);
bool pop(pstack ps, int* pval);
bool empty(pstack ps);//判断是否为空
void clear(pstack ps);
int main(void)
{
int val;
stack s;//等价于struct stack
initstack(&s);//目的制造出一个空栈
pushstack(&s,1);//压栈
pushstack(&s,2);
pushstack(&s, 99);
pushstack(&s, 7);
pushstack(&s, 6);
pushstack(&s, 2);
traverse(&s);//遍历
if (pop(&s, &val))
{
printf("出栈成功,出栈的元素是%d\n", val);
}
else
{
printf("出栈失败");
}
traverse(&s);//遍历
clear(&s);
traverse(&s);//遍历
return 0;
}
void initstack(pstack ps)
{
ps->ptop=(pnode)malloc(sizeof(Node));
if (NULL == ps->ptop)
{
printf("动态内存分配失败");
exit(-1);
}
else
{
ps->pbottom = ps->ptop;
ps->ptop->pNext = NULL;//等价于ps->pbotom->pNext = NULL 这个节点是头结点,所以pNext得空
}
return;
}
void pushstack(pstack ps, int val)
{
pnode pnew = (pnode)malloc(sizeof(node));
pnew->data = val;
pnew->pNext = ps->ptop;//ps->ptop
ps->ptop = pnew;
return;
}
void traverse(pstack ps)
{
pnode p=ps->ptop;
while (ps->ptop!=ps->pbottom)
{
printf("%d ",ps->ptop->data);
ps->ptop = ps->ptop->pNext;
}
ps->ptop = p;
return;
}
//把ps所指向的栈出栈一次,并把出栈的元素存入pval形参所指向的变量中,
//如果出栈失败返回false出栈成功放回true
bool empty(pstack ps)
{
if (ps->ptop == ps->pbottom)
return true;
else
return false;
}
bool pop(pstack ps, int *pval)
{
if (empty(ps))//ps本身存放的就是s的地址
{
return false;
}
else
{
pnode f = ps->ptop;
*pval = ps->ptop->data;
ps->ptop = ps->ptop->pNext;
free(f);
f = NULL;
return true;
}
}
//clear清空
void clear(pstack ps)
{
if (empty(ps))
return;
else
{
pnode p = ps->ptop;
pnode q = NULL;
while (p!=ps->pbottom)
{
q = p->pNext;
free(p);
p = q;
}
p = NULL;
q = NULL;
ps->ptop = ps->pbottom;
}
}
栈的总结
看完整个栈的程序实战演示,不男发现,栈其实就是一种被砍掉一部分功能的的链表。而为什么要砍掉部分功能形成一个栈呢?这其实是为了更好的对数句进行操作的原因,链表会本省存在一定的弊端,太发达也不是什么好事是吗。任何事情都是两面的,这个我们以后再讲。