座右铭:talk is easy,show me the code.
我们生活在幸福的时代,我们都站在居人的肩膀上看世界。
WHY?
Question:老实说学了数据结构已经一学期了,链表都没有搞清楚,凭什么弄明白栈?
Anser:和大多人一样,起初对栈一点也不了解。但逐渐理解链表之后发现栈其实也挺简单的。这得益于郝斌的C语言和数据结构,我非常感谢bilibili这个平台,里面有大量的学习视频。
什么是栈?
栈就相当于一个有桶而没有盖的桶,你往里面放东西,先放进去的一定会最后拿出来,后放进去的东西,先拿出来----------即==‘后进后出’==
栈的结构
在我的理解里面,结构体就相当于一个容器,把若干个属性封装起来。
这里的 PNode 相当于 Node *(类似于int 和 int * 的关系)
我们也可以理解成 int *也是一种数据类型
typedef struct Node
{
int data;//数据域
struct Node* next;//指针域,指向下一个节点
}Node,*PNode;
typedef struct Stack
{
PNode ptop;//指向栈顶元素
PNode pbottom;//指向栈底元素
}Stack,*PStack;
栈的初始化
栈的初始化就是将Stack里面的变量指向一个内存单元,如果不这样做,那么它的变量就是一个未知地址(地址是数值),我们把它称之为“垃圾值”。
这样做的目的就是方便栈的操作
void init_stack(PStack ps)
{
//分配动态内存
ps->ptop=(PNode)malloc(sizeof(Node));
if(ps->ptop==NULL)
{
printf("分配失败!\n");
exit(-1);
}
else
{
ps->pbottom=ps->ptop;
ps->pbottom->next=NULL;
//事实上ps->ptop->next=NULL也行;
}
}
进栈(压栈)
进栈就是把元素放进放进这个容器里面
void push_stack(PStack ps,int val)
{
PNode pnew=(PNode)malloc(sizeof(Node));
//申请节点
if(pnew==NULL)
{
printf("分配失败!\n");
exit(-1);
}
else
{
//将待进栈元素给申请节点的数据域
pnew->data=val;
pnew->next=ps->ptop;
ps->ptop=pnew;
}
}
出栈
出栈就是把最近进栈元素取出容器
//为了记下出栈元素是多少,因此我们需要通过指针变量通过指针操作来将
//元素记录下来,返回值为bool是因为我们需要判断出栈是否成功;
bool empty_stack(PStack ps)
{
//ps->ptop==ps->pbottom意味着栈为空
if(ps->ptop==ps->pbottom)
{
return true;
}
else return false;
}
bool pop_stack(PStack ps,int *val)
{
if(empty_stack(ps))
{
return false;
}
else
{
PNode r=ps->ptop;
*val=r->data;
ps->ptop=ps->ptop->next;
free(r);//释放内存
return true;
}
}
遍历栈
没什么好多说的,无非就是把栈里面的元素全部访寻一遍。
void traverse_stack(PStack ps)
{
PNode p=ps->ptop;
while(p!=ps->pbottom)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
实例演示
借助前文的函数,写下main()函数来演示代码。
int main()
{
Stack s;
int a;
init_stack(&s);
push_stack(&s,1);
push_stack(&s,2);
traverse_stack(&s);
if(pop_stack(&s,&a))
{
printf("出栈成功,出栈元素为: %d\n",a);
}
else
{
printf("出栈失败\n");
}
traverse_stack(&s);
return 0;
}
结果实例如下:
该例子无法验证栈为空的时候情况,所以我们需要再看一种情况,为了使文章篇幅尽可能短,我就直放置结果:
栈的大概知识点就是如此。
下一个博客写队列,期待你的到来!
个人博客:https:xuwenxiang666.github.io\
欢迎你的到来