栈本质上是一个线性表,只不过对线性表的操作进行了限制,只可以在表的一端进行操作(插入、删除元素)。栈是一种是一种实现数据“先进后出”的存储结构,分为静态栈和动态栈,静态栈就是以数组的方式存储数据,动态栈是以链表的方式存储数据;对栈的操作算法,常用的就是压栈和出;下面将以链式的方式创建栈,并对用c语言实现栈的压栈和出栈的算法:
1.栈的创建
在创建一个数据结构之前,必须知道这种数据结构由哪些参数组成,栈的本质既然是个链表,它必然由很多节点组成;为了实现“先进后出”这种数据结构,我们需要引进两个参数,一个是栈顶指针(pTop),始终指向栈顶元素。一个参数是栈底指针(pBottom),始终指向栈底元素。我们知道为了方便描述链表的各种操作,引进了头节点的概念,即为每个链表前面加一个头节点,但并存放有效数据;同样,为了实现栈的操作,我们同样需要一个不存放任何有效数据的节点,并且栈底指针始终指向该节点;
- typedef int elementype;
- //定义一个节点
- typedef struct Node
- {
- elementype data;
- struct Node *pNext;
- }NODE,*PNODE;//
- //构造一个栈
- typedef struct stack
- {
- PNODE pTop; //栈顶指针
- PNODE pBottom;//栈底指针
- }STACK,*PSTACK;
此时,数据类型构造出来了,接下来要创建一个空栈,这样我们才能进行栈的操作,创建栈,无非就是分配内存,内存分配有三种方式,静态存储区,栈,堆;
- //创建一个空栈,里面没有任何有效数据;
- void Create_Stack(PSTACK S)
- {
- S->pBottom=(struct Node *)malloc(sizeof(struct Node));
- if(NULL==S->pBottom)
- {
- printf("Memory allocation failure");
- exit(-1);
- }
- S->pTop=S->pBottom;
- S->pTop->data=0;
- S->pTop->pNext=NULL; //防止出现野指针
- }
2.压栈算法
图2 压栈算法示意图
压栈的伪算法:
(1).创建一个节点p,并修改节点的指针域使其指向栈顶数据元素;p->pNext=pTop;
(2)修改栈顶指针,使其指向栈顶元素,pTop=p;
程序代码:
- //进栈
- void Push_Stack(PSTACK S,int val)
- {
- PNODE p=(struct Node *)malloc(sizeof(struct Node));
- if(NULL==p)
- {
- printf("Memory allocation failure");
- exit(-1);
- }
- p->data=val;
- p->pNext=S->pTop; //让p的指针域指向上一个节点
- S->pTop=p; //让pTop指针指向栈顶元素
- }
3.出栈算法
图3.出栈算法示意图
出栈伪算法:
(1).先用P指针保存要删除数据的地址,用于便于释放此节点的内存,即p=pTop;
(2).修改栈顶指针的指向,使其指向栈顶元素;pTop=pTop->pNext;
附录:程序代码
stack.h文件代码:
- #ifndef __STACK_H_
- #define __STACK_H_
- typedef int elementype;
- //定义一个节点
- typedef struct Node
- {
- elementype data;
- struct Node *pNext;
- }NODE,*PNODE;//
- //构造一个栈
- typedef struct stack
- {
- PNODE pTop; //栈顶指针
- PNODE pBottom;//栈底指针
- }STACK,*PSTACK;
- //函数声明区
- void Create_Stack(PSTACK S);
- void Push_Stack(PSTACK S,int val);
- bool Pop_Stack(PSTACK S,int *val);
- void Traverse_Stack(PSTACK S);
- void Clear_Stack(PSTACK S);
- #endif
stack.c文件代码:
- #include<stdio.h>
- #include<stdlib.h>
- #include"stack.h"
- //创建一个空栈,里面没有任何有效数据;
- void Create_Stack(PSTACK S)
- {
- S->pBottom=(struct Node *)malloc(sizeof(struct Node));
- if(NULL==S->pBottom)
- {
- printf("Memory allocation failure");
- exit(-1);
- }
- S->pTop=S->pBottom;
- S->pTop->data=0;
- S->pTop->pNext=NULL; //防止出现野指针
- }
- //进栈
- void Push_Stack(PSTACK S,int val)
- {
- PNODE p=(struct Node *)malloc(sizeof(struct Node));
- if(NULL==p)
- {
- printf("Memory allocation failure");
- exit(-1);
- }
- p->data=val;
- p->pNext=S->pTop; //让p的指针域指向上一个节点
- S->pTop=p; //让pTop指针指向栈顶元素
- }
- //打印出栈里面的元素
- void Traverse_Stack(PSTACK S)
- {
- PNODE p=S->pTop;
- printf("栈中的元素是:\n");
- while(p!=S->pBottom)
- {
- printf("%d ",p->data);
- p=p->pNext;
- }
- printf("\n");
- }
- bool Is_Empty(PSTACK pS)
- {
- if (pS->pTop == pS->pBottom)
- return true;
- else
- return false;
- }
- bool Pop_Stack(PSTACK S,int *val)
- {
- if(Is_Empty(S))
- return false;
- else
- {
- PNODE p=S->pTop;
- *val=S->pTop->data;
- S->pTop=S->pTop->pNext; //使pTop指针指向栈顶元素;
- free(p); //释放p指针所指向的那个节点的内存;
- p=NULL; //要养成好的习惯;
- return true;
- }
- }
- void Clear_Stack(PSTACK S)
- {
- if(Is_Empty(S))
- return;
- else
- {
- PNODE p=NULL; //养成一好习惯,定义指针记得初始化;
- while(S->pTop!=S->pBottom)
- {
- p=S->pTop;
- S->pTop=S->pTop->pNext;
- free(p);
- p=NULL;
- }
- }
- }
自己添加的例子:
- # include <stdio.h>
# include <malloc.h>
# include <stdlib.h>
typedef struct Node
{
int data;
struct Node * pNext;
}NODE, * PNODE;
typedef struct Stack
{
PNODE pTop;
PNODE pBottom;
}STACK, * PSTACK; //PSTACK 等价于 struct STACK *
void init(PSTACK);
void push(PSTACK, int );
void traverse(PSTACK);
bool pop(PSTACK, int *);
void clear(PSTACK pS);
int main(void)
{
STACK S; //STACK 等价于 struct Stack
int val;
init(&S); //目的是造出一个空栈
push(&S, 1); //压栈
push(&S, 2);
push(&S, 3);
push(&S, 4);
push(&S, 5);
push(&S, 6);
traverse(&S); //遍历输出
clear(&S);
//traverse(&S); //遍历输出
if ( pop(&S, &val) )
{
printf("出栈成功,出栈的元素是%d\n", val);
}
else
{
printf("出栈失败!\n");
}
traverse(&S); //遍历输出
return 0;
}
void init(PSTACK pS)
{
pS->pTop = (PNODE)malloc(sizeof(NODE));
if (NULL == pS->pTop)
{
printf("动态内存分配失败!\n");
exit(-1);
}
else
{
pS->pBottom = pS->pTop;
pS->pTop->pNext = NULL; //pS->Bottom->pNext = NULL;
}
}
void push(PSTACK pS, int val)
{
PNODE pNew = (PNODE)malloc(sizeof(NODE));
pNew->data = val;
pNew->pNext = pS->pTop; //pS->Top不能改成pS->Bottom
pS->pTop = pNew;
return;
}
void traverse(PSTACK pS)
{
PNODE p = pS->pTop;
while (p != pS->pBottom)
{
printf("%d ", p->data);
p = p->pNext;
}
printf("\n");
return;
}
bool empty(PSTACK pS)
{
if (pS->pTop == pS->pBottom)
return true;
else
return false;
}
//把pS所指向的栈出栈一次,并把出栈的元素存入pVal形参所指向的变量中,如果出栈失败,返回false,否则返回true
bool pop(PSTACK pS, int * pVal)
{
if ( empty(pS) ) //pS本身存放的就是S的地址
{
return false;
}
else
{
PNODE r = pS->pTop;
*pVal = r->data;
pS->pTop = r->pNext;
free(r);
r = NULL;
return true;
}
}
//clear清空
void clear(PSTACK pS)
{
if (empty(pS))
{
return;
}
else
{
PNODE p = pS->pTop;
PNODE q = NULL;
while (p != pS->pBottom)
{
q = p->pNext;
free(p);
p = q;
}
pS->pTop = pS->pBottom;
}
}