C语言实现栈--数据结构

这篇具有很好参考价值的文章主要介绍了C语言实现栈--数据结构。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C语言实现栈--数据结构

  • 魔王的介绍:😶‍🌫️一名双非本科大一小白。
  • 魔王的目标:🤯努力赶上周围卷王的脚步。
  • 魔王的主页:🔥🔥🔥大魔王.🔥🔥🔥
    C语言实现栈--数据结构
    ❤️‍🔥大魔王与你分享:“断剑重铸的锐雯败于菲奥娜,原来破镜重圆的爱到处都是破绽”。

一、前言

1、介绍

栈是一种特殊的线性表,其只允许在固定的一端插入和删除元素,进行插入和删除的一端称为栈顶,另一端称为栈底,栈中的数据元素遵循后进先出(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈。入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。

C语言实现栈--数据结构

2、说明

栈的实现可以采用顺序表或链表,顺序表就是按顺序存进去(尾插),然后出的时候需要从后往前出。链表的话我们一边采用头插,因为如果是尾插的话,还要有前一个的地址,比头插麻烦一点,所以链表实现一般采用头插。
相对来说数组(顺序表)实现更优一些,因为数组在尾上插入数据代价更小。
如果顺序表和链表你已经掌握,那么相信栈和队列对你来说都是很简单的,因为它们只是对顺序表和链表进行特殊处理而已。

  • 本篇将通过顺序表实现栈。

二、栈的实现

1、创建结构体

我们需要创建一个结构体来存放数组指针和该数组的元素个数及数组的容量。

代码:

typedef int STDateType;

typedef struct Stack
{
	STDateType* a;
	int top;//如果初始化为0,可以理解为元素个数(也就是栈顶元素下标+1),如果初始化为-1,可以理解为栈顶元素的下标
	int capacity;
}ST;

2、初始化和销毁

初始化:
就像顺序表一样,我们需要首先开辟一个初始空间,然后不够的时候在扩容。
销毁:
因为空间是malloc在堆区申请出来的,所以需要我们进行手动释放,防止内存泄露。

代码:

//初始化和最后销毁
void STInit(ST* ps)
{
	assert(ps);
	ps->a = (STDateType*)malloc(sizeof(ST) * 5);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		return;
	}
	ps->top = 0;
	ps->capacity = 5;
}
void STDestory(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->capacity = 0;
	ps->a = NULL;
	1.没有让top也就是栈顶位置重置。
	ps->top = 0;
	//最后在Test.c上让结构体指针指向空。
}

3、入栈

入栈只能从栈顶入。

//入栈
void STPush(ST* ps, STDateType x)
{
	assert(ps);
	if (ps->top == ps->capacity) //判断是否满了
	{
		STDateType* temp = (STDateType*)realloc(ps->a, ps->capacity * sizeof(ST) * 2);
		if (temp == NULL)
		{
			perror("realloc fail");
			return;
		}
		else
		{
			ps->a = temp;
			ps->capacity *= 2;
			temp = NULL;
		}
	}
	ps->a[ps->top] = x;
	ps->top++;
}

4、出栈

直接减1就行。

//出栈
void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	ps->top--;
}

5、元素个数

就等于我们结构体里记录数据个数的值。

//元素个数
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

6、判断是否为空

为什么这些简单的操作也要封装成函数呢?
因为编写函数的肯定是一个人,但是使用函数的人并不知道创建的具体是什么,比如结构体里的那个记录元素个数的,可能另一个人编写的时候该变量是记录栈顶下标的,那么就会总是比总个数小1,所以使用者并不能判断到底是哪个,所以需要编写函数的人把每个单独的功能都尽可能封装成函数,当使用者使用时,不需要区分那么多,直接调用对应函数,就能得到想要的结果。

代码:

//判断是否为空
bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

7、栈顶元素

同上一个的描述,因为不知道记录的是栈顶元素的下标还是元素的总个数,所以为了方便且避免出错,需要封装成函数让使用者使用。

