一、栈的链式存储结构实现图
这本质上就是不带头节点的单链表。
二、代码实现
1.栈链的定义
#include<stdio.h>
#include<stdlib.h>
#define ERROR 0
#define OK 1
typedef int ElemType;
typedef int Status;
typedef struct stackNode
{
ElemType data;
struct stackNode *next;
}stackNode,*stackPtr;
typedef struct stack
{
stackPtr top;
int count;
}LinkStack;
2.栈链的系列操作
//初始化栈,将top指针指向NULL,栈的元素数count设为0
Status InitStack(LinkStack *s)
{
if(!s)
return ERROR;
s->count=0;
s->top=NULL;
return OK;
}
//求取栈链的元素数
int getLength(LinkStack *s)
{
if(!s)
return -1;
return s->count;
}
//判断是否为空栈
int isEmpty(LinkStack s)
{
if(s.count)
return 0;
return 1;
}
//得到栈顶元素
Status getTop(LinkStack *s,ElemType *e)
{
if(!s->count||!s)
return ERROR;
*e=s->top->data;
return OK;
}
//压栈,使用头插法,遵循先进后出原则
Status Push(LinkStack *s,ElemType e)
{
stackNode *p=(stackNode*)malloc(sizeof(stackNode));
if(!s)
return ERROR;
p->data=e;
p->next=s->top;
s->top=p;
s->count++;
return OK;
}
//弹栈
Status Pop(LinkStack *s,ElemType *e)
{
stackNode *p=s->top;
if(!s||!s->count)
return ERROR;
s->top=s->top->next;
*e=p->data;
free(p);
s->count--;
return OK;
}
//输出栈元素
Status PrintStack(LinkStack *s)
{
stackNode *p=s->top;
if(!s||!s->count)
return ERROR;
while(p)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
return OK;
}
//最后可以利用上述函数创建一个栈。
Status CreateStack(LinkStack *s)
{
int n;
InitStack(s);
if(!s)
return ERROR;
printf("输入初始化几个元素:");
scanf("%d",&n);
getchar();
while(n)
{
Push(s,n);
n--;
}
return OK;
}
三、总结
栈有两种存储结构,一种是顺序存储结构,一种是链式存储结构。但是都遵循一个原则:先进后出,后进先出。这样可以做到顺序输入,倒序输出,从而有很多的应用,比如C语言内存管理中的栈内存、Java虚拟机JVM中的栈内存等等,可以更好的理解程序的执行以及变量的生成。
这里的链式存储结构,本质上利用的仍是不带头节点的单链表和头插法。
这里提一提函数形参什么时候传入地址,什么时候传入值。如果我们需要通过函数改变实参,那么就要传入地址,如果仅仅传入的是实参的值,那么形参就相当于一个副本,即复制品,出了函数的作用范围,这个复制品的内存就被释放了,根本没有影响到实参。这个在此处不细讲,对于形参实参的区别在网上已经有很多相关的文章了,不清楚的同学可以自己去搜索阅读。