C语言数据结构之栈简单操作

C语言数据结构之栈简单操作

什么是栈?

栈(Stack)是一种线性数据结构,它具有“后进先出”(Last-In-First-Out)的特性。栈顶是栈的一端,另一端称为栈底。每次只能从栈顶插入数据(入栈)或者从栈顶取出数据(出栈)。

栈的简单操作

栈的简单操作包括:

  1. 初始化栈
  2. 判断栈是否为空
  3. 判断栈是否已满
  4. 入栈操作
  5. 出栈操作
  6. 获取栈顶元素

栈的初始化

栈的初始化可以通过动态分配内存的方式来实现。代码如下:

#define MAXSIZE 100
typedef int ElemType;

typedef struct {
    ElemType data[MAXSIZE];  // 存放栈数据
    int top;  // 栈顶指针
} SqStack;

// 初始化栈
void InitStack(SqStack *S) {
    S->top = -1;  // 栈顶指针初始化为-1,表示栈为空
}

判断栈是否为空

栈是否为空可以通过栈顶指针判断。如果栈顶指针等于-1,表示栈为空,否则栈不为空。代码如下:

// 判断栈是否为空
int IsEmpty(SqStack S) {
    if (S.top == -1) {
        return 1;  // 栈为空
    }
    return 0;  // 栈不为空
}

判断栈是否已满

静态数组实现的栈可以通过数组下标来判断栈是否已满。如果栈顶指针等于MAXSIZE-1,表示栈已满,否则栈未满。代码如下:

// 判断栈是否已满
int IsFull(SqStack S) {
    if (S.top == MAXSIZE-1) {
        return 1;  // 栈已满
    }
    return 0;  // 栈未满
}

入栈操作

入栈操作是将一个元素压入栈顶。入栈操作需要先判断栈是否已满。如果栈未满,将元素插入到栈顶,并将栈顶指针加1。代码如下:

// 入栈操作
int Push(SqStack *S, ElemType x) {
    if (IsFull(*S)) {
        return 0;  // 栈已满,入栈失败
    }
    S->top++;  // 栈顶指针加1
    S->data[S->top] = x;  // 将元素压入栈顶
    return 1;  // 入栈成功
}

出栈操作

出栈操作是将栈顶元素弹出。出栈操作需要先判断栈是否为空。如果栈非空,将栈顶元素弹出,并将栈顶指针减1。代码如下:

// 出栈操作
int Pop(SqStack *S, ElemType *x) {
    if (IsEmpty(*S)) {
        return 0;  // 栈为空,出栈失败
    }
    *x = S->data[S->top];  // 将栈顶元素弹出
    S->top--;  // 栈顶指针减1
    return 1;  // 出栈成功
}

获取栈顶元素

获取栈顶元素是返回栈顶元素的值,但不弹出栈顶元素。获取栈顶元素需要先判断栈是否为空。如果栈非空,返回栈顶元素的值。代码如下:

// 获取栈顶元素
int GetTop(SqStack S, ElemType *x) {
    if (IsEmpty(S)) {
        return 0;  // 栈为空,获取栈顶元素失败
    }
    *x = S.data[S.top];  // 返回栈顶元素的值
    return 1;  // 获取栈顶元素成功
}

示例说明

示例1:用栈模拟简单计算器

现在有一个简单的计算器,只支持+、-、*、/四则运算,不支持括号,我们需要用栈来模拟它。假设用户输入的表达式存放在一个字符数组exp中,我们可以通过以下步骤来实现:

  1. 初始化栈S。
  2. 从左到右遍历exp,依次读取每个字符。
  3. 如果字符是数字字符,则将其转换为整数,并入栈S。
  4. 如果字符是操作符,则从栈S中弹出两个操作数,进行计算,将计算结果压入栈S。
  5. 最后栈顶就是表达式计算结果。

具体实现可以参考以下代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXSIZE 100

typedef struct {
    int data[MAXSIZE];
    int top;
} SqStack;

void InitStack(SqStack *S) {
    S->top = -1;
}

int IsEmpty(SqStack S) {
    if (S.top == -1) {
        return 1;
    }
    return 0;
}

int IsFull(SqStack S) {
    if (S.top == MAXSIZE-1) {
        return 1;
    }
    return 0;
}

int Push(SqStack *S, int x) {
    if (IsFull(*S)) {
        return 0;
    }
    S->top++;
    S->data[S->top] = x;
    return 1;
}

