郝斌数据结构入门---P30---栈

郝斌数据结构入门---P30---栈

线性结构的常见应用之一:栈(只能头部插入,头部删除

定义:一种可以实现“ 先进后出 ”的存储结构,栈类似于箱子

分类:静态栈,动态栈

算法:出栈pop,入栈push(压栈)

应用:函数调用,中断,表达式求值,内存分配,缓冲处理,迷宫

为了便于链表的操作,产生一个没有实际含义的头结点。

扫描二维码关注公众号,回复: 3819868 查看本文章

初始化栈init()函数:

建立一个空栈,把pTop和pBotoom都指向头结点 

压栈push()函数:

第一步:先创建一个新的节点
第二步:把val赋给新节点的数据域
第三步:因为每次压栈到当前栈顶的上方,所以把新节点的指针域指向pTop
第四步:pTop指向新的节点

遍历输出traverse()函数:
定义一个指针p,p永远指向栈顶元素 
然后从栈顶到栈底依次遍历 

出栈pop()函数:
把pS所指向的栈出栈一次,并把出栈的元素存入pVal形参所指向的变量中
如果出栈失败,返回-1,否则返回1
先定义指针r,然后再把pTop往后移一个,最后把r释放 

清空节点clear()函数:
定义两个指针p和q
p指向栈顶元素,q指向栈顶下一个元素 
这样释放p,q刚好是下一个元素,然后再把q赋值给p,q往下移一个 

代码如下:

//动态栈的本质是操作链表

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

//NODE  = struct Node
//PNODE = struct Node * 
typedef struct Node
{
	int data;
	struct Node * pNext;
}NODE, *PNODE;


//STACK  = struct Stack
//PSTACK = struct Satck *
//栈里面有两个元素pTop,pBottom
typedef struct Stack 
{
	PNODE pTop;		//指向栈的顶部 
	PNODE pBottom;	//指向栈的底部 
}STACK, *PSTACK;	//PSTACK 等价于 struct Stack * 

void init(PSTACK);
void push(PSTACK, int);
void traverse(PSTACK);
int 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;
}

//初始化目的:建立一个空栈,把pTop和pBotoom都指向头结点 
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->pBottom->pNext = NULL;
	}
}

//压栈 
//第一步:先创建一个新的节点
//第二步:把val赋给新节点的数据域
//第三步:因为每次压栈到当前栈顶的上方,所以把新节点的指针域指向pTop
//第四步:pTop指向新的节点
void push(PSTACK pS, int val)
{
	PNODE pNew = (PNODE)malloc(sizeof(NODE));//创建新的节点
	
	pNew->data = val;		//把val赋给新节点的数据域
	pNew->pNext = pS->pTop; //pS->pTop不能改成pS->Bottom 
	pS->pTop = pNew;
	
	return ;
}

//遍历输出
//定义一个指针p,p永远指向栈顶元素 
//然后从栈顶到栈底依次遍历 
void traverse(PSTACK pS)
{
	PNODE p = pS->pTop;
	
	while (p != pS->pBottom)
	{
		printf("%d ", p->data);
		p = p->pNext;
	}
	printf("\n");
	
	return;
}

//判断栈是否为空 
int empty(PSTACK pS)
{
	if (pS->pTop == pS->pBottom)
		return 1;
	else
		return 0;
}

//出栈
//把pS所指向的栈出栈一次,并把出栈的元素存入pVal形参所指向的变量中
//如果出栈失败,返回-1,否则返回1
//先定义指针r,然后再把pTop往后移一个,最后把r释放 
int pop(PSTACK pS, int *pVal)
{
	if (empty(pS))	//pS本身存放的就是S的地址 
	{
		return 0;
	}
	else//栈是非空 
	{
		PNODE r = pS->pTop;
		*pVal = r->data;//保存栈顶数据 
		pS->pTop = r->pNext;
		free(r);
		r = NULL;
		
		return 1;
	}
}

//clear 清空节点 
//定义两个指针p和q
//p指向栈顶元素,q指向栈顶下一个元素 
//这样释放p,q刚好是下一个元素,然后再把q赋值给p,q往下移一个 
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;
	}
}

猜你喜欢

转载自blog.csdn.net/xiaodingqq/article/details/83213447