数据结构——栈(C语言)

github代码下载

github代码:
https://github.com/Kyrie-leon/Data_Structures/tree/main/stack_queue

一、 栈的概念及结构

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

二、栈的实现

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

在这里插入图片描述
在这里插入图片描述

而如果采用如下结构实现栈,尾插需要挪动数据,造成大量的计算开销。

在这里插入图片描述

2.1 栈的存储定义

静态存储的栈
使用一个静态一维数组a[N]实现,但这样做会造成太多的空间浪费或者空间不足

#define N 10
typedef int STDataType;
typedef struct Stack Stack;
struct Stack
{
    
    
	STDataType a[N];
	int _top;	//栈顶
};

支持动态增长的栈
使用一个指针_a动态开辟内存实现栈的存储

typedef int STDataType;
typedef struct Stack Stack;
//支持动态增长的栈
struct Stack
{
    
    
	STDataType * _a;
	int _top;			//栈顶
	int _capacity;		//容量
};

2.2 栈的初始化

初始化:默认为栈开辟四个STDataType大小的空间

  • capacity:栈的容量大小,默认4
  • _top: 表示栈顶,我们约定_top=0表示栈为空,之后每入栈一个元素_top加1,即_top所指向数组的下表总是比实际栈顶元素下标大1

在这里插入图片描述

在这里插入图片描述

//栈的初始化
void StackInit(Stack * ps)
{
    
    
	assert(ps);
	ps->_a = (STDataType *)malloc(sizeof(Stack) * 4);	//默认数组大小为4
	ps->_top = 0;		//栈为空,则栈顶为0
	ps->_capacity = 4;	//默认栈的容量为4
}

2.3 入栈

前面已经约定过_top所指向数组的下表总是比实际栈顶元素下标大1
入栈只需要将数据存放到_top下标的数组中,然后_top加1即可
在这里插入图片描述
在这里插入图片描述

//入栈
void StackPush(Stack * ps, STDataType data)
{
    
    
	assert(ps);
	//判断栈是否满了,满了则增容
	if (ps->_top == ps->_capacity)
	{
    
    
		ps->_capacity *= 2;	//每次扩容2倍
		STDataType * tmp = (STDataType *)realloc(ps->_a, sizeof(Stack)*ps->_capacity);
		//判断内存是否申请成功
		if (NULL == tmp)
		{
    
    
			printf("扩容失败\n");
			exit(-1);
		}
		ps->_a = tmp;
	}
	//入栈
	ps->_a[ps->_top] = data;	
	ps->_top++;
}

2.4 出栈

_top所指向数组的下表总是比实际栈顶元素下标大1
因此出栈只需将_top减1即可

在这里插入图片描述

//出栈
void StackPop(Stack * ps)
{
    
    
	assert(ps);
	assert(ps->_top>0);
	ps->_top--;
}

2.5 获取栈顶元素

_top所指向数组的下表总是比实际栈顶元素下标大1
所以栈顶元素的下标是_top-1

//获取栈顶元素
STDataType StackTop(Stack *ps)
{
    
    
	assert(ps);
	assert(ps->_top>0);

	return ps->_a[ps->_top-1];	
}

2.6 获取栈中有效元素个数

因为数组元素下标从0开始,因此_top就表示栈中有效元素个数


//获取栈中有效元素个数
int StackSize(Stack * ps)
{
    
    
	assert(ps);
	return ps->_top;
}

2.7 检测栈是否为空

通过_top的值就可以判断栈是否为空
若_top为0,表示为空,取反则返回非0
若_top为1,表示不为空,取反则返回0

//检测栈是否为空,如果为空返回非0,不为空返回0
int StackEmpty(Stack* ps)
{
    
    
	assert(ps);
	return !(ps->_top);
}

2.8 销毁栈


//销毁栈
void StackDestory(Stack * ps)
{
    
    
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_capacity = ps->_top = 0;
}

三、栈的测试

#include "stack.h"

void TestStack()
{
    
    
	Stack ps;
	StackInit(&ps);
	StackPush(&ps, 1);
	StackPush(&ps, 2);
	StackPush(&ps, 3);
	StackPush(&ps, 4);
	StackPush(&ps, 5);
	while (!StackEmpty(&ps))
	{
    
    

		printf("%d, %d\n", StackTop(&ps),StackSize(&ps));
		StackPop(&ps);
	}

	
}

int main()
{
    
    
	TestStack();
	system("pause");
	return 0;
}

在这里插入图片描述

四、代码清单

4.1 stack.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<windows.h>

#define N 10
typedef int STDataType;
typedef struct Stack Stack;
//struct Stack
//{
    
    
//	STDataType a[N];
//	int _top;	//栈顶
//};

//支持动态增长的栈
struct Stack
{
    
    
	STDataType * _a;
	int _top;			//栈顶
	int _capacity;		//容量
};

//初始化栈
void StackInit(Stack * ps);

//入栈
void StackPush(Stack * ps, STDataType data);

//出栈
void StackPop(Stack * ps);

//获取栈顶元素
STDataType StackTop(Stack *ps);

//获取栈顶中有效元素个数
int StackSize(Stack * ps);

//检测栈是否为空,如果为空返回非0,不为空返回0
int StackEmpty(Stack* ps);

//销毁栈
void StackDestory(Stack * ps);

4.2 stack.c

#include "stack.h"

//栈的初始化
void StackInit(Stack * ps)
{
    
    
	assert(ps);
	ps->_a = (STDataType *)malloc(sizeof(Stack) * 4);	//默认数组大小为4
	ps->_top = 0;		//栈为空,则栈顶为0
	ps->_capacity = 4;	//默认栈的容量为4
}

//入栈
void StackPush(Stack * ps, STDataType data)
{
    
    
	assert(ps);
	//判断栈是否满了,满了则增容
	if (ps->_top == ps->_capacity)
	{
    
    
		ps->_capacity *= 2;	//每次扩容2倍
		STDataType * tmp = (STDataType *)realloc(ps->_a, sizeof(Stack)*ps->_capacity);
		//判断内存是否申请成功
		if (NULL == tmp)
		{
    
    
			printf("扩容失败\n");
			exit(-1);
		}
		ps->_a = tmp;
	}
	//入栈
	ps->_a[ps->_top] = data;	
	ps->_top++;
}

//出栈
void StackPop(Stack * ps)
{
    
    
	assert(ps);
	assert(ps->_top>0);
	ps->_top--;
}

//获取栈顶元素
STDataType StackTop(Stack *ps)
{
    
    
	assert(ps);
	assert(ps->_top>0);

	return ps->_a[ps->_top-1];	
}

//获取栈中有效元素个数
int StackSize(Stack * ps)
{
    
    
	assert(ps);
	return ps->_top;
}

//检测栈是否为空,如果为空返回非0,不为空返回0
int StackEmpty(Stack* ps)
{
    
    
	assert(ps);
	return !(ps->_top);
}

//销毁栈
void StackDestory(Stack * ps)
{
    
    
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_capacity = ps->_top = 0;
}

4.3 test.c

#include "stack.h"

void TestStack()
{
    
    
	Stack ps;
	StackInit(&ps);
	StackPush(&ps, 1);
	StackPush(&ps, 2);
	StackPush(&ps, 3);
	StackPush(&ps, 4);
	StackPush(&ps, 5);
	while (!StackEmpty(&ps))
	{
    
    

		printf("%d, %d\n", StackTop(&ps),StackSize(&ps));
		StackPop(&ps);
	}

	
}

int main()
{
    
    
	TestStack();
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40076022/article/details/112282137
今日推荐