数据结构——栈

目录

前言

一、栈

二、栈的实现

[2.1 初始化栈](#2.1 初始化栈)

[2.2 入栈](#2.2 入栈)

[2.3 检测栈是否为空](#2.3 检测栈是否为空)

[2.3 出栈](#2.3 出栈)

[2.5 获取栈顶元素](#2.5 获取栈顶元素)

[2.6 获取栈中有效元素个数](#2.6 获取栈中有效元素个数)

[2.7 栈的销毁](#2.7 栈的销毁)

三、完整代码

总结


前言

前面,我们学习过了线性表中的顺序表和链表,今天我们来了解一下线性表的另外一种栈。

**栈是后进先出(LIFO)的数据结构。**这意味着最后一个进入栈的元素总是第一个出来的。栈的操作限制在栈顶进行,即只能从栈顶插入(入栈)和删除(出栈),这种特性使得栈符合后进先出的原则。


一、栈

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

二、栈的实现

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

我们通过数组来实现栈,就可以用定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈

主要接口:

cpp 复制代码
typedef int STDataType;

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

//栈的初始化
void StackInit(ST* ps);
//入栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
STDataType StackTop(ST* ps);
// 获取栈中有效元素个数
int StackSize(ST* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
bool StackEmpty(ST* ps);
//栈的销毁
void StackDestroy(ST* ps);

2.1 初始化栈

cpp 复制代码
//栈的初始化
void StackInit(ST* ps) {
	assert(ps);
	ps->a = NULL;
	ps->top = 0;//0为栈顶的下一个元素  -1为栈顶元素
	ps->capacity = 0;

}

我们初始化栈内元素为空,栈顶元素为和栈的容量为0。

2.2 入栈

cpp 复制代码
void StackPush(ST* ps, STDataType x)
{
	assert(ps);

	//扩容
	if (ps->top == ps->capacity) {
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* temp = (STDataType*)realloc(ps->a, newcapacity * sizeof(STDataType));
		if (temp == NULL)
		{
			perror("realloc fail");
		}
		ps->a = temp;
		ps->capacity = newcapacity;
	}

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

入栈操作相当于顺序表中的尾插操作,我们要先判断栈的大小是否足够,不够我们要先进行扩容操作,再先栈顶插入元素,插入的元素变成新的栈顶(即栈顶元素加1)。

2.3 检测栈是否为空

cpp 复制代码
bool StackEmpty(ST* ps) {
	
    assert(ps);
	return ps->top == 0;

}

如果链表为空,则栈顶为零对于零为真,返回ture,反之不为空返回false。

2.3 出栈

cpp 复制代码
//出栈
void StackPop(ST* ps) {
	assert(ps);
	assert(!StackEmpty(ps));//判空
	ps->top--;
}

如果出栈,只需要把栈顶减一,不需要进行删除操作。

2.5 获取栈顶元素

cpp 复制代码
//获取栈顶元素
STDataType StackTop(ST* ps) {

	assert(ps);
	assert(!StackEmpty(ps));//判空
	return ps->a[ps->top-1];

}

top初始化为0,即栈顶元素的下一个,所以减一即为栈顶元素。

2.6 获取栈中有效元素个数

cpp 复制代码
// 获取栈中有效元素个数
int StackSize(ST* ps) {
	assert(ps);
	return ps->top;

}

有效元素的个数就是栈顶,因为栈顶从零开始的。

2.7 栈的销毁

cpp 复制代码
void StackDestroy(ST* ps) {
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;

}

直接释放开辟的空间,同时栈的栈顶和容量都变为零。

三、完整代码

Stack.h

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

typedef int STDataType;

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

//栈的初始化
void StackInit(ST* ps);
//入栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
STDataType StackTop(ST* ps);
// 获取栈中有效元素个数
int StackSize(ST* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
bool StackEmpty(ST* ps);
//栈的销毁
void StackDestroy(ST* ps);

Stack.c

cpp 复制代码
#include"Stack.h"
//栈的初始化
void StackInit(ST* ps) {
	assert(ps);
	ps->a = NULL;
	ps->top = 0;//0为栈顶的下一个元素  -1为栈顶元素
	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* temp = (STDataType*)realloc(ps->a, newcapacity * sizeof(STDataType));
		if (temp == NULL)
		{
			perror("realloc fail");
		}
		ps->a = temp;
		ps->capacity = newcapacity;
	}

	//入栈
	ps->a[ps->top] = x;
	ps->top++;
}
//出栈
void StackPop(ST* ps) {
	assert(ps);
	assert(!StackEmpty(ps));
	ps->top--;
}
//获取栈顶元素
STDataType StackTop(ST* ps) {

	assert(ps);
	assert(!StackEmpty(ps));
	return ps->a[ps->top-1];

}
// 获取栈中有效元素个数
int StackSize(ST* ps) {
	assert(ps);
	return ps->top;

}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
bool StackEmpty(ST* ps) {
	
	assert(ps);
	return ps->top == 0;

}
//栈的销毁
void StackDestroy(ST* ps) {
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;

}

test.c

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

int main() {
	ST s;
	StackInit(&s);
	StackPush(&s, 1);
	StackPush(&s, 2);
	StackPush(&s, 3);

	StackPop(&s);
	int top = StackTop(&s);
	printf("%d ", top);

	StackPush(&s, 4);
	StackPush(&s, 5);

	while(!StackEmpty(&s))
	{
		int top = StackTop(&s);
		printf("%d ", top);
		StackPop(&s);
	}



	StackDestroy(&s);

}

总结

上述文章,我们讲了线性表中的栈的概念和具体实现,希望对你有所帮助。

相关推荐
Darling噜啦啦5 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
小小工匠6 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
玖玥拾6 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
Qres8216 天前
算法复键——树状数组
数据结构·算法
牛油果子哥q7 天前
并查集(DSU)超精讲,路径压缩、按秩合并、万能模板、连通性判定、最小生成树与刷题实战全解
数据结构·c++·最小生成树·并查集
凌波粒7 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
WL学习笔记7 天前
单项不带头不循环链表
数据结构·链表
小糯米6017 天前
JS 数组
数据结构·算法·排序算法
小欣加油7 天前
leetcode3612 用特殊操作处理字符串I
数据结构·c++·算法·leetcode·职场和发展
凌波粒7 天前
LeetCode--90.子集II(回溯算法)
数据结构·算法·leetcode