数据结构——栈

大家好我是小锋,今天我们来学习一下栈,

栈的概念及结构

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

那么大家思考一个问题我们在压栈1,2,3,4,它出栈就是4,3,2,1,吗?
其实不一定我们可以边压栈边出栈它的顺序也可以是1,2,3,4,

栈的实现

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


这里我们用顺序表来实现栈

这里有两种版本的顺序表静态的实际应用不大,我们用动态的版本来实现链表。
我们再分装一个.h文件来存放头文件

初始化

cpp 复制代码
//初始化
void stackinit(stack* ps) {
	assert(ps);
	ps->val = NULL;
	ps->capacity = 0;
	ps->top = 0;
}

压栈

cpp 复制代码
//压栈
void stackpush(stack* ps,CMMlet a) {
	assert(ps);
	if (ps->capacity == ps->top) {
		int n = ps->val == NULL ? 4 : ps->capacity * 2;
		CMMlet* cur = (CMMlet*)realloc(ps->val, n * sizeof(CMMlet));
		if (cur == NULL) {
			printf("%s", strerror(errno));
			return;
		}
		ps->val = cur;
		ps->capacity = n;
	}
	ps->val[ps->top] = a;
	ps->top++;
}

这里的操作都是顺序表的常规操作了我就不细说了

出栈

cpp 复制代码
//出栈
void stackpop(stack* ps) {
	assert(ps);
	assert(stackEmpty(ps));
	ps->top--;
}

这里我们主要注意(栈为空时不能继续出栈了)

这里我们可以写一个函数来判断,

cpp 复制代码
//检测栈是否为空(空返回0,非空返回非0)
int stackEmpty(stack* ps) {
	assert(ps);
	return ps->top;

}

获取栈顶元素

cpp 复制代码
//获取栈顶元素
CMMlet stacktop(stack* ps) {
	assert(ps);
	assert(stackEmpty(ps));
	return ps->val[ps->top - 1];
}

获取栈中有效元素个数

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

销毁栈

cpp 复制代码
//销毁栈
void stackdestroy(stack* ps) {
	assert(ps);
	assert(!stackEmpty(ps));
	free(ps->val);
	ps->val = NULL;
}

我们写个函数来验证一下我们写的栈是否可以正常操作

先写个函数输出表中的数据(这违背了栈的概念所有不在栈的操作中只是为了方便测试)

cpp 复制代码
// 打印栈
void stackdy(stack* ps) {
	for (int i = 0; i < ps->top; i++) {
		printf("%d", ps->val[i]);
	}
	printf("\n");
}

//测试函数

void stackcs() {
	stack ps;
	//初始化
	stackinit(&ps);
	//压栈
	stackpush(&ps, 1);
	stackpush(&ps, 2);
	stackpush(&ps, 3);
	stackpush(&ps, 4);
	stackpush(&ps, 5);
	stackdy(&ps);
	//出栈
	stackpop(&ps);
	stackpop(&ps);
	stackdy(&ps);
	//获取栈顶
	CMMlet n=stacktop(&ps);
	printf("%d\n", n);
	//获取元素个数

	stacksize(&ps);
	//销毁栈
	stackdestroy(&ps);
}

int main() {
	stackcs();
	return 0;
}

下面就是本期的所有代码,大家可以自己尝试一下

test.h

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS
#pragma once

# include<stdio.h>
# include<stdlib.h>
# include<assert.h>
# include<string.h>
# include<errno.h>




#define N 10
typedef int CMMlet;
typedef struct stack stack;
静态版本
//struct stack {
//	int top;//栈顶
//	CMMlet val[N]
//};
//动态版本
struct stack {
	int top;//栈顶
	CMMlet* val;
	int capacity;//容量
};

