一.栈的定义
Tips:阅读本文之前,请先熟悉链表知识:链表的理解与实现
栈是一种可以实现”先进后出“的数据结构。
栈只允许在栈顶进行插入、删除、遍历等操作。
如下图:
依次放入 5-6-7 到栈内。
拿出 6来,得先拿出 7来
拿出 5来,得先拿出7、6来。
也就是7后进的,7先出栈;5先进的,5后出栈。
二、栈的实现
1.初始化一个栈
1.1定义链表的节点结构
typedef struct Node
{
int data;
struct Node * pNext;
}NODE,*PNODE;
1.2定义栈的首指针与尾指针
typedef struct stack
{
PNODE pTop; //栈顶指针
PNODE pBottom;//栈底指针
}STACK,*PSTACK;
1.3初始化一个栈
//初始化一个栈
void initStack(PSTACK pS)
{
pS->pTop=(PNODE)malloc(sizeof(NODE));
if(pS->pTop==NULL)
{
printf("栈初始化失败\n");
exit(-1);
}
else
{
pS->pBottom=pS->pTop;
pS->pBottom->pNext=NULL;
}
}
如果此栈初始化成功,会有如下图示的结构:
2.压栈
压栈就是在栈顶压入一个元素。
压栈分为3步:
1.创建一个新节点存放数值;
2.使新节点指向pTop指向的元素;
3.使pTop指向新元素。
代码实现:
//压栈
void pushStack(PSTACK pS,int val)
{
//1.创建一个新节点存放数值;
PNODE pNew=(PNODE)malloc(sizeof(NODE));
pNew->data=val;
//2.使新节点指向pTop指向的元素;
pNew->pNext=pS->pTop;
//3.使pTop指向新元素。
pS->pTop=pNew;
}
如图:
压栈前:
压栈后
3.遍历栈
3.1判断栈是否为空(空则不遍历,直接返回)
当栈顶与栈底相等的时候,栈就是空栈。
//判断栈是否为空
int isEmpty(PSTACK pS)
{
if(pS->pTop==pS->pBottom)
{
return 1;
}
else
{
return 0;
}
}
3.2遍历栈
只要栈顶与栈底不相等,就遍历栈
//遍历栈
void traverseStack(PSTACK pS)
{
if(isEmpty(pS))
{
printf("栈为空,不可遍历\n");
}
else
{
PNODE p=pS->pTop;
while(p!=pS->pBottom)
{
printf("%d ",p->data);
p=p->pNext;
}
free(p);
pS->pTop=pS->pBottom;
}
}
4.出栈
出栈分为三步:
1. 创建一个指针p保存pTop指针
2. 让pTop指针指向下一个元素
3. 释放掉p
如图:
//出栈
void popStack(PSTACK pS)
{
if(isEmpty(pS))
{
printf("空栈,不可出栈\n");
}
else
{
//创建一个指针p保存pTop指针
PNODE p=pS->pTop;
//让pTop指针指向下一个元素
pS->pTop=p->pNext;
//释放掉p
free(p);
}
}
5.清空栈
1.我们直接让pTop=pBottom是否可行?
这样虽然清空了栈,但是pTop—pBottom之间的内存并没有被释放,会造成内存泄露,这样不行。
2.我们先释放pTop—pBottom之间的内存,再让pTop=pBottom。
//清空栈
void clearStack(PSTACK pS)
{
if(isEmpty(pS))
{
return ;
}
else
{
PNODE p=pS->pTop;
//1.清空pTop---pBottom之间的内存
while(p!=pS->pBottom)
{
PNODE q=p->pNext;
free(p);
p=q;
}
free(p);
//2.让pTop=pBottom
pS->pTop=pS->pBottom;
}
}
三.总体代码
#include <stdio.h>
#include <stdlib.h>
//链表节点的数据结构
typedef struct Node
{
int data;
struct Node * pNext;
}NODE,*PNODE;
//栈的数据结构
typedef struct stack
{
PNODE pTop;
PNODE pBottom;
}STACK,*PSTACK;
//初始化一个栈
void initStack(PSTACK pS)
{
pS->pTop=(PNODE)malloc(sizeof(NODE));
if(pS->pTop==NULL)
{
printf("栈初始化失败\n");
exit(-1);
}
else
{
pS->pBottom=pS->pTop;
pS->pBottom->pNext=NULL;
}
}
//压栈
void pushStack(PSTACK pS,int val)
{
PNODE pNew=(PNODE)malloc(sizeof(NODE));
pNew->data=val;
pNew->pNext=pS->pTop;
pS->pTop=pNew;
}
//判断栈是否为空
int isEmpty(PSTACK pS)
{
if(pS->pTop==pS->pBottom)
{
return 1;
}
else
{
return 0;
}
}
//遍历栈
void traverseStack(PSTACK pS)
{
if(isEmpty(pS))
{
printf("栈为空,不可遍历\n");
}
else
{
PNODE p=pS->pTop;
while(p!=pS->pBottom)
{
printf("%d ",p->data);
p=p->pNext;
}
free(p);
pS->pTop=pS->pBottom;
}
}
//出栈
void popStack(PSTACK pS)
{
if(isEmpty(pS))
{
printf("空栈,不可出栈\n");
}
else
{
//创建一个指针p保存pTop指针
PNODE p=pS->pTop;
//让pTop指针指向下一个元素
pS->pTop=p->pNext;
//释放掉p
free(p);
}
}
//清空栈
void clearStack(PSTACK pS)
{
if(isEmpty(pS))
{
return ;
}
else
{
PNODE p=pS->pTop;
while(p!=pS->pBottom)
{
PNODE q=p->pNext;
free(p);
p=q;
}
free(p);
pS->pTop=pS->pBottom;
}
}
int main()
{
STACK s;
initStack(&s);
pushStack(&s,3);
pushStack(&s,2);
pushStack(&s,1);
popStack(&s);
clearStack(&s);
traverseStack(&s);
return 0;
}
四.总结
栈是一种非常重要的线性结构,也是非常基本的数据结构。本文用链表的方式实现了栈。
栈在计算机领域有很多应用。
比如:函数的调用用到栈、判断回文也用到栈的知识。
所以,我们一定要掌握它!