(1)什么是栈
栈是一种实现“先进后出”的存储结构。
(2)栈的表示
栈有两种存储表示方法。顺序栈和链式栈
(3)栈的组成
栈顶指针,栈底指针(还可以为栈分配一个基本的容量)
入栈的节点要包括两部分:数据域,指针域。数据域用来存储数据;指针域用来指向另一个节点。既然入栈的节点包括两部分,则必定要用结构体来表示入栈的节点,用代码 可实现:
typedef struct node
{
int data;//数据域
struct node *pNext;//指针域
}NODE, *PNODE;
栈中的两个指针必定要指向入栈的节点,因此指针必须与节点的数据类型相同,则栈用代码可实现:
typedef struct stack
{
PNODE top;//栈顶指针
PNODE buttom;//栈底指针
}STACK, *PSTACK;
(4)栈的基本操作
1、初始化栈,即构造一个空栈。
动态申请一块内存,并将栈顶指针和栈底指针同时指向该内存。
相应函数的代码实现:
void initStack(PSTACK ps)
{
ps->top = (PNODE)malloc(sizeof(NODE));
if(NULL == ps->top)
{
printf("动态内存分配失败\n");
exit(-1);
}
else
{
ps->top->pNext = NULL;//将栈顶指针指向节点的指针域赋为空
ps->buttom = ps->top;//将栈顶指针付给栈底指针
}
}
2、入栈
入栈操作要指定需要对哪个栈操作,以及入栈的值。
首先要动态申请内存,并将数据域赋值,然后将该节点的指针域指向栈顶指针指向的节点的地址,最后将该节点的地址付给栈顶指针。
相应函数的代码实现:
void pushStack(PSTACK ps, int val)//在ps栈中压入值val
{
PNODE pNew = (PNODE)malloc(sizeof(NODE));
pNew->data = val;//将要压入的值赋给新申请的节点的数据域中
pNew->pNext = NULL;//将新申请的节点的指针赋为空
///
pNew->pNext = ps->top;
ps->top = pNew;
}
3、遍历
按照先进后出的顺序将栈中的元素输出
首先,要定义一个PNODE类型的变量p,并将栈顶指针指向的节点的地址赋给p,然后利用p = p->pNext进行遍历。
具体函数实现:
void traverse(PSTACK ps)
{
PNODE p;
p = ps->top;
while(p != ps->buttom)
{
printf("%d ",p->data);
p = p->pNext;
}
printf("\n");
}
4、判空
判断栈中是否含有元素。其中最为关键的:判断栈顶指针是否等于栈底指针。如果是,则栈为空;如果否,则栈不为空。
bool empty(PSTACK ps)
{
if(ps->top == ps->buttom)
return true;
else
return false;
}
5、出栈
首先,要判断栈中是否含有元素。若没有,则返回false;若有,才进行出栈操作。首先,申请一个PNODE类型的变量rm,并将栈顶指针指向的节点赋给它。然后将rm指向 的节点的指针域所指向的节点的地址赋给栈顶指针。此时,可以利用free函数释放内存。不要忘记将释放后的rm赋值为NULL。
函数实现:
bool pop(PSTACK ps, int *pval)
{
PNODE rm;
if(empty(ps))
return false;
else
{
rm = ps->top;
*pval = rm->data;
ps->top = rm->pNext;
free(rm);
rm = NULL;//当不在使用申请的内存时,记得释放。释放后应该把指向这块内存的指针指向NULL
//以防程序后面不小心使用它。
return true;
}
}
6、清空栈
将栈中的元素清除。最后,回到初始化状态。
首先,定义两个PNODE 类型的变量p,q。其中将栈顶元素所指向的节点的地址赋给p,将p赋值为NULL。q = p->pNext表示将q指向p所指向的节点的指针域所只想和的节 点。然后将p释放,然后将q的值赋给p。在while循环中,只要p != ps->buttom则一直循环下去。直到条件满足,跳出循环。
函数实现:
void clear(PSTACK ps)
{
PNODE p = ps->top;
PNODE q = NULL;
while(p != ps->buttom)
{
q = p->pNext;
free(p);//释放p所指向的用函数malloc所申请的空间
p = q;
}
ps->top = ps->buttom;
}
7、栈的全部代码:
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct node
{
int data;//数据域
struct node *pNext;//指针域
}NODE, *PNODE;
typedef struct stack
{
PNODE top;//栈顶指针
PNODE buttom;//栈底指针
}STACK, *PSTACK;
/**初始化栈**/
void initStack(PSTACK ps)
{
ps->top = (PNODE)malloc(sizeof(NODE));
if(NULL == ps->top)
{
printf("动态内存分配失败\n");
exit(-1);
}
else
{
ps->top->pNext = NULL;//将栈顶指针指向节点的指针域赋为空
ps->buttom = ps->top;//将栈顶指针付给栈底指针
}
}
/**入栈**/
void pushStack(PSTACK ps, int val)//在ps栈中压入值val
{
PNODE pNew = (PNODE)malloc(sizeof(NODE));
pNew->data = val;//将要压入的值赋给新申请的节点的数据域中
pNew->pNext = NULL;//将新申请的节点的指针赋为空
///
pNew->pNext = ps->top;
ps->top = pNew;
}
/**遍历**/
void traverse(PSTACK ps)
{
PNODE p;
p = ps->top;
while(p != ps->buttom)
{
printf("%d ",p->data);
p = p->pNext;
}
printf("\n");
}
/**判空**/
bool empty(PSTACK ps)
{
if(ps->top == ps->buttom)
return true;
else
return false;
}
/**出栈**/
bool pop(PSTACK ps, int *pval)
{
PNODE rm;
if(empty(ps))
return false;
else
{
rm = ps->top;
*pval = rm->data;
ps->top = rm->pNext;
free(rm);
rm = NULL;//当不在使用申请的内存时,记得释放。释放后应该把指向这块内存的指针指向NULL
//以防程序后面不小心使用它。
return true;
}
}
/**清空栈**/
void clear(PSTACK ps)
{
PNODE p = ps->top;
PNODE q = NULL;
while(p != ps->buttom)
{
q = p->pNext;
free(p);//释放p所指向的用函数malloc所申请的空间
p = q;
}
ps->top = ps->buttom;
}
void main()
{
STACK s;
int val;
initStack(&s);
/**************
测试empty(PSTACK ps)函数
if(empty(&s))
{
printf("ok");
printf("\n");
}
**************/
pushStack(&s, 1);
pushStack(&s, 2);
pushStack(&s, 3);
pushStack(&s, 4);
pushStack(&s, 5);
traverse(&s);
clear(&s);
if(pop(&s, &val))
{
printf("出栈成功,出栈的元素为:%d\n",val);
}
else
{
printf("出栈失败\n");
}
traverse(&s);
return;
}