• 【数据结构】栈的顺序表实现


    在这里插入图片描述每一个不曾起舞的日子,都是对生命的辜负。

    1. 栈的概念及结构

    1.1 概念

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

    即:是仅限在表尾进行插入删除线性表

    • 压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

    • 出栈:栈的删除操作叫做出栈。出数据也在栈顶。

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

    1.2 栈顶

    是一个线性表,我们把允许插入和删除的一段称为栈顶

    img

    1.3 栈底

    栈顶相对,另一端称为栈底,实际上,栈底的元素我们不需要关心。

    2. 接口

    2.1 可写接口

    1)数据入栈

    栈的插入操作,叫做 入栈,也可称为 进栈、压栈。如下图所示,代表了三次入栈操作:

    在这里插入图片描述

    代码实现:

    void StackPush(ST* ps, STDataType x)
    {
    	assert(ps);
    	if (ps->top == ps->capacity)
    	{
    		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
    		STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newcapacity);
    		if (tmp == NULL)
    		{
    			perror("realloc fail");
    			exit(-1);
    		}
    		ps->a = tmp;
    		ps->capacity = newcapacity;
    	}
    	ps->a[ps->top] = x;
    	ps->top++;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    由于栈是由顺序表实现的,因此当空间不够需要扩容,入栈之后top需要+1为了记录下一个入栈位置。

    2)数据出栈

    栈的删除操作,叫做 出栈,也可称为 弹栈。如下图所示,代表了两次出栈操作:

    在这里插入图片描述

    void StackPop(ST* ps)
    {
    	assert(ps);
    	assert(!StackEmpty(ps));
    	--ps->top;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    弹一次让top减一即可。

    3)清空栈

    一直 出栈,直到栈为空,如下图所示:

    在这里插入图片描述

    即一直出栈到没有元素即可。

    //想要直接清除栈也可以直接销毁,此代表着程序结束
    void StackDestory(ST* ps)
    {
    	assert(ps);
    	free(ps->a);
    	ps->a = NULL;
    	ps->top = ps->capacity = 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.2 只读接口

    1)获取栈顶数据

    对于一个栈来说只能获取 栈顶 数据,一般不支持获取 其它数据。

    STDataType StackTop(ST* ps)
    {
    	assert(ps);
    	assert(!StackEmpty(ps));
    	return ps->a[ps->top - 1];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2)获取栈元素个数

    栈元素个数一般用一个额外变量存储,入栈 时加一,出栈 时减一。这样获取栈元素的时候就不需要遍历整个栈。通过 **O ( 1 )**的时间复杂度获取栈元素个数。

    int StackSize(ST* ps)
    {
    	assert(ps);
    	return ps->top;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3)栈的判空

    当栈元素个数为零时,就是一个空栈,空栈不允许 出栈 操作。

    bool StackEmpty(ST* ps)
    {
    	assert(ps);
    	return ps->top == 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3. 栈的顺序表实现

    对于顺序表,在 C语言 中表现为 数组,在进行 栈的定义 之前,我们需要考虑以下几个点:
      1)栈数据的存储方式,以及栈数据的数据类型;
      2)栈的大小;
      3)栈顶指针;

    此类信息都在对应的Stack.h头文件中定义

    3.1 Stack.h

    #pragma once
    #include<stdio.h>
    #include<stdlib.h>
    #include<assert.h>
    #include<stdbool.h>
    
    typedef int STDataType;
    typedef struct Stack
    {
    	STDataType* a;
    	int top;
    	int capacity;
    }ST;
    
    void StackInit(ST* ps);//栈的初始化
    void StackDestory(ST* ps);//栈的销毁
    void StackPush(ST* ps, STDataType x);//入栈
    void StackPop(ST* ps);//出栈
    
    STDataType StackTop(ST* ps);//获取栈顶元素
    bool StackEmpty(ST* ps);//判断栈是否为空
    int StackSize(ST* ps);//计算栈的数据个数
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    3.2 Stack.c

    #define _CRT_SECURE_NO_WARNINGS 1
    #include"Stack.h"
    void StackInit(ST* ps)
    {
    	ps->a = NULL;
    	ps->top = ps->capacity = 0;
    }
    
    
    void StackDestory(ST* ps)
    {
    	assert(ps);
    	free(ps->a);
    	ps->a = NULL;
    	ps->top = ps->capacity = 0;
    }
    void StackPush(ST* ps, STDataType x)
    {
    	assert(ps);
    	if (ps->top == ps->capacity)
    	{
    		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
    		STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newcapacity);
    		if (tmp == NULL)
    		{
    			perror("realloc fail");
    			exit(-1);
    		}
    		ps->a = tmp;
    		ps->capacity = newcapacity;
    	}
    	ps->a[ps->top] = x;
    	ps->top++;
    
    }
    void StackPop(ST* ps)
    {
    	assert(ps);
    	assert(!StackEmpty(ps));
    	--ps->top;
    }
    
    STDataType StackTop(ST* ps)
    {
    	assert(ps);
    	assert(!StackEmpty(ps));
    	return ps->a[ps->top - 1];
    }
    bool StackEmpty(ST* ps)
    {
    	assert(ps);
    	return ps->top == 0;
    }
    int StackSize(ST* ps)
    {
    	assert(ps);
    	return ps->top;
    }
    
    
    
    • 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

    3.3 Test.c

    #define _CRT_SECURE_NO_WARNINGS 1
    #include"Stack.h"
    
    void TestStack()
    {
    	ST st;
    	StackInit(&st);
    	StackPush(&st, 1);
    	StackPush(&st, 2);
    	StackPush(&st, 3);
    	printf("%d ", StackTop(&st));
    	StackPop(&st);
    	printf("%d ", StackTop(&st));
    	StackPop(&st);
    	printf("%d ", StackTop(&st));
    
    	StackPush(&st, 4);
    	StackPush(&st, 5);
    	printf("\n");
    	while (!StackEmpty(&st))
    	{
    		printf("%d ", StackTop(&st));
    		StackPop(&st);
    	}
    	printf("\n");
    }
    
    int main()
    {
    	TestStack();
    	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

    在这里插入图片描述

    4. 总结

    栈的学习内容就到这里,下一章会是队列的实现以及oj题的讲解。

  • 相关阅读:
    Guitar Pro 8吉他新版功能特性简介
    前端面试:复习闭包
    【机器学习】李宏毅——Adversarial Attack(对抗攻击)
    Python武器库开发-基础篇(四)
    SpringBoot原理初探
    【动态规划】leetcode 213. 打家劫舍 II
    Ubuntu下Nginx配置ModSecurity详细思路及过程
    Vue3 相较 Vue2 做的重大更新
    【C++】SLT 六大组件之一:容器总结
    多样性和VE的进化
  • 原文地址:https://blog.csdn.net/NEFUT/article/details/126214426