int Pop(SqStack *S, int *x) {
    if (IsEmpty(*S)) {
        return 0;
    }
    *x = S->data[S->top];
    S->top--;
    return 1;
}

int GetTop(SqStack S, int *x) {
    if (IsEmpty(S)) {
        return 0;
    }
    *x = S.data[S.top];
    return 1;
}

int main() {
    SqStack S;
    InitStack(&S);
    char exp[MAXSIZE];
    printf("请输入表达式:");
    fgets(exp, MAXSIZE, stdin);
    int len = strlen(exp);
    int i, num1, num2, result;
    for (i = 0; i < len; i++) {
        if (exp[i] >= '0' && exp[i] <= '9') {  // 如果是数字字符
            int num = exp[i] - '0';
            Push(&S, num);
        } else if (exp[i] == '+' || exp[i] == '-' || exp[i] == '*' || exp[i] == '/') {  // 如果是操作符
            Pop(&S, &num2);
            Pop(&S, &num1);
            switch (exp[i]) {  // 根据操作符进行计算
                case '+':
                    result = num1 + num2;
                    break;
                case '-':
                    result = num1 - num2;
                    break;
                case '*':
                    result = num1 * num2;
                    break;
                case '/':
                    result = num1 / num2;
                    break;
            }
            Push(&S, result);
        }
    }
    GetTop(S, &result);
    printf("计算结果:%d\n", result);
    return 0;
}

示例2:判断括号是否匹配

现在有一个括号字符串,我们需要用栈来判断其中的括号是否匹配。假设括号字符串存放在一个字符数组str中,我们可以通过以下步骤来实现:

  1. 初始化栈S。
  2. 从左到右遍历str,依次读取每个字符。
  3. 如果字符是左括号,入栈S。
  4. 如果字符是右括号,从栈S中弹出一个左括号,判断两者是否匹配。
  5. 遍历完成后,如果栈S非空,则括号不匹配,否则括号匹配。

具体实现可以参考以下代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXSIZE 100

typedef struct {
    char data[MAXSIZE];
    int top;
} SqStack;

void InitStack(SqStack *S) {
    S->top = -1;
}

int IsEmpty(SqStack S) {
    if (S.top == -1) {
        return 1;
    }
    return 0;
}

int IsFull(SqStack S) {
    if (S.top == MAXSIZE-1) {
        return 1;
    }
    return 0;
}

int Push(SqStack *S, char x) {
    if (IsFull(*S)) {
        return 0;
    }
    S->top++;
    S->data[S->top] = x;
    return 1;
}

int Pop(SqStack *S, char *x) {
    if (IsEmpty(*S)) {
        return 0;
    }
    *x = S->data[S->top];
    S->top--;
    return 1;
}

int GetTop(SqStack S, char *x) {
    if (IsEmpty(S)) {
        return 0;
    }
    *x = S.data[S.top];
    return 1;
}

int main() {
    SqStack S;
    InitStack(&S);
    char str[MAXSIZE];
    printf("请输入括号字符串:");
    fgets(str, MAXSIZE, stdin);
    int len = strlen(str);
    int i;
    char ch, top;
    for (i = 0; i < len-1; i++) {
        ch = str[i];
        if (ch == '(' || ch == '[' || ch == '{') {  // 如果是左括号
            Push(&S, ch);
        } else if (ch == ')' || ch == ']' || ch == '}') {  // 如果是右括号
            if (IsEmpty(S)) {
                printf("括号不匹配\n");
                return 0;
            }
            Pop(&S, &top);
            if ((ch == ')' && top != '(') || (ch == ']' && top != '[') || (ch == '}' && top != '{')) {
                printf("括号不匹配\n");
                return 0;
            }
        }
    }
    if (!IsEmpty(S)) {
        printf("括号不匹配\n");
        return 0;
    }
    printf("括号匹配\n");
    return 0;
}

总结

本文主要介绍了栈(Stack)的基本概念和简单操作,包括栈的初始化、判断栈是否为空、判断栈是否已满、入栈操作、出栈操作、获取栈顶元素等。栈是一种非常常用的数据结构,它可以用于解决很多实际问题,例如用栈模拟计算器、用栈判断括号是否匹配等。通过本文的介绍,相信读者已经对栈有了更深入的了解,可以更加灵活地使用栈来解决实际问题。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言数据结构之栈简单操作 - Python技术站

