数据结构初级(C语言版):栈 ,什么是栈?如何用C语言实现栈?

本文介绍了栈的基本概念,即栈是一种后进先出(LIFO)的数据结构,常用于编程中的临时存储和处理。通过C语言详细展示了如何使用顺序表来实现栈,包括初始化、销毁、压栈、弹栈、判断栈空、获取栈顶元素和计算栈内元素个数等操作。同时,提供了完整的顺序栈源码实现及VS2022环境下的测试示例。
摘要由CSDN通过智能技术生成

数据结构初级:栈 ,什么是栈?如何用C语言实现栈?

1. 什么是栈?

栈:栈是一种数据结构,是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素的操作,进行数据插入和删除操作的一端被称为栈顶,另一端被成为栈底.栈中的元素遵循先进后出LIFO(Last In First Out)的原则.
我们可以把栈简单的想象成一个桶(因为想要把东西放入桶中或者从桶里拿走东西只能通过桶口),从桶的顶端放入东西则是入栈,从顶端拿走东西则是出栈.
网络转载图片,侵删
并且,我们一般将给栈顶插入一个元素这个动作称为压栈(Push),将删除栈顶元素这个动作成为弹栈(Pop).

2. 栈的代码实现剖析

当我们想创建一个栈的时候,一般有两种数据结构可以选择,一个是顺序表(类似数组),另一个则是链表(有后继在内存中不连续存储的数据结构).根据我们上面所讲的栈的定义,用顺序表来实现可以说是非常方便了,因为顺序表的特殊性,它的内存在计算机中是连续存储的,并且在不改变位置的情况下,在顺序表的表尾插入和删除数据是相对来说比较方便的.

因此,下面以顺序表为基础来实现是个完整的栈.

首先我们需要分析,当我们需要用顺序表来实现栈的时候,应该用第一个放入元素的位置来当栈底,最后一个元素放入的位置来当栈顶方便插入和删除元素:
在这里插入图片描述
那么,我们首先要创建一个结构体,结构体中有 a: 顺序栈(用顺序表来实现的栈一般称为顺序栈), top:栈顶元素的下一个位置, capacity: 栈的空间大小

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;		//这里的top指向的是栈顶元素的下一个位置,当栈内为空时则为0
	int capacity;
}Stack;

2.1 初始化栈

然后我们初始化一下顺序栈,因为栈内还没有任何元素,因此栈的头指针先置空为NULL;
top因为还没有任何元素,因此top指向0;
而capacity也是因为还没有任何元素也没有开辟空间,因此也是0;

//栈的初始化
void StackInit(Stack* ps)
{
	assert(ps);  //因为传进来的是结构体的指针,因此不能为NULL
	ps->a = NULL;
	ps->top = 0;		//这里的top指向的是栈顶元素的下一个位置,当栈内为空时则为0
	ps->capacity = 0;	//初始内存为0
}

2.2 栈的销毁

初始化完成后一定要销毁栈,将所申请的空间还给操作系统

//栈的销毁
void StackDestroy(Stack* ps)
{
	assert(ps); //断言

	free(ps->a);
	ps->a = NULL;	//置空防止野指针
	ps->capacity = 0;	//销毁后为0
	ps->top = 0;	//销毁后为0
}

2.3 压栈(Push)

从栈顶插入一个元素到栈中

//入栈(从栈顶插入一个元素到栈中)
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	//首先要判断一下栈中是否已满,若已满,则要扩容
	if (ps->top == ps->capacity)
	{
		//若栈本身就是空栈,则先申请一部分内存,若非空且满了,则扩容到原来内存大小的两倍
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		//申请内存,先创建一个临时数组,直接用realloc来扩容
		STDataType* tmpa = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
		if (tmpa == NULL)
		{
			perror("realloc false");
			return;
		}
		ps->a = tmpa;
		ps->a[ps->top ] = data;
		ps->capacity = newCapacity;
	}
	else
	{
		//若栈中没满,则直接赋值
		ps->a[ps->top] = data;
	}
	//赋值完成后栈中元素+1,则top向后走一位
	ps->top++;
}

2.4 判断栈中是否为空

判断栈中是否为空,若为空则返回true,不为空则返回false

//判断栈中是否为空,若为空则返回true,不为空则返回false
bool StackEmpty(Stack* ps)
{
	assert(ps);

	return ps->top == 0;
}

