关于栈的学习

栈的定义

1、栈是操作被限制的线性表,栈底不能操作,入栈和出栈的操作都在栈顶,一般用数组来表示,栈底就是下标为0的数组元素,另一头为栈顶

2、栈分为两种,顺序栈和链栈,最主要的是顺序栈。

3、栈符合先进后出,后进先出的规则

一、顺序栈

1、结构

顺序栈的结构包含了数据项(数组)和指针项(数组下标),指针项称为栈顶指针top,通常栈顶指针top指向栈顶元素,那么就可以推出当栈顶指针top=(-1)时是个空栈。

2、顺序栈的操作

(1)栈结构的定义

typedef struct//栈体的定义
{
	int num[MAXSIZE];//栈元素的存储
	int top;//栈顶指针,为-1时为空栈,等于MAXSIZE-1时为满栈
}Sequen;

(2)栈的初始化操作

Sequen* Init(void)//栈的初始化,包括栈结构的内存申请,栈顶指针的初始赋值,返回栈结构的地址
{
	Sequen *st=(Sequen*)malloc(sizeof(Sequen));//申请结构体的空间大小,并把地址赋给st,申请失败会返回0
	st->top=-1;
	return st; 
}

(3)入栈

void pushsstack(Sequen* st,int data)//入栈
{
	if(!st || st->top==MAXSIZE-1)//判断栈结构是申请到空间或者是否满栈
	{
		printf("满了或没有栈体\n");
		return;
	}
	st->top++;//将栈顶指针往后移动一位
	st->num[st->top]=data;//将入栈的元素放入栈顶中
	return;
}

(4)出栈

int popsstack(Sequen* st)//出栈
{
	int i;
	if(!st || st->top==-1)//判断栈结构是申请到空间或者是否空栈
	{
		printf("满了或没有栈体\n");
		return 0;
	}
	i=st->num[st->top];//将要出栈的元素保存在i中
	st->top--;//栈顶指针往前移动一位
	return i;
}

(5)取栈顶元素

int qusstack(Sequen* st)//取栈顶元素
{
	int i;
	if(!st || st->top==-1)
	{
		printf("满了或没有栈体\n");
		return 0;
	}
	i=st->num[st->top];//注意:此时不需要改变栈顶的指针位置
	return i;
}

(6)判断栈空

void kosstack(Sequen* st)//判断空栈
{
	if(st->top==-1)//如果栈顶指针等于-1则
	{
		printf("空\n");
	}
	else if(!st)//如果没有申请成功栈体则
		printf("没有栈体\n");
	return;
}

(7)清除栈

void clearsstack(Sequen* st)//清除栈
{
	st->top=-1;//将栈顶指针复位-1
	return;
}

(8)栈的调试

void main()
{
	int i;
	Sequen* st;//定义栈体指针
	st=Init();//栈的初始
	kosstack(st);//判断栈空,此时应该为空
	pushsstack(st,100);//入栈
	i=popsstack(st);//出栈
	pushsstack(st,200);//入栈
	i=qusstack(st);//取栈顶元素
	printf("%d \n",i);
}

3、总程序

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 5
typedef struct//栈体的定义
{
	int num[MAXSIZE];//栈元素的存储
	int top;//栈顶指针,为-1时为空栈,等于MAXSIZE-1时为满栈
}Sequen;
Sequen* Init(void)//栈的初始化,包括栈结构的内存申请,栈顶指针的初始赋值,返回栈结构的地址
{
	Sequen *st=(Sequen*)malloc(sizeof(Sequen));//申请结构体的空间大小,并把地址赋给st,申请失败会返回0
	st->top=-1;
	return st; 
}
void pushsstack(Sequen* st,int data)//入栈
{
	if(!st || st->top==MAXSIZE-1)//判断栈结构是申请到空间或者是否满栈
	{
		printf("满了或没有栈体\n");
		return;
	}
	st->top++;//将栈顶指针往后移动一位
	st->num[st->top]=data;//将入栈的元素放入栈顶中
	return;
}
int popsstack(Sequen* st)//出栈
{
	int i;
	if(!st || st->top==-1)//判断栈结构是申请到空间或者是否空栈
	{
		printf("满了或没有栈体\n");
		return 0;
	}
	i=st->num[st->top];//将要出栈的元素保存在i中
	st->top--;//栈顶指针往前移动一位
	return i;
}
int qusstack(Sequen* st)//取栈顶元素
{
	int i;
	if(!st || st->top==-1)
	{
		printf("满了或没有栈体\n");
		return 0;
	}
	i=st->num[st->top];//注意:此时不需要改变栈顶的指针位置
	return i;
}
void kosstack(Sequen* st)//判断空栈
{
	if(st->top==-1)//如果栈顶指针等于-1则
	{
		printf("空\n");
	}
	else if(!st)//如果没有申请成功栈体则
		printf("没有栈体\n");
	return;
}
void clearsstack(Sequen* st)//清除栈
{
	st->top=-1;//将栈顶指针复位-1
	return;
}
void main()
{
	int i;
	Sequen* st;//定义栈体指针
	st=Init();//栈的初始
	kosstack(st);//判断栈空,此时应该为空
	pushsstack(st,100);//入栈
	i=popsstack(st);//出栈
	pushsstack(st,200);//入栈
	i=qusstack(st);//取栈顶元素
	printf("%d \n",i);
}