(0)
上一篇 2023年5月16日
下一篇 2023年5月16日

相关文章

  • C++数据结构哈希表详解

    C++数据结构哈希表详解 哈希表(Hash Table)是一种非常重要的数据结构,用于实现字典等各种应用。哈希表将关键字映射到一个固定大小的数据集合中,以支持常数时间复杂度的插入、查找和删除操作。哈希表的核心思想是将关键字通过哈希函数(Hash Function)映射到数据集合中的一个索引位置,哈希函数需要满足良好的散列性质,使得关键字能够均匀地散布在数据集…

    数据结构 2023年5月17日
    00
  • 数据结构与算法中二叉树子结构的详解

    数据结构与算法中二叉树子结构的详解 什么是二叉树子结构 二叉树是一种数据结构,由包含根节点的节点组成,可以拓展为左子树和右子树。二叉树子结构指的是,在一棵二叉树中,具有连续节点的子树。 如何判断是否为二叉树子结构 对于一棵二叉树T和另外一棵二叉树S,我们可以判断S是否为T的子树,遵循以下判断原则: 如果树S为空,则表示S不是T的子树; 如果树S的根节点和树T…

    数据结构 2023年5月17日
    00
  • C语言一篇精通链表的各种操作

    C 语言精通链表操作攻略 简介 链表是一种常用的数据结构,它相对于数组等数据结构来说,具有更高的灵活性和增删操作的效率。在 C 语言中,我们可以用指针来实现链表,这也是指针与动态内存分配的重要应用之一。本文将提供在 C 语言中精通链表操作的攻略,包括链表的创建、添加、删除、搜索、遍历等常用操作。 基本结构体定义 链表一般由结构体和指针构成,下面我们定义一个链…

    数据结构 2023年5月17日
    00
  • Java数据结构之堆(优先队列)详解

    Java数据结构之堆(优先队列)详解 概述 堆是一种基于树的数据结构,它可以用来解决很多问题,例如排序、优先队列等。在堆中,每个节点的值都小于或等于它的子节点的值。堆分为两种类型:最大堆和最小堆。在最大堆中,根节点的值最大;而在最小堆中,根节点的值最小。 堆的操作主要有以下两种: 插入:将一个元素插入到堆中,需要维护堆的性质,即节点的值小于或等于子节点的值。…

    数据结构 2023年5月17日
    00
  • 一文带你走进js数据类型与数据结构的世界

    一文带你走进JS数据类型与数据结构的世界 一、JS数据类型 1. 原始类型 JS中原始类型包括:Undefined、Null、Boolean、Number、String、Symbol(ES6新增)。 其中Undefined和Null分别代表未定义和空值,Boolean表示布尔值,Number表示数字,String表示字符串,Symbol是ES6新增的一种基础…

    数据结构 2023年5月17日
    00
  • C++数据结构之链表详解

    C++数据结构之链表详解 链表是一种重要的数据结构,它可以动态的分配内存空间,实现灵活的元素插入,删除等操作。本文将详细讲解链表的定义、实现、常见操作以及链表的应用。 定义与特点 链表是一种线性表数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。链表分为单向链表和双向链表,其中单向链表的每个节点只包含一个指针,指向下一个节点,而双向链表的每…

    数据结构 2023年5月17日
    00
  • C#数据结构之顺序表(SeqList)实例详解

    C#数据结构之顺序表(SeqList)实例详解 顺序表(SeqList)概述 顺序表(SeqList)是一种线性表存储结构,它的特点是元素的存储位置是连续的。因为它的存储结构是数组,所以在访问和修改元素时,可以通过数组下标进行快速定位。顺序表在内存中的存储相对紧凑,因此查找和修改效率都很高,适用于大多数元素较少、但是需要频繁访问的场景。 实现顺序表(SeqL…

    数据结构 2023年5月17日
    00
  • Redis数据结构之链表详解

    Redis数据结构之链表详解 Redis中,链表是一个非常重要的底层数据结构,被用于实现众多高级数据结构(例如列表、队列等)的底层实现,同时也可以被用户直接使用。这篇文章将详细讲解Redis的链表实现、过程和应用。 链表结构 Redis的链表由多个节点组成,每个节点包含以下三个部分: 前置节点地址(prev) 后置节点地址(next) 节点的值(value)…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部