2.5 获取栈顶的元素

注意:top指向的是栈顶元素的下一个位置,因此栈顶元素的位置应该在top-1处

//获取栈顶的元素
STDataType StackTop(Stack* ps)
{
	assert(ps);
	//若栈内为空,则无法获取
	assert(!StackEmpty(ps));

	//top指向的是栈顶元素的下一个位置,因此栈顶元素的位置应该在top-1处
	return ps->a[ps->top - 1];
}

2.6 弹栈(Pop)

删除栈顶的元素

//弹栈(删除栈顶的元素)
void StackPop(Stack* ps)
{
	assert(ps);
	//若栈中为空则无法删除
	assert(!StackEmpty(ps));

	ps->top--;
}

2.7 获取栈内有效元素个数

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

	return ps->top;
}

3. 顺序栈的源码(环境:vs2022)

Stack.h

#pragma once

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


typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;		
	int capacity;
}Stack;

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

//栈的销毁
void StackDestroy(Stack* ps);

//入栈(从栈顶插入一个元素到栈中)
void StackPush(Stack* ps, STDataType data);

//判断栈中是否为空,若为空则返回true,不为空则返回false
bool StackEmpty(Stack* ps);

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

//弹栈(删除栈顶的元素)
void StackPop(Stack* ps);

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

Stack.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"Stack.h"

//栈的初始化
void StackInit(Stack* ps)
{
	assert(ps);  //因为传进来的是结构体的指针,因此不能为NULL
	ps->a = NULL;
	ps->top = 0;		//这里的top指向的是栈顶元素的下一个位置,当栈内为空时则为0
	ps->capacity = 0;	//初始内存为0
}


//栈的销毁
void StackDestroy(Stack* ps)
{
	assert(ps); //断言

	free(ps->a);
	ps->a = NULL;	//置空防止野指针
	ps->capacity = 0;	//销毁后为0
	ps->top = 0;	//销毁后为0
}

//入栈(从栈顶插入一个元素到栈中)
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	//首先要判断一下栈中是否已满,若已满,则要扩容
	if (ps->top == ps->capacity)
	{
		//若栈本身就是空栈,则先申请一部分内存,若非空且满了,则扩容到原来内存大小的两倍
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		//申请内存,先创建一个临时数组,直接用realloc来扩容
		STDataType* tmpa = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
		if (tmpa == NULL)
		{
			perror("realloc false");
			return;
		}
		ps->a = tmpa;
		ps->a[ps->top ] = data;
		ps->capacity = newCapacity;
	}
	else
	{
		//若栈中没满,则直接赋值
		ps->a[ps->top] = data;
	}
	//赋值完成后栈中元素+1,则top向后走一位
	ps->top++;
}

//判断栈中是否为空,若为空则返回true,不为空则返回false
bool StackEmpty(Stack* ps)
{
	assert(ps);

	return ps->top == 0;
}

//获取栈顶的元素
STDataType StackTop(Stack* ps)
{
	assert(ps);
	//若栈内为空,则无法获取
	assert(!StackEmpty(ps));

	//top指向的是栈顶元素的下一个位置,因此栈顶元素的位置应该在top-1处
	return ps->a[ps->top - 1];
}


//弹栈(删除栈顶的元素)
void StackPop(Stack* ps)
{
	assert(ps);
	//若栈中为空则无法删除
	assert(!StackEmpty(ps));

	ps->top--;
}

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

	return ps->top;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"Stack.h"

void test0()
{
    //定义一个栈
    Stack st;
    StackInit(&st);
    printf("此时栈内有%d个元素\n", StackSize(&st));
    //分别插入 1,2,3,4,5
    printf("分别插入 1,2,3,4,5\n");
    StackPush(&st, 1);
    StackPush(&st, 2);
    StackPush(&st, 3);
    StackPush(&st, 4);
    StackPush(&st, 5);
    //获取栈顶元素,打印后将之弹出
    printf("获取栈顶元素,打印后将之弹出\n");
    int i = 5;
    while (i--)
    {
        printf("%d ", StackTop(&st));
        StackPop(&st);
    }
    printf("\n");
    printf("此时栈内有%d个元素\n", StackSize(&st));
}



int main()
{
    test0();


    return 0;
}

4. 运行结果

在这里插入图片描述
完结撒花❀❀❀~

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值