数据结构——栈

目录

前言

一、栈

二、栈的实现

[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);

}

总结

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

相关推荐
ALISHENGYA4 分钟前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
DARLING Zero two♡30 分钟前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
波音彬要多做2 小时前
41 stack类与queue类
开发语言·数据结构·c++·学习·算法
Noah_aa2 小时前
代码随想录算法训练营第五十六天 | 图 | 拓扑排序(BFS)
数据结构
KpLn_HJL3 小时前
leetcode - 2139. Minimum Moves to Reach Target Score
java·数据结构·leetcode
AC使者9 小时前
5820 丰富的周日生活
数据结构·算法
无 证明9 小时前
new 分配空间;引用
数据结构·c++
别NULL13 小时前
机试题——疯长的草
数据结构·c++·算法
ZSYP-S15 小时前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring