数据结构之栈详解

1. 栈的概念以及结构

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

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

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

总:

**栈顶(top):**线性表允许进行插入删除的那一端

**栈底(bottom):**固定的,不允许进行插入和删除的另一端

**空栈:**不含任何元素的空表

2.栈的功能以及实现

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

这里定长的静态栈的结构,实现中一般不实用

cpp 复制代码
//静态栈
typedef int STDataType;

#define N 10
typedef struct Stack
{
    STDataType a[N];
    int top;
}Stack; 

所以我们主要实现下面的支持动态增长的栈

cpp 复制代码
//支持动态增长的栈
typedef int STDataType;

typedef struct Stack
{
    STDataType* a; 
    int top;         //栈顶
    int capacity;    //容量
}Stack;

栈所需要实现的一些功能

cpp 复制代码
//栈初始化
void STInit(ST* ps);
//清空栈
void STDestroy(ST* ps);

//插入栈
void STPush(ST* ps);
//删除栈元素
void STPop(ST* ps);
//查看栈的大小
int STSize(ST* ps);
//查看栈中有没有元素
bool STEmpty(ST* ps);
//输出栈顶元素
STDataType STTop(ST* ps);

->1. 栈初始化

cpp 复制代码
void STInit(ST* ps)
{
	assert(ps);

	ps->a = (ST*)malloc(sizeof(ST) * CAPACITY__SIZE);
	if (NULL == ps->a)
	{
		perror("STInit::malloc");
		return;
	}

	//压栈元素的下一个位置
	ps->top = 0;
	ps->capacity = CAPACITY__SIZE;
}

->2. 清空栈

cpp 复制代码
//清空栈
void STDestroy(ST* ps)
{
	free(ps->a);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

->3. 插入栈

cpp 复制代码
//插入栈
void STPush(ST* ps, STDataType x)
{
	assert(ps);

	if (ps->top == ps->capacity)
	{
		ST* Expand = (ST*)realloc(ps->a,sizeof(ST) * ps->capacity * CAPACITY__SIZE);
		if (NULL == Expand)
		{
			perror("STPop::malloc");
			exit(-1);
		}

		ps->a = Expand;
		ps->capacity *= CAPACITY__SIZE;
	}

	ps->a[ps->top++] = x;
}

->4. 删除栈元素

cpp 复制代码
//删除栈元素
void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty);

	ps->top--;
}

->5. 查看栈的大小

cpp 复制代码
//查看栈的大小
int STSize(ST* ps)
{
	return ps->top;
}

->6. 查看栈中有没有元素

cpp 复制代码
//查看栈中有没有元素
bool STEmpty(ST* ps)
{
	return  ps->top == 0;
}

->7.输出栈顶元素

cpp 复制代码
//输出栈顶元素
STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty);

	return ps->a[ps->top - 1];
}

整合以上我们来实现栈,下面是实现栈的完整代码

Stack.h

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

//动态栈
#define CAPACITY__SIZE 4
typedef int STDataType;

typedef struct Stack
{
	int* a;
	int top;
	int capacity;
}ST;

//栈初始化
void STInit(ST* ps);
//清空栈
void STDestroy(ST* ps);

//插入栈
void STPush(ST* ps, STDataType x);
//删除栈元素
void STPop(ST* ps);
//查看栈的大小
int STSize(ST* ps);
//查看栈中有没有元素
bool STEmpty(ST* ps);
//输出栈顶元素
STDataType STTop(ST* ps);

Stack.c

cpp 复制代码
#include "Stack.h"

void STInit(ST* ps)
{
	assert(ps);
	ps->a = (STDataType*)malloc(sizeof(STDataType) * CAPACITY__SIZE);
	if (NULL == ps->a)
	{
		perror("STInit::malloc");
		return;
	}

	//压栈元素的下一个位置
	ps->top = 0;
	ps->capacity = CAPACITY__SIZE;
}

//清空栈
void STDestroy(ST* ps)
{
	free(ps->a);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

//插入栈
void STPush(ST* ps, STDataType x)
{
	assert(ps);

	if (ps->top == ps->capacity)
	{
		STDataType* Expand = (STDataType*)realloc(ps->a,sizeof(STDataType) * ps->capacity * CAPACITY__SIZE);
		if (NULL == Expand)
		{
			perror("STPop::malloc");
			exit(-1);
		}

		ps->a = Expand;
		ps->capacity *= CAPACITY__SIZE;
	}

	ps->a[ps->top++] = x;
}

//删除栈元素
void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));

	ps->top--;
}
//查看栈的大小
int STSize(ST* ps)
{
	return ps->top;
}

//查看栈中有没有元素
bool STEmpty(ST* ps)
{
	return  ps->top == 0;
}

//输出栈顶元素
STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));

	return ps->a[ps->top - 1];
}

test.c

cpp 复制代码
#include "Stack.h"

int main()
{
	ST Stack;
	STInit(&Stack);
	STPush(&Stack, 1);
	STPush(&Stack, 2);
	STPush(&Stack, 3);
	STPush(&Stack, 4);
	STPush(&Stack, 5);
	/*while (!STEmpty(&Stack))
	{
		printf("%d->", Stack.a[--Stack.top]);

	}
	printf("NULL\n");*/
	while (!STEmpty(&Stack))
	{
		printf("%d ", STTop(&Stack));
		STPop(&Stack);
	}
	printf("\n");
	STDestroy(&Stack);

	return 0;
}

测试结果:

相关推荐
小刘在重生~1 小时前
Java 集合|Collection、List、ArrayList、LinkedList、泛型、Collections 工具类
java·数据结构·list
我不会起名字3221 小时前
一天一道算法题(29):单调栈
java·数据结构·python·算法·leetcode·golang·单调栈
苦瓜小生1 小时前
【前端】【力扣与手撕】十天带你刷完前端算法与手撕,全是最简单好记的最优解法!day4
前端·数据结构·算法·leetcode·面试
少司府3 小时前
C++进阶:智能指针
开发语言·数据结构·c++·b树·算法·c·智能指针
LuminousCPP4 小时前
数据结构-排序(一):基础排序算法横向对比|冒泡、插入、希尔、堆与双向选择,详解二分 / Knuth 增量
c语言·数据结构·笔记·算法·排序算法
青山木4 小时前
Hot 100 --- 买卖股票的最佳时机
java·数据结构·算法·leetcode·贪心算法
csdn_aspnet5 小时前
C++ 未排序数组中第 k 个最小/最大元素 | 最坏情况下的线性时间
数据结构·c++·算法
aqiu11111115 小时前
【LeetCode 902】最大为 N 的数字组合 - 详细题解与数位组合思路
数据结构·算法·leetcode·蓝桥杯·数位dp
2601_9622974819 小时前
在python3中、下列输出变量a的正确写法是_2020超星大数据Python免费答案
数据结构·python·算法·编程·字符串操作
shehuiyuelaiyuehao20 小时前
算法29,前缀和,除自身以外的数组的乘积
java·数据结构·算法