C语言数据结构篇——栈的顺序存储

简介: C语言数据结构篇——栈的顺序存储

前言


在学完顺序表和链表这两种最基本的数据结构之后就要进入我们的栈和队列的学习了,首先我们来学习栈,而栈的存储方式一样有两种,一种是顺序存储,一种是链式存储,储存结构的不同使实现栈的基本算法也不同,今天我要给大家分享的的就是栈的顺序存储。


初识栈


栈也属于线性表,但是栈是操作受限的线性表,操作受限,就是栈的特点特点之一,在前面线性表的学习中我们知道,链表可以在表的两端甚至任何位置进行插入,删除,等操作,但栈却只能在固定的一端进行操作,意思就是栈的插入,删除等操作都只能在表的一个固定端点上进行,如下图:


149caa00d21e4521ad0c877052d3affc.png


如上图,我们可以看到插入,删除等操作只能在一侧进行, 所以向一个栈中插入新元素又称为压栈,入栈;同样的,栈数据的删除又可以称为出栈,弹栈,能够进行压栈,弹栈的一端自称为栈顶,不能的一端称为栈底,下面我们就来看一看应该怎么实现栈的顺序存储;


栈的创建


栈的创建,我们同样以头结点结构体的形式创建栈,头结点的结构体中保存一个数组和一个整型top,如下:


#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define maxsize 1024//栈的容量(自定义)
#define INFINITY 99999//随便定一个数,待会需要
typedef struct
{
    int data[maxsize];//该数组用来存放栈的数据
    int top;//数组中栈顶元素的下标(即最后一个元素下标)
}seqstack;//定义别名方便使用


这样一个栈就创建好了,下面就可以直接使用了 ;


栈的初始化


我们上面说了头结点中的top代表栈顶元素在数组中的下标 ,所以初始化时就不能把top赋值成自然数,所以我们把top赋值为-1,这样就完成了栈的初始化


void initstack(seqstack* stack)//初始化栈
{
    stack->top=-1;
}


判断栈为空


判断栈是否为空也很简单,要判断栈为空就判断栈是否为初始状态,而上面我们也进行了栈的初始化,所以栈是否等于-1就可以作为判断栈是否为空的依据,具体代码如下:


int isempty(seqstack* stack)//判断栈为空
{
    if(stack->top==-1)
    {
        return 1;//栈为空
    }
    return 0;//栈不为空
}


获取栈顶元素


因为我们是用数组来存放栈的数据的,所以要获取栈顶元素,就是获取数组中位于栈顶元素的下标,由上面的结构示意图可以看出来,栈底指的就是数组的第一个元素的位置,栈底指的就是数组最后一个元素,而头结点结构体中的top正是数组中最后一个元素的下标,所以获取栈顶元素是不是也很简单了呢?具体代码如下:


int seqstack_top(seqstack* stack)//获取栈顶元素
{
    if(isempty(stack)==0)//栈不为空
    {
        return stack->data[stack->top];
    }
    return INFINITY;//返回无穷大,不能返回-1,有可能栈的顶端元素就是-1
}


弹出栈顶元素


弹出栈顶元素就是我们的弹栈,压栈,意思就是弹出栈顶元素,使栈顶元素的后面一个元素成为栈顶元素,对应到数组中的实际操作其实就是删除数组的最后一个元素,所以也是比较简单的,具体代码如下:


int seqstack_pop(seqstack* stack)//弹出栈顶元素
{
    if(isempty(stack)==0)
    {
        return stack->data[stack->top--];
    }
    return INFINITY;//与获取栈顶元素同理
}


压入栈顶元素


压入栈顶元素就是我们称的压栈,入栈,即吧压入的数据放到栈顶的前面,使之称为新的栈顶,而数组上的意思就是在数组最后一个数据上再加一个数据,具体代码如下:


void seqstack_push(seqstack* stack,int val)//压栈(入栈)
{
    if(stack->top>=maxsize-1)栈已满则无法进行压栈
    {
        return;//退出程序
    }
    stack->top++;//此时栈顶改变,所以top指向新的栈顶下标
    stack->data[stack->top]=val;//入栈
}


销毁栈


销毁栈就不多说了,直接上代码:


void seqstack_destory(seqstack* stack)
{
    if(isempty(stack)==0)
    {
        free(stack);
    }
}


当然,为了方便使用,我们还可以建立一个遍历打印(即输出)栈的函数,代码如下:


void seqstack_print(seqstack* stack)
{
    for(int i=0;i<=stack->top;i++)
    {
        if(i%5==0)
        {
            printf("\n");
        }
        printf("%d ",stack->data[i]);
    }
    printf("\n");
}


以上就是栈的一些基本操作,我们都以函数的形式封装完了。


完整代码  


下面我们就随便写点数据将这些函数都用起来,就是完整代码啦,代码如下:


