数据结构——栈

一、栈的概念

栈是一种特殊的线性表,只允许在栈的一端入数据和出数据,这一端称为栈顶,另一端称为栈底。

入数据时称为入栈或进栈或压栈,出数据时(删除数据)称为出栈。

在进出数据时,需要遵照先进后出,后进先出的规则。

比如
在这里插入图片描述
出栈顺序是5,4,3,2,1。但不一定就是5,4,3,2,1。
比如入一个数据就出一个数据,那么出栈顺序就变成了1,2,3,4,5。

二、实现栈

实现一个栈可以用数组也可以用链表,使用数组时,在数组尾插入数据,消耗小。因此选择使用数组实现栈,实现队列时会使用链表。

栈的结构体

typedef int STDataType; //方便对数据类型进行修改

typedef struct StackNode
{
	STDataType* arr;   //数组
	int capacity;      //最大容量
	int top;           //栈顶数据的下一个位置

}STNode;

栈的一些操作包括入栈,出栈,获取栈顶元素,获取栈的大小,判空,初始化和销毁等。

1、初始化和销毁

在初始化时,top的值可以为-1或者0,如果是-1,说明top位置处是栈顶。
如果是0,说明top位置处是栈顶位置的下一个。对于top初始化的不同,其他的接口的代码实现也不同,这里选择初始化为0;
在这里插入图片描述

//初始化顺序栈
void StackInit(STNode* ps)
{
	assert(ps);

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

2、入栈

入栈非常简单,因为top是指向栈顶位置的下一个,那么入栈就是将数据放在top处,在++top即可。

//入栈
void StackPush(STNode* ps, STDataType x)
{
	assert(ps);
	//没有空间或者空间满了,先扩容
	if (ps->capacity == ps->top)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->arr,sizeof(STNode) * newcapacity);
		if (tmp == NULL)
		{
			perror("malloc()");
			return;
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
	//插入数据
	ps->arr[ps->top++] = x;

}

其中由于使用的是数组,可能存在空间不够的情况,因此需要判断是否需要扩容。

3、出栈

出栈就是删除栈顶元素,让我们不能当前栈顶,那么修改top就可以做到

//出栈
void StackPop(STNode* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->top--;
}

4、获得栈顶数据

top是指向栈顶数据的下一个,那么–top后top位置处就是栈顶数据。

//获得栈顶元素
int FindTop(STNode* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
}

获得栈顶元素前提是栈内需要有数据。

5、判空

判空只需要判断top是否等于-1或者0,那么代码也是很简单。

//判断栈空
bool StackEmpty(STNode* ps)
{
	return ps->top == 0;
}

返回这个表达式的真假即可。4

6、获得栈的大小

因为我们在结构体内定义了capacity这个成员,因此这个接口也很容易实现

//获得栈的大小
int StackSize(STNode* ps)
{
	assert(ps);
	return ps->capacity;
}

三、完整代码

依旧是使用多个文件编写。

stack.h

#pragma once
#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.h>
typedef int STDataType;

typedef struct StackNode
{
	STDataType* arr;   //数组
	int capacity;      //最大容量
	int top;           //栈顶数据的下一个位置

}STNode;

//初始化
void StackInit(STNode* ps);
//销毁
void StackDestroy(STNode* ps);
//入栈
void StackPush(STNode* ps, STDataType x);
//出栈
void StackPop(STNode* ps);
//判断栈空
bool StackEmpty(STNode* ps);
//获得栈顶元素
int FindTop(STNode* ps);
//栈的大小
int StackSize(STNode* ps);

stack.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"stack.h"


//初始化顺序栈
void StackInit(STNode* ps)
{
	assert(ps);

	ps->arr = NULL;
	ps->capacity = 0;
	ps->top = 0;
}
//销毁栈
void StackDestroy(STNode* ps)
{
	assert(ps);
	free(ps->arr);
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}
//入栈
void StackPush(STNode* ps, STDataType x)
{
	assert(ps);
	//没有空间或者空间满了,先扩容
	if (ps->capacity == ps->top)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->arr,sizeof(STNode) * newcapacity);
		if (tmp == NULL)
		{
			perror("malloc()");
			return;
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
	//插入数据
	ps->arr[ps->top++] = x;

}
//出栈
void StackPop(STNode* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->top--;
}
//判断栈空
bool StackEmpty(STNode* ps)
{
	return ps->top == 0;
}
//获得栈顶元素
int FindTop(STNode* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
}
//获得栈的大小
int StackSize(STNode* ps)
{
	assert(ps);
	return ps->capacity;
}

关于栈的介绍就到这里了 ,下篇会使用链表实现一个队列。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值