//初始化
void stackinit(stack* ps);
//压栈
void stackpush(stack* ps, CMMlet a);
//出栈
void stackpop(stack* ps);
//获取栈顶元素
CMMlet stacktop(stack* ps);
//获取栈中有效元素个数
int stacksize(stack* ps);
//检测栈是否为空(空返回0,非空返回非0)
int stackEmpty(stack* ps);
//销毁栈
void stackdestroy(stack* ps);

test.c

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

//初始化
void stackinit(stack* ps) {
	assert(ps);
	ps->val = NULL;
	ps->capacity = 0;
	ps->top = 0;
}

//压栈
void stackpush(stack* ps,CMMlet a) {
	assert(ps);
	if (ps->capacity == ps->top) {
		int n = ps->val == NULL ? 4 : ps->capacity * 2;
		CMMlet* cur = (CMMlet*)realloc(ps->val, n * sizeof(CMMlet));
		if (cur == NULL) {
			printf("%s", strerror(errno));
			return;
		}
		ps->val = cur;
		ps->capacity = n;
	}
	ps->val[ps->top] = a;
	ps->top++;
}

//出栈
void stackpop(stack* ps) {
	assert(ps);
	assert(stackEmpty(ps));
	ps->top--;
}

//获取栈顶元素
CMMlet stacktop(stack* ps) {
	assert(ps);
	assert(stackEmpty(ps));
	return ps->val[ps->top - 1];
}

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

//检测栈是否为空(空返回0,非空返回非0)
int stackEmpty(stack* ps) {
	assert(ps);
	return ps->top;

}


//销毁栈
void stackdestroy(stack* ps) {
	assert(ps);
	free(ps->val);
	ps->val = NULL;
	ps->top = ps->capacity = 0;
}

cs.c

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



// 打印栈
void stackdy(stack* ps) {
	for (int i = 0; i < ps->top; i++) {
		printf("%d", ps->val[i]);
	}
	printf("\n");
}

//测试函数

void stackcs() {
	stack ps;
	//初始化
	stackinit(&ps);
	//压栈
	stackpush(&ps, 1);
	stackpush(&ps, 2);
	stackpush(&ps, 3);
	stackpush(&ps, 4);
	stackpush(&ps, 5);
	stackdy(&ps);
	//出栈
	stackpop(&ps);
	stackpop(&ps);
	stackdy(&ps);
	//获取栈顶
	CMMlet n = stacktop(&ps);
	printf("%d\n", n);
	//获取元素个数
	int a = stacksize(&ps);
	printf("%d\n", a);
	stackdy(&ps);
	//销毁栈
	stackdestroy(&ps);
}

int main() {
	stackcs();
	return 0;
}

以上就是全部内容了,如果有错误或者不足的地方欢迎大家给予建议。

相关推荐
m0_639906945 小时前
Redis入门|五种数据结构、使用场景、持久化RDB&AOF
数据结构·数据库·redis
ZhengEnCi6 小时前
Agent 架构怎么选:从单 Agent 到多 Agent 编排的选型决策指南
算法·架构
秋天的怀念_David7 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Pniubi7 小时前
力扣283移动零(双指针法)
算法·leetcode·职场和发展
hhb_6187 小时前
大模型落地三重优化实战
人工智能·算法·机器学习
云和数据.ChenGuang7 小时前
光哥说Python RAG 系统需要哪些评估指标:从检索到生成的全链路评测指南
网络·人工智能·python·算法·langchain
2601_970703839 小时前
工业除湿机租赁:把一份租金合同拆开看
大数据·数据结构·算法·数据库架构·推荐算法
心中有你02149 小时前
Java实现Dijkstra最短路径算法(邻接表 + 优先队列)
java·数据库·算法
ZhengEnCi10 小时前
同样的模型,为什么本地和云 API 差别那么大:量化精度、聊天模板与采样参数的三大元凶
人工智能·算法·llm
Zwawa10 小时前
串口为什么会丢字节:从轮询到中断和环形缓冲区
c语言·单片机·嵌入式