//栈顶元素
STDateType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	return ps->a[ps->top - 1];
}

三、总代码

Stack.h

`Stack.h

  #pragma once

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

typedef int STDateType;

typedef struct Stack
{
	STDateType* a;
	int top;//如果初始化为0,可以理解为元素个数(也就是栈顶元素下标+1),如果初始化为-1,可以理解为栈顶元素的下标
	int capacity;
}ST;

//初始化和最后销毁
void STInit(ST* ps);
void STDestory(ST* ps);

//入栈
void STPush(ST* ps, STDateType x);

//出栈
void STPop(ST* ps);

//元素个数
int STSize(ST* ps);

//判断是否为空
bool STEmpty(ST* ps);

//栈顶元素
STDateType STTop(ST* ps);

Stack.c

Stack.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Stack.h"

//初始化和最后销毁
void STInit(ST* ps)
{
	assert(ps);
	//ps->a = malloc(sizeof(ST) * 5);  1.没有强转
	ps->a = (STDateType*)malloc(sizeof(ST) * 5);
	2.开辟新空间后没有检查
	if (ps->a == NULL)
	{
		perror("malloc fail");
		return;
	}
	ps->top = 0;
	ps->capacity = 5;
}
void STDestory(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->capacity = 0;
	ps->a = NULL;
	1.没有让top也就是栈顶位置重置。
	ps->top = 0;
	//最后在Test.c上让结构体指针指向空。
}

//入栈
void STPush(ST* ps, STDateType x)
{
	assert(ps);
	//if (ps->top == ps->capacity)
	//{
	//	ST* str = realloc(ps->a, ps->capacity * sizeof(ST) * 2);
	//	if (str == NULL)
	//	{
	//		perror("realloc fail");
	//		return;
	//	}
	//}  
	1.没有把扩容的时候创建的新指针赋给原指针
	if (ps->top == ps->capacity) //判断是否满了
	{
		//ST* temp = realloc(ps->a, ps->capacity * sizeof(ST) * 2);
		//2.指针应该指向数据的类型的地址,而且realloc也没强转为数据类型的指针
		STDateType* temp = (STDateType*)realloc(ps->a, ps->capacity * sizeof(ST) * 2);
		if (temp == NULL)
		{
			perror("realloc fail");
			return;
		}
		else
		{
			ps->a = temp;
			3.忘记让结构体内的容量*2
			ps->capacity *= 2;
			temp = NULL;
		}
	}
	ps->a[ps->top] = x;
	ps->top++;
}

//出栈
void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	ps->top--;
}

//元素个数
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

//判断是否为空
bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

//栈顶元素
STDateType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	return ps->a[ps->top - 1];
}

Test.c

Test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Stack.h"

int main()
{
	ST ps;
	STInit(&ps);
	STPush(&ps, 0);
	STPush(&ps, 1);
	STPush(&ps, 2);
	STPush(&ps, 3);
	STPush(&ps, 4);

	//打印,因为只能从栈顶出,所以每打印一个数据就需要弹出这个数据(出栈)。

	while (!STEmpty(&ps))
	{
		printf("%d ", STTop(&ps));
		STPop(&ps);//打印和出栈是一对,因为想要打印下一个,那么栈顶的元素必须出栈
	}
	STDestory(&ps);
	ps.a = NULL;
	return 0;
}

四、总结

C语言实现栈--数据结构

✨请点击下面进入主页关注大魔王
如果感觉对你有用的话,就点我进入主页关注我吧!文章来源地址https://www.toymoban.com/news/detail-421540.html

到了这里,关于C语言实现栈--数据结构的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言实现栈--数据结构

    魔王的介绍:😶‍🌫️一名双非本科大一小白。 魔王的目标:🤯努力赶上周围卷王的脚步。 魔王的主页:🔥🔥🔥大魔王.🔥🔥🔥 ❤️‍🔥大魔王与你分享:“断剑重铸的锐雯败于菲奥娜,原来破镜重圆的爱到处都是破绽”。 栈是一种特殊的线性表,其只允许在固定的

    2023年04月22日
    浏览(25)
  • 堆--C语言实现数据结构

    本期带大家一起用C语言实现堆🌈🌈🌈 堆(Heap)是一种特殊的树状数据结构,它是一种完全二叉树。堆被广泛应用于优先队列、排序算法等领域。 堆的特点: 堆分为最大堆和最小堆两种类型。最大堆中,父节点的值大于或等于其子节点的值;最小堆中,父节点的值小于或

    2024年02月16日
    浏览(30)
  • 数据结构 队列(C语言实现)

            任其事必图其效;欲责其效,必尽其方。——欧阳修;本篇文章主要写的是什么是队列、以及队列是由什么组成的和这些组成接口的代码实现过程。( 大多细节的实现过程以注释的方式展示请注意查看 )    话不多说安全带系好,发车啦 (建议电脑观看) 。 附

    2024年02月11日
    浏览(47)
  • 队列--C语言实现数据结构

    本期带大家一起用C语言实现队列🌈🌈🌈 队列是一种线性数据结构,它按照先进先出(FIFO)的原则进行操作。可以把队列想象成排队买票或者排队上公交车的队伍。 顺序队列 由一个连续的内存区域组成,可以存储多个元素。队列有两个指针,分别指向队头(Front)和队尾(

    2024年02月16日
    浏览(31)
  • 数据结构:队列(Python语言实现)

    队列是一种 先进先出 的数据结构(特殊的线性结构),在队列 尾部 插入新元素,在队列 头部 删除元素。 一般队列的基本操作如下: create:创建空队列。 enqueue:将新元素加入队列的尾部,返回新队列。 dequeue:删除队列头部元素,返回新队列。 front:返回队列头部的元素

    2024年02月13日
    浏览(39)
  • C语言实现队列--数据结构

    😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️Take your time ! 😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️ 💥个人主页:🔥🔥🔥大魔王🔥🔥🔥 💥所属专栏:🔥魔王的修炼之路–数据结构🔥 如果你觉得这篇文章对你有帮助,请在文章结尾处留下你的 点赞 👍和 关注 💖,支持一

    2024年02月05日
    浏览(36)
  • 数据结构初阶(用C语言实现简单数据结构)--栈和队列

    ✨✨欢迎来到T_X_Parallel的博客!!       🛰️博客主页:T_X_Parallel       🛰️专栏 : 数据结构初阶       🛰️欢迎关注:👍点赞🙌收藏✍️留言 这小猫真好看 言归正传,通过上篇有关顺序表和链表的博客,可以了解到线性表的一些大致特征,这篇博

    2024年02月08日
    浏览(35)
  • 【数据结构】C语言实现链栈

    大家好,很高兴又和大家见面啦!!! 在上一篇内容中,我们简单介绍了一下如何解决顺序栈空间不够的方法: 在创建顺序栈前,提前在空间内容申请一篇足够大的空间; 创建一个动态的链栈; 当我们使用第一种方式时,如果我们此时需要创建的是两个同类型的顺序栈,那

    2024年01月23日
    浏览(32)
  • C语言实现链表--数据结构

    魔王的介绍:😶‍🌫️一名双非本科大一小白。 魔王的目标:🤯努力赶上周围卷王的脚步。 魔王的主页:🔥🔥🔥大魔王.🔥🔥🔥 ❤️‍🔥大魔王与你分享:很喜欢宫崎骏说的一句话:“不要轻易去依赖一个人,它会成为你的习惯当分别来临,你失去的不是某个人而是你精

    2024年02月02日
    浏览(33)
  • 数据结构链表(C语言实现)

            机遇对于有准备的头脑有特别的亲和力。本章将讲写到链表其中主要将写到单链表和带头双向循环链表的如何实现。    话不多说安全带系好,发车啦 (建议电脑观看) 。 附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗

    2024年02月10日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包