二、链栈

1、结构

链栈就是链表,将链表的头指针看成栈顶指针,去掉头节点,用链表的头插法实现栈的出入即可

2、链栈的操作

(1)栈节点结构及栈的维护定义

//定义链的节点的结构体
typedef struct linkst
{
	int data;//数据域
	struct linkst *next;//指针域
}Listnode;
//链栈的维护结构
typedef struct
{
	int num;//栈的计数
	struct linkst *top;//栈顶指针
}safeg;

(2)栈的初始化操作

safeg* Init()//返回的是维护结构的地址
{
	safeg* st=(safeg*)malloc(sizeof(safeg));//申请维护结构内存
	st->num=0;//将栈元素的计数清0
	st->top=NULL;//栈顶指针指向NULL,避免野指针
	return st;//返回维护结构的地址
}

(3)入栈

void pushstack(safeg *st,int n)//输入维护(操作)的结构体地址和入栈的数据
{
	Listnode* tmp;//定义一个指向结构体节点的指针
	if(!st)//如果申请的维护结构失败了,没钱不干了
	{
		printf("链栈的维护结构未创建\n");
		return;
	}
	tmp =(Listnode*)malloc(sizeof(Listnode));//申请链的节点的内存
	if(st->num==0 || st->top==NULL)//如果是空栈,即第一次入栈
	{
		st->top=tmp;//先将栈顶指针 指向新申请的第一个节点地址
		tmp->data=n;//将入栈的数据放入第一个节点
		tmp->next=NULL;//头插法,将第一个的节点的指针域置为NULL
		st->num++;//将栈计数器加一
		return;//函数返回
	}
	else//不是第一次入栈
	{
		tmp->data=n;//将入栈的数据放入节点
		tmp->next=st->top;//将新的节点的指针域指向栈顶指针
		st->top=tmp;//将栈顶指针指向新的节点
		st->num++;//将栈计数器加一
	}
}

(4)出栈

int popstack(safeg *st)//返回出栈的数据
{
	int i;
	Listnode* tmp;//定义结构体节点的指针
	if(!st || st->num==0 || st->top==NULL)//判断是否申请了维护结构的内存或者为空栈
	{
		printf("非法!\n");
		return 0;
	}
	tmp=st->top;//将结构体的指针指向栈顶指针同个地址(要出栈的地址)
	i=tmp->data;//将要出栈的数据保存
	st->top=tmp->next;//将栈顶指针移向下一个链节点
	(st->num)--;//将栈计数器减一
	tmp->next=NULL;//将出栈节点的指针域指向NULL
	free(tmp);//释放出栈的节点
	tmp=NULL;//避免野指针
	return i;//返回出栈节点的数据
}

(5)取栈顶元素

//取栈顶元素
int getstack(safeg *st)//和出栈类似,但是栈顶指针不用移动
{
	int n;
	if(!st || (st->top==NULL) || st->num==0)
	{
		printf("非法!\n");
		return 0;
	}
	n=(st->top)->data;
	return n;
}

(6)判断栈空

void kostack(safeg *st)
{
	if(!st || (st->top==NULL) || st->num==0)
	{
		printf("非法!\n");
	}
}

(7)清除栈

void clearstack(safeg *st)
{
	Listnode *p1,*p2;//定义两个链节点的指针
	if(!st || (st->top==NULL) || st->num==0)//判栈空
	{
		return;
	}
	p1=st->top;//将p1指向栈顶指针的节点地址(要删除的节点地址)
	p2=p1->next;//p2指向下一个节点
	while(p1!=NULL)//只要栈顶指针不为空
	{
		st->top=p2;//将栈顶指针移动到下一个节点位置
		p1->next=NULL;//将要删除节点的指针域指向NULL1
		free(p1);//释放要删除的节点
		p1=NULL;//避免野指针
		p1=p2;
		if(p2) p2=p1->next;//如果p2指向不为NULL,则将p2移动到下一个节点
		else  p2=NULL;//否则,p2为NULL
		st->num--;//将栈计数器减一
	}
}

