栈的实现详解

目录

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

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

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 ̄)づ╭❤~ 再见啦~

相关推荐
Dream_Snowar34 分钟前
速通Python 第三节
开发语言·python
唐诺44 分钟前
几种广泛使用的 C++ 编译器
c++·编译器
XH华1 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生1 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_1 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
高山我梦口香糖1 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
落魄君子2 小时前
GA-BP分类-遗传算法(Genetic Algorithm)和反向传播算法(Backpropagation)
算法·分类·数据挖掘
冷眼看人间恩怨2 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
菜鸡中的奋斗鸡→挣扎鸡2 小时前
滑动窗口 + 算法复习
数据结构·算法
信号处理学渣2 小时前
matlab画图,选择性显示legend标签
开发语言·matlab