#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define maxsize 1024//栈的容量
#define INFINITY 99999//随便定一个数
typedef struct
{
    int data[maxsize];//定义一个数组
    int top;//栈顶元素的下标
}seqstack;
void initstack(seqstack* stack)//初始化栈
{
    stack->top=-1;
}
int isempty(seqstack* stack)//判断栈为空
{
    if(stack->top==-1)
    {
        return 1;//栈为空
    }
    return 0;//栈不为空
}
int seqstack_top(seqstack* stack)//获取栈顶元素
{
    if(isempty(stack)==0)//
    {
        return stack->data[stack->top];
    }
    return INFINITY;//返回无穷大,不能返回-1,有可能栈的顶端元素就是-1
}
int seqstack_pop(seqstack* stack)//弹出栈顶元素
{
    if(isempty(stack)==0)
    {
        return stack->data[stack->top--];
    }
    return INFINITY;
}
void seqstack_push(seqstack* stack,int val)//压栈(入栈)
{
    if(stack->top>=maxsize-1)
    {
        return;//退出程序
    }
    stack->top++;//指向栈顶
    stack->data[stack->top]=val;//入栈
}
void seqstack_destory(seqstack* stack)
{
    if(isempty(stack)==0)
    {
        free(stack);
    }
}
void seqstack_print(seqstack* stack)
{
    for(int i=0;i<=stack->top;i++)
    {
        if(i%5==0)
        {
            printf("\n");
        }
        printf("%d ",stack->data[i]);
    }
    printf("\n");
}
int main()
{
    srand((unsigned)time(0));//以时间为种子获取随机数
    seqstack stack;
    initstack(&stack);
    printf("请输入栈的初始数据个数\n");
    int number;
    scanf("%d",&number);
    for(int i=0;i<number;i++)//将随机数压栈
    {
        seqstack_push(&stack,rand()%1000);
        //rand可以按顺序读取srand通过种子获得的随机数
        //“%1000”是因为我想将随机数的值控制在0到1000
    }
    //获取栈顶元素
    printf("栈顶元素:%d\n",seqstack_top(&stack));
    printf("栈中的元素");
    seqstack_print(&stack);
    seqstack_pop(&stack);//出栈
    printf("出栈后栈中的元素");
    seqstack_print(&stack);
    printf("请输入要压栈的元素\n");
    int input;
    scanf("%d",&input);
    seqstack_push(&stack,input);//入栈
    printf("压栈后栈中的元素");
    seqstack_print(&stack);
    seqstack_destory(&stack);
    return 0;
}


随便写点数据运行一下就是下面这个效果啦


请输入栈的初始数据个数

10

栈顶元素:629

栈中的元素

340 937 63 665 546

729 904 922 326 629

出栈后栈中的元素

340 937 63 665 546

729 904 922 326

请输入要压栈的元素

9999

压栈后栈中的元素

340 937 63 665 546

729 904 922 326 9999


大一学生,c语言学习半年,文章有什么不完善的地方还请见谅,欢迎大家对文章提出自己的看法,最后,感谢大家的阅读


相关文章
|
26天前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
38 1
|
1月前
|
存储 算法 搜索推荐
【趣学C语言和数据结构100例】91-95
本文涵盖多个经典算法问题的C语言实现,包括堆排序、归并排序、从长整型变量中提取偶数位数、工人信息排序及无向图是否为树的判断。通过这些问题,读者可以深入了解排序算法、数据处理方法和图论基础知识,提升编程能力和算法理解。
46 4
|
1月前
|
存储 机器学习/深度学习 搜索推荐
【趣学C语言和数据结构100例】86-90
本文介绍并用C语言实现了五种经典排序算法:直接插入排序、折半插入排序、冒泡排序、快速排序和简单选择排序。每种算法都有其特点和适用场景,如直接插入排序适合小规模或基本有序的数据,快速排序则适用于大规模数据集,具有较高的效率。通过学习这些算法,读者可以加深对数据结构和算法设计的理解,提升解决实际问题的能力。
43 4
|
1月前
|
存储 算法 数据处理
【趣学C语言和数据结构100例】81-85
本文介绍了五个经典算法问题及其C语言实现,涵盖图论与树结构的基础知识。包括使用BFS求解单源最短路径、统计有向图中入度或出度为0的点数、统计无向无权图各顶点的度、折半查找及二叉排序树的查找。这些算法不仅理论意义重大,且在实际应用中极为广泛,有助于提升编程能力和数据结构理解。
41 4
|
27天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
53 5
|
26天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
57 1
|
1月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
210 9
|
1月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
35 1
|
1月前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。
|
1月前
|
存储 JavaScript 前端开发
执行上下文和执行栈
执行上下文是JavaScript运行代码时的环境,每个执行上下文都有自己的变量对象、作用域链和this值。执行栈用于管理函数调用,每当调用一个函数,就会在栈中添加一个新的执行上下文。