栈的初识(C语言)(1)

观 郝斌老师 视频

目录

一.栈的定义(Stack)

二.栈的分类

三.栈的基本操作

1.压栈(Push)

2.出栈(Pop)

四.栈的实现

(一)动态栈的实现

1.创建结构体

2.函数声明

3.栈的初始化

4.压栈

5.遍历

6.出栈

7.判断是否为空栈

8.清空

9.完整代码(动态栈实现)

(二)静态栈的实现

1.简单描述

 2.完整代码(动态栈实现)

四.栈的应用(略)


一.栈的定义(Stack)

栈是限制插入和删除只能在一个位置上进行的表,该位置 是表的末端,叫做栈的顶部(Top)。

栈是一种实现“先进后出”的存储结构。

类似于箱子,只能一端在箱子的同一端进出。

二.栈的分类

栈分为两种:

静态栈(数组栈)(用数组实现)

动态栈(链式栈)(用链表实现)

三.栈的基本操作

1.压栈(Push)

2.出栈(Pop)

四.栈的实现

(一)动态栈的实现

1.创建结构体

//创建结构体

typedef struct Node 
{
	int data;
	struct Node * pNext;
}NODE,*PNODE; //创建链表的结点

typedef struct Stack
{
	PNODE pTop;    //栈顶
	PNODE pBottom; //栈底
}STACK,*PSTACK; //创建栈的大概框架

2.函数声明


//函数声明 
void init (PSTACK );//初始化
void push (PSTACK ,int  ) ; //压栈/入栈
bool pop (PSTACK ,int *);//出栈 
bool empty (PSTACK ); //判断是否为空 
void traverse (PSTACK);//遍历 
void clear (PSTACK);//清空 

3.栈的初始化

//栈的初始化

void init (PSTACK ps)//创造一个空栈 ,需要一个头指针(方便链表) 
{
	ps->pTop = (PNODE)malloc(sizeof(NODE));
	if(NULL == ps->pTop)
	{
		printf("动态分配内存失败!\n");
		exit(-1);
	}
	else
	{
		ps->pBottom = ps->pTop;//栈底 等于 栈顶,则栈为空
		ps->pBottom->pNext = NULL;//或ps->pTop->pNext = NULL; 使底指针(头指针)的指针域为空 
	}
	return;
}

4.压栈

//压栈

void push (PSTACK ps ,int val )//可以不用 int * ,因为没有改变 val。 
{
	PNODE pnew = (PNODE) malloc (sizeof (NODE));
	
	pnew->data = val;
	pnew->pNext = ps->pTop;//ps->pTop 不能改为 ps->pBottom 
	ps->pTop = pnew;
	
	return ;
}

5.遍历

//遍历

void traverse (PSTACK ps)
{
	PNODE p = ps->pTop; //遍历不改变栈,所以要定义一个新的变量,不移动Top
	while(p != ps->pBottom)
	{
		printf("%3d",p->data);//可以进行相关替换
		p = p->pNext;
	}
	printf("\n");
}

6.出栈

//出栈

//把 ps 所指向的栈 出栈一次,并把出栈的元素存入 pval形参 所指向的变量中 ,如果出栈失败返回false
bool pop (PSTACK ps,int * pval)
{
	if( empty(ps) )// ps 本身就存放的就是 s 的地址 
	{
		return false;
	}
	else
	{
		PNODE r = ps->pTop;
		ps->pTop = r->pNext;
		* pval = r->data ;//不能 pval = &r->data; (有区别) 
		free(r);
		r = NULL;
	}
}

7.判断是否为空栈

//判断是否为空栈

bool empty (PSTACK ps)
{
	if( ps->pBottom == ps->pTop)
	{
		return true;
	}
	else
	{
		return false;
	}
}

8.清空

//清空(注意清空与销毁的区别)
//清空只是清除数据,框架仍然存在;销毁是整个栈不存在了

void clear (PSTACK ps)
{
	if(empty(ps))
	{
		return ;
	}
	else
	{
		PNODE p = ps->pTop ,q = NULL;
		
		while(p != ps->pBottom)
		{
			q = p->pNext;
			free(p);
			p = q;
		}
		ps->pTop = ps->pBottom;
	}
}

9.完整代码(动态栈实现)

/*链式栈*/

#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;

//函数声明 
void init (PSTACK );//初始化
void push (PSTACK ,int  ) ; //压栈/入栈
bool pop (PSTACK ,int *);//出栈 
bool empty (PSTACK ); //判断是否为空 
void traverse (PSTACK);//遍历 
void clear (PSTACK);//清空 

int main(void)
{
	STACK s;//创建一个名为 s 的栈 ,未存放有效数据 
	int val;
	
	init (&s);
	
	push(&s,1);
	push(&s,54);
	push(&s,3);
	push(&s,2);
	push(&s,7);
	push(&s,8);
	traverse(&s);
		
	if(pop(&s,&val))
	{
		printf("出栈成功,出栈元素是%d\n",val);
	}
	else
	{
		printf("出栈失败\n");
	}
	traverse(&s);
	
	clear (&s);
	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->pBottom->pNext = NULL;//或ps->pTop->pNext = NULL; 使底指针(头指针)的指针域为空 
	}
	return;
}

