如何用C语言创建一个顺序栈,并实现基础的 “ 出栈入栈 ” 功能

1. 栈(stack)

1. 栈:只允许在一端进行插入、删除的线性数据结构。允许插入和删除的一端叫做栈顶, 另一端叫做栈底。

2. 栈分为顺序栈和链式栈,本文主要介绍顺序栈的使用,想了解链式栈的朋友欢迎浏览下期内容!

​3. 栈的特点: 先进后出。顺序栈占用一片连续存储空间进行操作,链式栈则是分散存储。

4. 我们依旧准备三个文件:stack.c、stack.h、main.c。

5. 请大家多看注释可帮助理解运用!

2. 创建栈

栈的功能函数中不仅有 “ 出栈入栈 ” 还有一系列辅助实现功能的函数——判空、判满、清空、回收、求有效数据长度、显示栈元素函数。

(1)stack.h

在头文件中,定义栈的大小SIZE、定义栈结构体、做函数声明等操作。

#ifndef _stack_h_
#define _stack_h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//宏定义栈(数组)大小
#define SIZE 10
//重命名数据类型int
typedef int data_t;
//顺序栈结构体
typedef struct stack{
    data_t data[SIZE]; //顺序栈用数组做栈体
    int top; //栈顶指针:用来操作插入、删除(实质非指针)
}stack;

//创建顺序栈
stack *stack_create();
//判空
int stack_empty(stack *head); //head是手动开辟空间的首地址
//判满
int stack_full(stack *head);
//清空栈
void stack_clear(stack *head);
//回收栈
void stack_destroy(stack **head);
//获取栈的长度
int stack_length(stack *head);
//显示栈的数据
void stack_display(stack *head);

#endif

(2)stack.c

封装判空、判满、清空、回收、求有效数据长度、显示栈元素函数的功能。

#include "stack.h"

//创建顺序栈
stack *stack_create()
{
    //给栈结构体开辟空间
    stack *head = (stack *)malloc(sizeof(stack));
    if (NULL == head)
    {
        printf("malloc failed!");
        return NULL;
    }
    //给给开辟的空间填充0
    memset(head, 0, sizeof(stack));
    head->top = -1; //栈顶指针初始化为-1表示没有元素
    //返回空间入口地址
    return head;
}

//判空
int stack_empty(stack *head)
{
    if (-1 == head->top)
    {
        printf("Stack is empty!\n");
        return 1;
    }
    return 0;
}

//判满
int stack_full(stack *head)
{
    if (SIZE - 1 == head->top)
        return 1;
    return 0;
}

//清空栈
void stack_clear(stack *head)
{
   head->top = -1; 
}

//回收栈
void stack_destroy(stack **head)
{
    free(*head);
    *head = NULL;
}

//获取栈的长度
int stack_length(stack *head)
{
    return (head->top + 1);
}

//遍历栈的数据
void stack_display(stack *head)
{
    for(int i = 0; i < head->top+1; i++)
        printf("%-3d", head->data[i]);
    puts("");
}

3. 出入栈以及获取栈顶元素

(1)stack.h

在头文件中加入函数声明。

//入栈
int stack_push(stack *head, data_t data);
//出栈
data_t stack_pop(stack *head);
//获取栈顶元素
data_t stack_top(stack *head);

有同学可能会疑问:出栈和获取栈顶元素感觉是差不多的意思呢?

其实获取栈顶元素只是将当前栈顶的数据返回,可供用户打印,而出栈操作不仅包含了获取栈顶元素的功能,额外还将栈顶元素删除,使栈的有效元素减一。

所以在只是想知道栈顶元素的情况下,可使用获取栈顶元素函数;在不仅想知道栈顶元素,还想删除栈顶元素时,使用出栈函数。

(2)stack.c

封装出入栈以及获取栈顶函数的功能。

//入栈
int stack_push(stack *head, data_t data)
{
    //判满
    if (stack_full(head))
    {
        printf("Stack is full! Push failed!\n");
        return -1;
    }
    //有效元素+1
    head->top += 1;
    //插入数据
    head->data[head->top] = data;

    return 0;
}

//出栈
data_t stack_pop(stack *head)
{
    //判空
    if (stack_empty(head))
    {
        printf("Stack is empty! Pop failed!\n");
        return -1;
    }
    //记录栈顶元素
    data_t data = head->data[head->top];
    //有效元素-1
    head->top -= 1;
    //返回已删除的栈顶数据
    return data;
}

//获取栈顶元素
data_t stack_top(stack *head)
{
    //判空
    if (stack_empty(head))
    {
        printf("Stack is empty! Pop failed!\n");
        return -1;
    }
    //返回栈顶元素
    return head->data[head->top];
}

4. 在主函数中验证栈的功能

(1)main.c

#include "stack.h"

int main(int argc, char *argv[])
{ 
    //创建顺序栈
    stack *head = stack_create();
    if (NULL == head)
    {
        printf("malloc failed!\n");
        return -1;
    }
    
    //插入十个数(入栈)
    printf("插入十个数:\n");
    int i = 0;
    while(i++ < 10)
        stack_push(head, i);
    //展示插入数据后的栈
    stack_display(head);

    //出栈
    printf("出栈操作.出栈的元素为:%d\n", stack_pop(head));
    stack_display(head);

    //获取栈顶元素
    printf("栈顶元素为:%d\n", stack_top(head));

    //回收顺序栈
    stack_destroy(&head); //参数是二级指针,所以需要传入一级指针的地址

    return 0;
} 

注:有些同学很爱忽略回收栈这一步,但记得malloc手动开辟的空间一定要及时free,否则会造成内存泄漏。

(2)运行结果展示

插入十个数:
1  2  3  4  5  6  7  8  9  10 
出栈操作.出栈的元素为:10
1  2  3  4  5  6  7  8  9  
栈顶元素为:9

5. 总结

1. 栈的先进后出是它独有的特点,可运用在实现递归、表达式求值等方面。

2. 栈也是线性数据结构的一种,另外线性数据结构还包括线性表(顺序表、链表)、队列,它们各有各的特色,如想了解其他线性结构的使用,欢迎浏览主页相关文章!

3. 除了顺序栈,链式栈也有着他独有的特点,那链式栈怎样实现呢?

敬请期待下集:C语言链式栈的实现(linkstack)

感谢观看!如有疑问欢迎提出!

  ----香菜小猫祝这位uu天天开心----

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值