(8)栈的调试

void main()
{
	int i,n;
	safeg* st;
	st=Init();
	pushstack(st,100);
	pushstack(st,200);
	pushstack(st,300);
	printf("栈的元素个数:%d\n",st->num);
	/*for(i=0;i<4;i++)
	{
		n=popstack(st);
		printf("%d ",n);
	}*/
	clearstack(st);
	printf("栈的元素个数:%d\n",st->num);
}

三、总程序

#include<stdio.h>
#include<stdlib.h>
//定义链的节点的结构体
typedef struct linkst
{
	int data;//数据域
	struct linkst *next;//指针域
}Listnode;

//链栈的维护结构
typedef struct
{
	int num;//栈的计数
	struct linkst *top;//栈顶指针
}safeg;

//链栈维护的初始化
safeg* Init()//返回的是维护结构的地址
{
	safeg* st=(safeg*)malloc(sizeof(safeg));//申请维护结构内存
	st->num=0;//将栈元素的计数清0
	st->top=NULL;//栈顶指针指向NULL,避免野指针
	return st;//返回维护结构的地址
}

//入栈
void pushstack(safeg *st,int n)//输入维护(操作)的结构体地址和入栈的数据
{
	Listnode* tmp;//定义一个指向结构体节点的指针
	if(!st)//如果申请的维护结构失败了,没钱不干了
	{
		printf("链栈的维护结构未创建\n");
		return;
	}
	tmp =(Listnode*)malloc(sizeof(Listnode));//申请链的节点的内存
	if(st->num==0 || st->top==NULL)//如果是空栈,即第一次入栈
	{
		st->top=tmp;//先将栈顶指针 指向新申请的第一个节点地址
		tmp->data=n;//将入栈的数据放入第一个节点
		tmp->next=NULL;//头插法,将第一个的节点的指针域置为NULL
		st->num++;//将栈计数器加一
		return;//函数返回
	}
	else//不是第一次入栈
	{
		tmp->data=n;//将入栈的数据放入节点
		tmp->next=st->top;//将新的节点的指针域指向栈顶指针
		st->top=tmp;//将栈顶指针指向新的节点
		st->num++;//将栈计数器加一
	}
}

//出栈
int popstack(safeg *st)//返回出栈的数据
{
	int i;
	Listnode* tmp;//定义结构体节点的指针
	if(!st || st->num==0 || st->top==NULL)//判断是否申请了维护结构的内存或者为空栈
	{
		printf("非法!\n");
		return 0;
	}
	tmp=st->top;//将结构体的指针指向栈顶指针同个地址(要出栈的地址)
	i=tmp->data;//将要出栈的数据保存
	st->top=tmp->next;//将栈顶指针移向下一个链节点
	(st->num)--;//将栈计数器减一
	tmp->next=NULL;//将出栈节点的指针域指向NULL
	free(tmp);//释放出栈的节点
	tmp=NULL;//避免野指针
	return i;//返回出栈节点的数据
}

//取栈顶元素
int getstack(safeg *st)//和出栈类似,但是栈顶指针不用移动
{
	int n;
	if(!st || (st->top==NULL) || st->num==0)
	{
		printf("非法!\n");
		return 0;
	}
	n=(st->top)->data;
	return n;
}

//判断栈空
void kostack(safeg *st)
{
	if(!st || (st->top==NULL) || st->num==0)
	{
		printf("非法!\n");
	}
}

//清除栈
void clearstack(safeg *st)
{
	Listnode *p1,*p2;//定义两个链节点的指针
	if(!st || (st->top==NULL) || st->num==0)//判栈空
	{
		return;
	}
	p1=st->top;//将p1指向栈顶指针的节点地址(要删除的节点地址)
	p2=p1->next;//p2指向下一个节点
	while(p1!=NULL)//只要栈顶指针不为空
	{
		st->top=p2;//将栈顶指针移动到下一个节点位置
		p1->next=NULL;//将要删除节点的指针域指向NULL1
		free(p1);//释放要删除的节点
		p1=NULL;//避免野指针
		p1=p2;
		if(p2) p2=p1->next;//如果p2指向不为NULL,则将p2移动到下一个节点
		else  p2=NULL;//否则,p2为NULL
		st->num--;//将栈计数器减一
	}
}

//主函数
void main()
{
	int i,n;
	safeg* st;
	st=Init();
	pushstack(st,100);
	pushstack(st,200);
	pushstack(st,300);
	printf("栈的元素个数:%d\n",st->num);
	/*for(i=0;i<4;i++)
	{
		n=popstack(st);
		printf("%d ",n);
	}*/
	clearstack(st);
	printf("栈的元素个数:%d\n",st->num);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值