栈是一种后进先出的结构,实现栈有两种方法,链表和数组。用链表的好处在于不用提前声明大小,只在需要的时候创建。而使用数组的好处在于不用指针操作,但是却需要提前声明数组大小。不过通常使用栈的时候,容量都不需要太大,所以使用数组实现也是不错的方法。栈的数组实现比较简单,所以本文只写栈的链表实现。
1)定义链表结点以及相关内容
typedef char elemtype; //定义栈中元素类型
typedef struct node node;
typedef struct node *pnode; //pnode为指向struct node的指针
typedef pnode stack;
struct node {
elemtype data;
struct node *next;
};
2)定义栈操作函数
void error(const char *msg); //错误提示函数
int isEmpty(stack s); //判断栈是否为空的函数
void pop(stack s); //弹出栈顶元素
void push(stack s, elemtype x); //压入元素x到栈中
elemtype top(stack s); //返回栈顶元素
stack createStack(); //创建栈
void makeEmpty(stack s);//清空栈
3)创建栈
创建栈函数createStack(),创建一个包含一个头结点的链表,注意这个头结点是不用的,它只用来做链表的表头,方便操作。其中makeEmpty(stack s)函数用于清空栈s,也就是将s中存在的元素全部pop出来,pop函数在后面实现。
stack createStack()
{
stack s = (stack)malloc(sizeof(node));
s->next = NULL;
makeEmpty(s);
return s;
}
void makeEmpty(stack s)
{
if (s == NULL)
error("must create stack first");
while (!isEmpty(s))
pop(s);
}
4)判断栈是否为空
判断栈是否为空的函数isEmpty(stack s)实现很简单,只需要判断s->next==NULL即可。
int isEmpty(stack s)
{
return s->next == NULL;
}
5)核心函数pop、push、top
push函数就是将元素x插入到链表头部(表头的后面),pop函数则是将链表的第一个有效结点(表头后面的第一个结点)弹出,top函数返回链表的第一个有效结点的元素值。
void push(stack s, elemtype x)
{
pnode tmp = (stack)malloc(sizeof(node));
if (tmp == NULL)
error("no memory");
else {
tmp->data = x;
tmp->next = s->next;
s->next = tmp;
}
}
void pop(stack s)
{
if (isEmpty(s))
error("stack is empty");
else {
pnode first = s->next;
s->next = s->next->next;
free(first);
}
}
elemtype top(stack s)
{
if (isEmpty(s)) {
error("stack is empty");
return 0;
} else {
return s->next->data;
}
}