void push (PSTACK ps ,int val )//可以不用 int * ,因为没有改变 val。 
{
	PNODE pnew = (PNODE) malloc (sizeof (NODE));
	
	pnew->data = val;
	pnew->pNext = ps->pTop;//ps->pTop 不能改为 ps->pBottom 
	ps->pTop = pnew;
	
	return ;
}

void traverse (PSTACK ps)
{
	PNODE p = ps->pTop;
	while(p != ps->pBottom)
	{
		printf("%3d",p->data);
		p = p->pNext;
	}
	printf("\n");
}

//把 ps 所指向的栈 出栈一次,并把出栈的元素存入 pval形参 所指向的变量中 ,如果出栈失败返回false
bool pop (PSTACK ps,int * pval)
{
	if( empty(ps) )// ps 本身就存放的就是 s 的地址 
	{
		return false;
	}
	else
	{
		PNODE r = ps->pTop;
		ps->pTop = r->pNext;
		* pval = r->data ;//不能 pval = &r->data; (有区别) 
		free(r);
		r = NULL;
	}
}

bool empty (PSTACK ps)
{
	if( ps->pBottom == ps->pTop)
	{
		return true;
	}
	else
	{
		return false;
	}
}

void clear (PSTACK ps)
{
	if(empty(ps))
	{
		return ;
	}
	else
	{
		PNODE p = ps->pTop ,q = NULL;
		
		while(p != ps->pBottom)
		{
			q = p->pNext;
			free(p);
			p = q;
		}
		ps->pTop = ps->pBottom;
	}
}

(二)静态栈的实现

1.简单描述

用一个数组实现栈,要提前声明数组的大小。(静态栈相对比较简单可以自己尝试实现)

空栈的 Top 为 -1 ,即空栈的初始化。

将 x 压入栈中,使 Top = Top + 1 ; Stack[Top] = x ; 其中Stack代表的是具体栈的数组名。

关于是否要判断栈是否已满的问题:链式栈一般不会有满的情况,不需要判断是否栈满。
数组栈可能会满,一般来说这并不是一个问题,因为在典型应用程序中,即使有相当多的栈操作,在任一时刻栈的元素的实际个数从不会太大。 

 2.完整代码(动态栈实现)

/*数组栈*/ 

#include<stdio.h>
#define N 7

typedef struct Stack
{
	int Top;
	int stack[N];
}STACK;

//函数声明
void init (STACK *);
bool push(STACK * , int );
bool full(STACK *);
bool empty(STACK *);
bool pop(STACK * ,int *);
void traverse(STACK *);

int main(void)
{
	STACK s;
	int val;
	
	init(&s);
	push(&s,15);
	push(&s,8);
	push(&s,7);
	push(&s,6);
	push(&s,5);
	push(&s,4);
	push(&s,3);
	push(&s,1);//不能压入栈,因为 N = 7,此为第八个元素 
	traverse(&s);
	
	if(pop(&s,&val))
	{
		printf("出栈成功,出栈的元素为:%d\n",val);
	}
	else
	{
		printf("出栈失败\n");
	}
	traverse(&s);
	
	return 0;
}

void init (STACK * ps)
{
	ps->Top = -1;
	return ;
}

//压栈 
bool push(STACK * ps, int val)
{
	if( full(ps) )
	{
		return false;
	}
	else
	{
		ps->Top = ps->Top + 1;
		ps->stack[ps->Top] = val;
		return true;
	}
}

//判断栈是否已满,一般不需要 
bool full(STACK *ps)
/*链式栈一般不会有满的情况,不需要判断是否栈满。
但是数组栈可能会满,一般来说这并不是一个问题,
因为在典型应用程序中,即使有相当多的栈操作,
在任一时刻栈的元素的实际个数从不会太大。 
*/
{
	if( N - 1 == ps->Top )
	{
		return true;
	}
	else
	{
		return false;
	}
}

//出栈 
bool pop(STACK * ps,int * pval)
{
	if( empty(ps) )
	{
		return false;
	}
	else
	{
		* pval = ps->stack[ps->Top];
		ps->Top = ps->Top - 1;
		return true;
	}
	
}

//判断栈是否为空 
bool empty(STACK * ps)
{
	if(ps->Top == -1)
	{
		return true;
	}
	else
	{
		return false;
	}
}

//遍历 
void traverse(STACK * ps)
{
	if( empty(ps) )
    {
    	;
	}
    else
    {
    	int p = ps->Top;
    	while(p >= 0)
    	{
    		printf("%4d",ps->stack[p]);
    		p = p - 1;
		}
	}
	printf("\n");
	return ;
}

四.栈的应用(略)

1.函数调用

2.中断

3.表达式求值

4.内存分配

5.缓冲处理

6.迷宫

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值