数据结构——栈(链栈)

本文详细介绍了链栈的概念和实现,包括初始化、入栈、出栈、获取栈顶元素、判断栈是否为空、获取栈的长度、清空、销毁及打印等功能。通过示例展示了如何使用链栈存储和操作数据,如入栈20个数字并进行出栈、获取栈顶元素等操作。
摘要由CSDN通过智能技术生成

栈的概念:只能在表尾进行插入(入栈)和删除(出栈)的数据结构(受到限制的线性表)。

表尾比较特殊,我们一般把这个表尾叫做栈顶,另一端栈底。没有数据节点,则叫做空栈。

上一篇文章将的是顺序栈(包括栈的概念),顺序栈结构体设计里面一共三个成员,即一个指针(用来接收malloc从堆内申请的一整块内存)、栈顶指针和存储当前最大的容量的值;而链栈的结构体和单链表相同,只不过这里要注意的点在于用单链表的头插和头删代替表尾进行插入和删除。

链栈的结构体设计:

typedef int ELEM_TYPE;

//链式栈的结构体声明:  直接用单链表的即可
typedef struct LStack
{
	ELEM_TYPE data;//数据域
	struct LStack* next;//指针域
}LStack, * PLStack;

链栈可执行函数声明:

//初始化
void Init_LStackl(struct LStack* ps);

//入栈(插入)
bool Pushl(PLStack ps, ELEM_TYPE val);

//出栈(获取删除的栈顶元素值,并且删除) //用到一个输出参数
bool Popl(PLStack ps, ELEM_TYPE* rtval);

//获取栈顶元素(获取栈顶元素值,但是不删除) //用到一个输出参数
bool Topl(PLStack ps, ELEM_TYPE* rtval);

//判空
bool IsEmptyl(PLStack ps);


//获取有效长度
int Get_lengthl(PLStack ps);

//清空
void Clearl(PLStack ps);

//销毁
void Destroyl(PLStack ps);

//打印
void Show(PLStack ps);

初始化:

void Init_LStackl(struct LStack* ps)
{
	assert(ps != NULL);
	ps->next = NULL;
}

入栈:

bool Pushl(PLStack ps, ELEM_TYPE val)
{
	assert(ps != NULL);
	//assert
	//1.购买新节点
	struct LStack* pnewnode = (struct LStack*)malloc(1 * sizeof(struct LStack));
	assert(pnewnode != NULL);
	pnewnode->data = val;


	//2.找到合适的插入位置(头插,不用找,因为头结点就是合适位置)
	//3.进行插入
	pnewnode->next = ps->next;
	ps->next = pnewnode;
	return true;
}

出栈:(获取删除的栈顶元素值,并且删除) 用到一个输出参数

bool Popl(PLStack ps, ELEM_TYPE* rtval)
{
	assert(ps != NULL);
	assert(rtval != NULL);
	if (IsEmptyl(ps))//确实链栈至少有一个节点
	{
		return false;
	}
	*rtval = ps->next->data;//将一会要出栈的值 通过输出参数rtval带出来
	//申请一个临时指针指向待删除节点,跨越指向,释放待删除节点
	PLStack p = ps->next;
	ps->next = p->next;
	free(p);
	return true;
}

获取栈顶元素(获取栈顶元素值,但是不删除) //用到一个输出参数

bool Topl(PLStack ps, ELEM_TYPE* rtval)
{
	assert(ps != NULL);
	assert(rtval != NULL);
	if (IsEmptyl(ps))//确实链栈至少有一个节点
	{
		return false;
	}

	*rtval = ps->next->data;//将一会要出栈的值 通过输出参数rtval带出来
	return true;
}

判空:

bool IsEmptyl(PLStack ps)
{
	assert(ps != NULL);
	return ps->next == NULL;
}

获取有效长度:

int Get_lengthl(PLStack ps)
{
	assert(ps != NULL);
	int cout=0;
	//只要调用我们之前写的 两个for循环里面的那个 不需要前驱的for循环, 遍历一遍即可
	for (PLStack p = ps->next; p != NULL; p = p->next)
	{
		cout++;
	}
	return cout;
}

清空,销毁,打印

//清空
void Clearl(PLStack ps)
{
	assert(ps != NULL);
	Destroyl(ps);
}

//销毁
void Destroyl(PLStack ps)
{
	assert(ps != NULL);
	while (ps->next != NULL)
	{
		PLStack p = ps->next;
		ps->next = p->next;
		free(p);
	}
}

//打印
void Show(PLStack ps)
{
	assert(ps != NULL);
	for (PLStack p = ps->next; p != NULL; p = p->next)
	{
		printf("%d ", p->data);
	}
	printf("\n");
}

测试:

LStack head;//建立一个头结点
		Init_LStackl(&head);//初始化这个头结点
	
		for(int i=0; i<20; i++)//20 19 18.....3 2 1
		{
			Pushl(&head, i+1);//将1到20入栈
		}
		Show(&head);//打印1到20
		printf("length = %d\n", Get_lengthl(&head));//打印有效长度
	//出栈,并且获取出栈的元素
		ELEM_TYPE tmp;
		bool tag1 = Popl(&head, &tmp);
		if(tag1)
		{
			printf("pop = %d\n", tmp);//打印出栈的值
		}
		Show(&head);//打印出栈后的链栈
		printf("length = %d\n", Get_lengthl(&head));//打印有效长度
	//获取栈顶元素值(不删除)
		ELEM_TYPE flg;
		bool tag2 = Topl(&head, &flg);
		if(tag2)
		{
			printf("top = %d\n", flg);//打印栈顶元素值
		}
		Show(&head);//打印
		printf("length = %d\n", Get_lengthl(&head));//打印有效长度
	
		Destroyl(&head);//销毁

结果:

 没有内存泄漏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值