栈的学习-c语言实现

本文探讨了数据结构的狭义与广义定义,强调了数据存储与操作的重要性。在算法方面,文章阐述了算法与数据存储方式的关系,并提出了泛型思想。接着,文章对比了数组和链表两种线性存储方式的优缺点。最后,文章重点介绍了栈这种线性结构的应用,特别是在函数调用和递归中的作用。

数据结构
狭义:
数据结构是专门研究数据存储的问题
数据的存储包含两方面:个体的存储+个体关系的存储
广义:
数据结构既包括数据的存储也包括数据的操作
对存储数据的操作就是算法
算法
狭义:
算法是和数据的存储方式密切相关
广义:
算法和数据的存储方式无关
这就是泛型思想

数据的存储方式有几种
线性
连续存储【数组】
优点
存取速度很快
缺点
事先需要知道数组的长度
插入删除元素很慢
空间通常有限制
需要大块连续的内存块
离散存储【链表】
优点
空间没有限制
插入删除元素很快
缺点
存取速度很慢
线性结构的应用–栈
线性结构的应用–队列
对于栈的学习

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


//定义节点 
typedef struct Node
{
	int data;
	struct Node * pNext;
} NODE, * PNODE;

//定义栈 
typedef struct Stack
{
	PNODE pTop;
	PNODE pBottom;
} STACK, * PSTACK;

//声明函数 
void init(PSTACK);
void push(PSTACK,int);
bool empty(PSTACK);
void traverse(PSTACK);
bool pop(PSTACK);
void clear(PSTACK);

//主函数
int main(void)
{
	
	STACK S;
	int val;
	/*测试初始化栈及压栈函数*/
	init(&S);
	push(&S, 1);
	push(&S, 2);
	push(&S, 3);
	push(&S, 4);
	push(&S, 5);
	traverse(&S);
	/*测试出栈*/
	pop(&S);
	traverse(&S);
	//测试清空栈
	clear(&S);
	traverse(&S);
	
 
 } 
 
 //栈的初始化 ,形参是指针变量,所以传参的时候,要把数据的地址传进来 
void init(PSTACK pS)
{
 	//注意这里是给栈里的单个节点分配内存,而不是给整个栈
	 //不要写成 (PSTACK)malloc(sizeof(STACK))  冒傻气 
 	pS->pTop = (PNODE)malloc(sizeof(NODE));
 	if(NULL == pS->pTop)
	{
	 	printf("n内存分配失败");
	 	exit(-1); 
	} 
	else
	{
	 	pS->pBottom = pS->pTop;
	 	//由于现在 pS->pBottom = pS->pTop,
		//所以写成 pS->pBottom->pNext = NULL 也是可以的 
 	    pS->pBottom->pNext = NULL;//pBottom无实际意义,所以他指向的下一个节点是无,要设置为空
	}	
}
 
 //压栈操作,top 和bottom 都是无实际意义的节点,见最后面的图
void push(PSTACK pS,int val)
{
	//给压栈的数据,动态分配一块内存 
	PNODE pNew = (PNODE)malloc(sizeof(NODE)); 
	if(NULL == pNew)
	{
		printf("n内存分配失败");
	 	exit(-1);
	}
	
	pNew->data = val;
	/*这里的理解还存在问题 
	问题的原因是没有理解什么是压栈,方向搞混了 
	是top顶指针节点,指向bottom底部指针节点 
	直接pTop=pNew 是因为,pTop 没有意义,可以直接赋值
	*/
	//下面这个地方稍微有点绕,最好画个图	
	pNew->pNext = pS->pTop;
	pS->pTop = pNew;	
}

//这是出栈,脑子干什么去了? 
bool pop(PSTACK pS)
{
	PNODE pTemp;//防止改变原来的栈,定义一个临时节点
	if( empty(pS) )
	{
		printf("此栈为空");
		return false; 
	}
	else
	{
		pTemp->pNext = pS->pTop->pNext;
		//* val = pS->pTop->data;
		pS->pTop = pTemp->pNext;
		free(pTemp);
		pTemp = NULL;
		return true;
	}
	
}

//不用判断是否满,因为理论上是无限的 
bool empty(PSTACK pS)
{
	if(pS->pBottom == pS->pTop)
	{
		return true;
	}
	else
	{
		return false;
	}
}
 
//遍历链表 
void traverse(PSTACK pS)
{
	PNODE pT;
	if(empty(pS))
	{
		printf("空栈");
	}
	else
	{
		PNODE pTemp;
		pTemp = pS->pTop;
		/*错误写法 ,调试结果出来为空栈 
		while(pS->pBottom != pS->pTop)
	    {
		printf(" %d", pS->pTop->data);
		pS->pTop = 	pS->pTop->pNext;
	    }
	     
	    */
	    ///* 
		while(pTemp != pS->pBottom)
		{
			printf(" %d", pTemp->data);
			pTemp = pTemp->pNext;
		}
		//*/ 
		printf("\n");
	 } 
	return;
}
 
void clear(PSTACK pS)
{
	if( empty(pS) )
	{
		printf("空"); 
	}
	else
	{
		while(pS->pTop != pS->pBottom)
		{
			PNODE pTemp = pS->pTop;
			pS->pTop = pS->pTop->pNext;
			free(pTemp);
		}
	}
}

压栈操作示意
函数的调用,利用的就是压栈出栈的原理,递归也是
如下图
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值