数据结构初阶:栈

本篇博客主要介绍栈的概念与结构等内容。

1.栈

1.1 概念与结构

栈:一种特殊的线性表 ,其只允许在固定的一端进行插入和删除元素 操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。 栈中的数据元素遵守后进先出LIFO(Last in First out)的原则。

**压栈:**栈的插入操作叫作进栈/压栈/入栈,入数据在栈顶。

出栈: 栈的删除操作叫作出栈。出数据也在栈顶。

栈底层结构选型

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较少。

1.2 栈的实现

Stack.h

复制代码
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>


//定义栈的结构
typedef int STDataType;
typedef struct Stack
{
	STDataType* arr;
	int top;      //指向栈顶的位置
	int capacity; //容量
}ST;

void STInit(ST* ps);
void STDestroy(ST* ps);


//入栈---栈顶
void StackPush(ST* ps, STDataType x);
//出栈---栈顶
void StackPop(ST* ps);
//取栈顶数据
STDataType StackTop(ST* ps);

bool StackEmpty(ST* ps);
//获取栈中有效元素个数
int STSize(ST* ps);
1.3 定义栈的结构
复制代码
//定义栈的结构
typedef int STDataType;
typedef struct Stack
{
	STDataType* arr;
	int top;      //指向栈顶的位置
	int capacity; //容量
}ST;

代码逻辑:

首先,通过typedef定义了一个整数类型STDataType ,这里实际上是将int类型取了一个别名STDataType。

然后,定义了一个结构体Stack,这个结构体包含了三个成员:

  • STDataType* arr:一个指向整数类型的指针,用于存储栈的元素。
  • int top:用于指向栈顶的位置。
  • int capacity:表示栈的容量。
1.4 栈的初始化
复制代码
void STInit(ST* ps)
{
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}

代码逻辑:

函数的参数是一个指向ST结构体的指针ps。在函数内部,将结构体中的成员进行了如下初始化:

  • ps->arr被初始化为NULL,表示栈的元素数组为空。
  • ps->top和ps->capacity都被初始化为0,分别表示栈顶位置和栈的容量为0。

这样,通过调用这个函数,可以将一个栈结构体初始化为一个空栈的状态。

1.5 栈的销毁
复制代码
void STDestroy(ST* ps)
{
	if (ps->arr)
		free(ps->arr);
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}

代码逻辑:

函数的参数是一个指向ST结构体的指针ps。在函数内部,进行了以下操作:

首先,检查ps->arr是否不为NULL。如果不为NULL,则使用free函数释放ps->arr所指向的内存空间,以避免内存泄漏。

然后,将ps->arr再次设置为NULL,并将ps->top和ps->capacity都设置为0,将栈结构体的相关成员恢复到初始状态。

这样,通过调用这个函数,可以释放栈所占用的内存资源,并将栈结构体的成员进行清理和重置。

1.6 入栈
复制代码
//入栈----栈顶
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		//空间不够---增容
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
	//空间足够
	ps->arr[ps->top++] = x;
}

代码逻辑:

用于实现向栈中入栈的操作。

函数的参数包括一个指向栈结构体的指针ps和一个要入栈的元素x。

在函数内部,首先使用assert函数检查ps是否有效 。然后,通过判断栈顶位置ps->top是否等于栈的容量ps->capacity来确定是否需要进行扩容操作。

如果需要扩容,会根据当前容量的情况计算新的容量(如果当前容量为0,则新容量为4;否则新容量为当前容量的2倍),然后使用realloc函数 对栈的元素数组进行扩容。如果扩容失败(tmp为NULL),则会输出错误信息并退出程序。

如果空间足够,直接将元素x放入栈顶位置(ps->arr[ps->top] = x),然后将栈顶位置加1(ps->top++)。

总的来说,这个函数实现了在栈空间不足时进行自动扩容,并将元素成功入栈的功能。

1.7 判空和出栈
复制代码
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

//出栈----栈顶
void StackPop(ST* ps)
{
	assert(!StackEmpty(ps));
	--ps->top;
}

代码逻辑:

  • bool StackEmpty(ST* ps): 这个函数用于判断栈是否为空。它首先使用assert函数检查ps是否有效,然后通过判断栈顶位置ps->top是否为0来确定栈是否为空。如果ps->top为0,则表示栈为空,函数返回true;否则,函数返回false。
  • void StackPop(ST* ps): 这个函数用于实现出栈操作。它首先使用assert函数和StackEmpty函数来检查栈是否为空,如果栈为空则会产生断言错误。如果栈不为空,那么将栈顶位置ps->top减1,实现出栈操作。
1.8 取栈顶数据
复制代码
//取栈顶数据
STDataType StackTop(ST* ps)
{
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
}
1.9 获取栈中数据有效个数
复制代码
//获取栈中有效元素个数
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

代码逻辑:

函数的参数是一个指向栈结构体的指针 ps 。在函数内部,首先使用 assert 函数检查 ps 是否有效。然后,直接返回栈顶位置 ps->top 的值,将其作为栈中有效元素的个数。因为栈顶位置的值就表示了栈中当前元素的数量。

2.源代码(Stack.c)

复制代码
#define _CRT_SECURE_NO_WARNINGS
#include"Stack.h"

void STInit(ST* ps)
{
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}
void STDestroy(ST* ps)
{
	if (ps->arr)
		free(ps->arr);
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}
//入栈----栈顶
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		//空间不够---增容
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
	//空间足够
	ps->arr[ps->top++] = x;
}


bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

//出栈----栈顶
void StackPop(ST* ps)
{
	assert(!StackEmpty(ps));
	--ps->top;
}
//取栈顶数据
STDataType StackTop(ST* ps)
{
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
}
//获取栈中有效元素个数
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

3.小结

以上便是本篇博客的所有内容,如果诸君学到知识的话,还请诸君点点赞,支持博主。

相关推荐
§ꦿCFོ༉9 小时前
嵌入式八股—C语言入门学习(一)
c语言·编程语言·嵌入式八股文
沐晓时光10 小时前
C语言入门,字符串和字符串函数知识讲解
c语言·开发语言
智者知已应修善业17 小时前
【51单片机实现从下到上,从上到下,从中间到两边,两边到中间】2024-10-23
c语言·经验分享·笔记·单片机·嵌入式硬件·51单片机
老师我太想进步了202620 小时前
【数据结构-3】算法美学之降复杂度
数据结构·算法
布莱克6051 天前
C/C++ 中变量的声明与定义:区别、联系与常见误区
c语言·开发语言·c++·声明·定义
揽星河..1 天前
【C语言】底层程序设计
c语言·开发语言
w_zero_one1 天前
算法--构造
java·数据结构·算法
揽星河..1 天前
【C语言】结构体
c语言·开发语言
唐青枫1 天前
C 语言 malloc() 详解与实战 Demo
c语言
lisw051 天前
互联网上的数据结构可视化!
数据结构·信息可视化