数据结构之栈

栈的定义

栈(stack)是限定于在表尾进行插入和删除操作的线性表
可以理解为后进先出,先进后出的数据结构

栈的基本操作

1.Push
将数据压入栈中,压出的数据成为新的栈顶
2.Pop
获取栈顶数据,并释放,原栈顶后一个元素成为新栈顶



栈的分类

1.顺序存储结构栈

用一段内存作为栈的存储空间,top指向栈顶元素的下标

2.共享空间栈

两个类型的栈共享一段内存,适用于此消彼长型的数据情况。top1指向栈1的栈顶,top2指向栈2的栈顶,当top1与top2碰头则栈空间不足。

3.链栈

     就是一个只允许在线性链表表头插入删除的线性链表top为指向链表节点的指针。
C实现

1.顺序结构栈

栈结构为
typedef struct item//普通栈
{
	int buffer[MAX_SIZE];//这个其实可以动态分配
	int top=-1;
}Stack;
MAX_SIZE为一个宏定义

Push操作
bool Push(Stack *L,int *arry,int lenth)
{
	if (MAX_SIZE - L->top - 1<lenth)return 0;//看空间是否足够
	for (int i = 0; i < lenth; i++)
	{
		L->top++;
		L->buffer[L->top] = arry[i];
	}
	return 1;
}

该操作允许向栈中压入一组数据,会进行对栈空间进行计算,如果栈空间不够(MAX_SIZE-L->top-1)则返回0,压入成功返回1

Pop操作
bool Pop(Stack *L, int *e)
{
	if (L->top == -1)return 0;
	*e = L->buffer[L->top];
	L->top--;
	return 1;
}
弹出操作会先判断栈中是否有数据即栈顶知否指向-1,如果是则表示栈为空返回0,否则返回栈顶数据。

因为插入与弹出操作均未涉及到循环所以其时间复杂度为O(1)

2.共享空间栈

栈结构:
typedef struct date//共享空间栈
{
	int buffer[MAX_SIZE];
	int top1=-1;
	int top2=MAX_SIZE;
}SqlStack;

top1指向数组的底部  top2指向数据的顶部 MAX_SIZE依然是对数组长度的宏定义

Push操作
bool Push(SqlStack *L,int *arry,int lenth,int Stacknum)//适用于两栈共享
{
	if (L->top1 + lenth > L->top2)return 0;//没有存储空间了
	if (Stacknum == 1)
	{
		for (int i = 0; i < lenth; i++)
		{
			L->top1++;
			L->buffer[L->top1] = arry[i];
		}
	}
	else if (Stacknum == 2)
	{
		for (int i = 0; i < lenth; i++)
		{
			L->top2--;
			L->buffer[L->top2] = arry[i];
		}
	}
	else return 0;
	return 1;
}
该操作依然允许压入一组数据,并且需要指出压入栈1或者压入栈2,当top1与top2碰面则表示该栈空间已不足返回0,否则完成操作后返回1


Pop操作
bool Pop(SqlStack *L,int *date,int Stacknum)
{
	if (L->top1 == -1 && L->top2 == MAX_SIZE)return 0;//栈中没有数据
	if (Stacknum == 1)
	{
		*date = L->buffer[L->top1];
		L->top1--;
	}
	else if (Stacknum == 2)
	{
		*date = L->buffer[L->top2];
		L->top2++;
	}
	else return 0;
	return 1;
}

弹出栈顶元素的数据,这里判断空栈的方式是top1=-1并且top2=MAX_SIZE


3.链栈

数据结构:
节点:
typedef struct obj
{
	int num = 0;
	obj*next = NULL;
}StackNode,*LinkStackPtr;


栈结构:
typedef struct element
{
	LinkStackPtr top=NULL;
	int count;
}LinkStack;//链栈

Push操作:
bool Push(LinkStack *L,int date)//新加入的元素会在顶部
{
	LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode));
	s->num = date;
	s->next = L->top;
	L->top = s;
	L->count++;
	return 1;
}

该操作会先创建一个链节点s为其分配存储空间 s的向后指针next指向栈顶之后栈顶指针指向s,此时操作结束top指向s,s指向栈原栈顶元素
Pop操作:
bool Pop(LinkStack *L,StackNode *e)
{
	LinkStackPtr ptr;
	if (L->top==NULL)return 0;
	e->num = L->top->num;
	ptr = L->top;
	L->top = L->top->next;
	free(ptr);
	L->count--;
	return 1;
}
该操作依然会先对链栈进行判断是否是空链栈,判断方式可以是判断count的值,也可以判断top指针是否为空
copy一个节点元素并将其复制给e所在地址的元素返回。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值