栈的实现详解

目录

[一. 栈的概念和结构](#一. 栈的概念和结构)

[二. 栈的实现方式](#二. 栈的实现方式)

1.链表实现栈

[2. 数组实现栈](#2. 数组实现栈)

[三. 栈各个功能实现](#三. 栈各个功能实现)

[1. 结构体的定义](#1. 结构体的定义)

[2. 栈的初始化](#2. 栈的初始化)

[3. 入栈操作](#3. 入栈操作)

[4. 出栈操作](#4. 出栈操作)

[5. 返回栈顶的值](#5. 返回栈顶的值)

[6. 销毁栈](#6. 销毁栈)

[7. 判断栈是否为空](#7. 判断栈是否为空)

[8. 返回栈有多少元素](#8. 返回栈有多少元素)

[四. 完整代码](#四. 完整代码)

[1. stack.h](#1. stack.h)

[2. stack.c](#2. stack.c)

[3. test.c](#3. test.c)


一. 栈的概念和结构

栈是一种特殊的线性表,只允许在固定的一端进行插入和删除元素。进入数据插入和删除操作的一端成为栈顶另一端称为栈底,栈中元素遵守后进先出或先进后出原则

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

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

二. 栈的实现方式

栈可以用链表实现也可以用数组实现

1.链表实现栈

如果用尾做栈顶,尾插尾删要设计成双向链表否则插入效率极低

如果用头做栈顶可以设计成单链表的方式

虽然不用扩容但是cpu命中率低

2. 数组实现栈

可以静态实现也可以动态实现

需要扩容,但是cpu命中率高


两种方式各有优劣,这里我们选择使用数组实现

三. 栈各个功能实现

1. 结构体的定义
cpp 复制代码
typedef int StackType;
typedef struct Stack
{
	StackType* a;//StackType是存储元素的类型
	int Top;
	int capacity;
}ST,*pS;

三个参数的含义:

a:指针,用来存储数据

Top:栈顶元素在a中的位置

capacity:a能容纳的元素个数

2. 栈的初始化
cpp 复制代码
void StackInit(pS pst)
{
	assert(pst);
	
	pst->a = NULL;
	pst->capacity = 0;
	pst->Top = 0;
}

此处pst->Top可以初始化为0也可以初始化为-1,代表栈顶元素在a中的位置或者代表栈顶元素在a中位置的下一个(两种写法对后面代码会产生影响)

3. 入栈操作
cpp 复制代码
void BuyNode(pS pst)
{

	int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
	StackType* tmp = (StackType*)realloc(pst->a, sizeof(StackType) * newcapacity );
	if (tmp == NULL)
	{
		perror("relloc fail");
		return;
	}
	pst->a = tmp;
	pst->capacity = newcapacity;
}

void StackPush(pS pst, StackType data)
{
	assert(pst);
	if (pst->Top == pst->capacity)
	{
		BuyNode(pst);
	}
	pst->a[pst->Top] = data;
	pst->Top++;
}

扩容时要看是容量(capacity)是0还是非0,非0就扩充2倍,0就赋值为4来开辟动态内存

如果上文Top初始化为-1,此处的pst->Top++要在赋值前

4. 出栈操作
cpp 复制代码
void StackPop(pS pst)
{
	assert(pst);

	pst->Top--;//数组里的值不用改,再添加数据会覆盖掉
}
5. 返回栈顶的值
cpp 复制代码
StackType StackTop(pS pst)
{
	assert(pst);

	return pst->a[pst->Top-1];
}

因为Top指向的是栈顶元素的下一个位置,所以要-1

6. 销毁栈
cpp 复制代码
void StackDestroy(pS pst)
{
	assert(pst);
	
	free(pst->a);
	pst->a = NULL;
	pst->capacity = 0;
	pst->Top = 0;
}
7. 判断栈是否为空
cpp 复制代码
bool StackEmpty(pS pst)
{
	assert(pst);
	return pst->Top == 0; 
}
8. 返回栈有多少元素
cpp 复制代码
int StackSize(pS pst)
{
	assert(pst);

	return pst->Top;
}

数组存储是有0这个下标的,所以直接返回Top,如果Top是指向栈顶元素那返回Top+1

四. 完整代码

1. stack.h
cpp 复制代码
#include<stdio.h>
#include<assert.h>
#include<stdbool.h>
#include<stdlib.h>
typedef int StackType;

typedef struct Stack
{
	StackType* a;
	int Top;
	int capacity;
}ST,*pS;
//初始化
void StackInit(pS pst);
//入栈
void StackPush(pS pst,StackType data);
//出栈
void StackPop(pS pst);
//取栈顶数据
StackType StackTop(pS pst);
//判空
bool StackEmpty(pS pst);
//获取数据个数
int StackSize(pS pst);

void StackDestroy(pS pst);
2. stack.c
cpp 复制代码
#include"stack.h"

//初始化
void StackInit(pS pst)
{
	assert(pst);
	
	pst->a = NULL;
	pst->capacity = 0;
	pst->Top = 0;
}

void BuyNode(pS pst)
{

	int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
	StackType* tmp = (StackType*)realloc(pst->a, sizeof(StackType) * newcapacity );
	if (tmp == NULL)
	{
		perror("relloc fail");
		return;
	}
	pst->a = tmp;
	pst->capacity = newcapacity;
}

void StackPush(pS pst, StackType data)
{
	assert(pst);
	if (pst->Top == pst->capacity)
	{
		BuyNode(pst);
	}
	pst->a[pst->Top] = data;
	pst->Top++;
}

void StackPop(pS pst)
{
	assert(pst);

	pst->Top--;//数组里的值不用改,再添加数据会覆盖掉
}

StackType StackTop(pS pst)
{
	assert(pst);

	return pst->a[pst->Top-1];
}

void StackDestroy(pS pst)
{
	assert(pst);
	
	free(pst->a);
	pst->a = NULL;
	pst->capacity = 0;
	pst->Top = 0;
}
bool StackEmpty(pS pst)
{
	assert(pst);
	return pst->Top == 0; 
}

int StackSize(pS pst)
{
	assert(pst);

	return pst->Top;
}
3. test.c
cpp 复制代码
#include"stack.h"


int main()
{
	ST s = { 0 };
	StackInit(&s);
	StackPush(&s, 2);
	StackPush(&s, 2);
	StackPush(&s, 3);
	StackPush(&s, 3);
	printf("%d\n", StackSize(&s));
	while(!StackEmpty(&s))
	{
		printf("%d\n", StackTop(&s));
		StackPop(&s);
	}
	StackDestroy(&s);
	return 0;
}

本篇文章到此结束希望可以帮到您(๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤

(づ ̄3 ̄)づ╭❤~ 再见啦~

相关推荐
<但凡.11 分钟前
题海拾贝:力扣 138.随机链表的复制
数据结构·算法·leetcode
장숙혜11 分钟前
JavaScript正则表达式解析:模式、方法与实战案例
开发语言·javascript·正则表达式
安大小万28 分钟前
C++ 学习:深入理解 Linux 系统中的冯诺依曼架构
linux·开发语言·c++
随心Coding32 分钟前
【零基础入门Go语言】错误处理:如何更优雅地处理程序异常和错误
开发语言·后端·golang
T.Ree.36 分钟前
C语言_自定义类型(结构体,枚举,联合)
c语言·开发语言
Channing Lewis38 分钟前
python生成随机字符串
服务器·开发语言·python
田梓燊42 分钟前
图论 八字码
c++·算法·图论
苦 涩1 小时前
考研408笔记之数据结构(六)——查找
数据结构
小熊科研路(同名GZH)1 小时前
【Matlab高端绘图SCI绘图模板】第002期 绘制面积图
开发语言·matlab