• 【数据结构】栈的实现


    (一)栈定义

    栈:是一种受限制的线性表,即只能在尾部进行插入、删除的线性表,而且是一种先进后出的数据结构。尾部这一端又叫做栈顶,另一端叫做栈底。

    入栈:向一个栈内插入元素叫做入栈或压栈,它把新元素放到栈顶元素的上面,是它成为新的栈顶元素。
    出栈:在栈内删除元素叫出栈或退站,即把栈顶元素删除掉,使其相邻的的元素成为新的栈顶元素。

    栈的实现一般用数组或链表实现,但数组结构实现更优,因为数组在尾部插入删除的代价小。
    如图:数组的入栈和出栈,满足后进先出
    在这里插入图片描述
    类似于枪的子弹夹,后进的去子弹先发射出来,前面的子弹才可以发射出来。

    (二)栈实现

    (1)创建结构体

    typedef int STDataType;// 动态栈
    typedef struct Stack
    {
    	STDataType* a;
    	int top;		// 栈顶	
    
    	int capacity;  // 容量 
    }Stack;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    typedef int STDataType为了方便改类型,栈结构需要创建三个成员变量,STDataType* a,方便增容用指针的形式,top表示栈顶,capacity表示栈容量。

    (2)具体函数实现及解析

    (1.1)初始化栈

    void StackInit(Stack* ps)// 初始化栈 
    {
    	ps->a = (STDataType*)malloc(sizeof(STDataType)*4);
    	ps->top = 0;
    	ps->capacity = 4;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    初始化先先开辟4个空间,方便增容,置栈顶为0,表示指向栈顶的下一个元素,而capacity置为4。

    (1.2)入栈

    void StackPush(Stack* ps, STDataType data)// 入栈 
    {
    	assert(ps);
    	if (ps->top == ps->capacity)
    	{
    		STDataType* tmp = (STDataType*)realloc(ps->a,ps->capacity*sizeof(STDataType)* 2);
    		if (tmp == NULL)
    		{
    			perror("realloc fail");
    			exit(-1);
    		}
    		ps ->a = tmp;
    		ps->capacity *= 2;
    	}
    	ps->a[ps->top] = data;
    	ps->top++;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    入栈先断言结构体指针不能为空,再判断是否要增容,如果top等于capacity就增,用realloc函数进行增容,增2倍,放到tmp指针变量里,判断tmp是否为空,不为空则把a指向tmp指针,并更新capacity。再把数据放到ps->top下标位置,并++使栈顶指向下一个元素。

    (1.3)出栈

    void StackPop(Stack* ps)// 出栈 
    {
    	assert(ps);
    	assert(!StackEmpty(ps));
    	ps->top--;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    出栈的情况直接top–,使栈顶位置往下走,需要两处重要的断言,一是ps不能为空,二是因为这里的栈是不能为空的,我们调用StackEmpty函数啊,如果为空返回真再取反,为假,则报错。

    (1.4)获取栈顶元素

    STDataType StackTop(Stack* ps)// 获取栈顶元素
    {
    	assert(ps);
    	assert(!StackEmpty(ps));
    	return ps->a[ps->top - 1];
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    因为ps->top指的是栈顶元素下一个位置,我们取栈顶元素时需要减一,同样需要两处断言,同上。

    (1.5)获取栈中有效元素个数

    int StackSize(Stack* ps)// 获取栈中有效元素个数 
    {
    	assert(ps);
    	return ps->top;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    返回个数,直接返回的是ps->top,因为这是数组是从0开始的,所以直接返回即可。

    (1.6)检测栈是否为空

    bool StackEmpty(Stack* ps)// 检测栈是否为空0 
    {
    	assert(ps);
    	return ps->top == 0;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    判断是否为空,先断言,直接返回表达式,如果等于0为空,返回true,反之返回false。

    (1.7)销毁栈

    void StackDestroy(Stack* ps)// 销毁栈 
    {
    	assert(ps);
    	free(ps->a);
    	ps->a = NULL;
    	ps->capacity = ps->top = 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    销毁栈,先释放指针a所指向的空间,再把它置为空指针,后两个变量皆置为0。

    (三)栈实现代码

    (1)Stack.c

    #include"Stack.h"
    void StackInit(Stack* ps)// 初始化栈 
    {
    	ps->a = (STDataType*)malloc(sizeof(STDataType)*4);
    	ps->top = 0;
    	ps->capacity = 4;
    }
    
    void StackPush(Stack* ps, STDataType data)// 入栈 
    {
    	assert(ps);
    	if (ps->top == ps->capacity)
    	{
    		STDataType* tmp = (STDataType*)realloc(ps->a,ps->capacity*sizeof(STDataType)* 2);
    		if (tmp == NULL)
    		{
    			perror("realloc fail");
    			exit(-1);
    		}
    		ps ->a = tmp;
    		ps->capacity *= 2;
    	}
    	ps->a[ps->top] = data;
    	ps->top++;
    }
    
    void StackPop(Stack* ps)// 出栈 
    {
    	assert(ps);
    	assert(!StackEmpty(ps));
    	ps->top--;
    }
    
    STDataType StackTop(Stack* ps)// 获取栈顶元素
    {
    	assert(ps);
    	assert(!StackEmpty(ps));
    	return ps->a[ps->top - 1];
    
    }
    
    int StackSize(Stack* ps)// 获取栈中有效元素个数 
    {
    	assert(ps);
    	return ps->top;
    }
    
    bool StackEmpty(Stack* ps)// 检测栈是否为空0 
    {
    	assert(ps);
    	return ps->top == 0;
    
    }
    
    void StackDestroy(Stack* ps)// 销毁栈 
    {
    	assert(ps);
    	free(ps->a);
    	ps->a = NULL;
    	ps->capacity = ps->top = 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    (2)Stack.h

    #pragma once
    #include
    #include
    #include
    #include
    
    typedef int STDataType;// 动态栈
    typedef struct Stack
    {
    	STDataType* a;
    	int top;		// 栈顶	
    
    	int capacity;  // 容量 
    }Stack;
    
    void StackInit(Stack* ps);// 初始化栈 
    
    void StackPush(Stack* ps, STDataType data);// 入栈 
    
    void StackPop(Stack* ps);// 出栈 
    
    STDataType StackTop(Stack* ps);// 获取栈顶元素 
    
    int StackSize(Stack* ps);// 获取栈中有效元素个数 
    
    bool StackEmpty(Stack* ps);// 检测栈是否为空
    
    void StackDestroy(Stack* ps);// 销毁栈 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    (3)test.c

    #include"Stack.h"
    void test1()
    {
    	Stack st;
    	StackInit(&st);
    	StackPush(&st, 1);
    	StackPush(&st, 2);
    	StackPush(&st, 3);
    	StackPush(&st, 4);
    	StackPush(&st, 5);
    	StackPush(&st, 6);
    
    
    	printf("size:%d\n", StackSize(&st)); 
    
    	StackPop(&st);
    	StackPop(&st);
    	StackPop(&st);
    	StackPop(&st);
    	StackPop(&st);
    	printf("%d\n", StackTop(&st));
    
    	StackDestroy(&st);
    
    }
    int main()
    {
    	
    	test1();
    	return 0;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    (四)栈结构测试结果

    在这里插入图片描述

  • 相关阅读:
    leetcode - 780. Reaching Points
    SpringMVC之国际化&上传&下载
    新浪微博一键删除所有内容
    机器人运动学笔记
    利用剪切干涉法的准直测量
    金仓数据库KingbaseES数据库参考手册(服务器配置参数9. 错误报告和日志)
    Java23种设计模式-行为型模式之命令模式
    十大排序——4.堆排序
    长安链GO语言智能合约编写与编译
    npm包、全局数据共享、分包
  • 原文地址:https://blog.csdn.net/m0_59292239/article/details/127772356