C语言超详细讲解栈的实现及代码

C语言超详细讲解栈的实现及代码

什么是栈?

栈(Stack)是计算机中的一种数据结构,也是一种线性结构。它只允许在特定一端进行插入和删除操作,即在栈顶进行操作。栈的特点是后进先出(LIFO,Last In First Out),即在栈顶进入元素,在栈顶取出元素。

栈的实现

栈的实现可以用数组(array)或链表(linked list)来实现。其中,一般使用数组来实现栈。

数组实现栈

首先,我们需要定义一个栈结构体:

#define MAXSIZE 100 // 定义栈的最大容量为100

typedef struct {
  int data[MAXSIZE]; // 存放栈中元素的数组
  int top; // 栈顶指针
} Stack;

其中,data用来储存栈中的元素,top表示栈顶指针,即栈中元素个数。我们将栈顶指针top初始化为-1,表示栈为空。

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

接下来,我们需要实现入栈(Push)和出栈(Pop)操作。入栈操作就是往栈顶添加元素,出栈操作则是从栈顶删除元素。我们也需要判断栈是否为空或已满。

bool Push(Stack * S, int x) {
  if (S->top == MAXSIZE - 1) // 栈已满,不能继续入栈
    return false;
  S->data[++S->top] = x; // 栈顶指针+1,将元素x压入栈顶
  return true;
}

bool Pop(Stack * S, int * x) {
  if (S->top == -1) // 栈已空,无法继续出栈
    return false;
  *x = S->data[S->top--]; // 将栈顶元素弹出并保存到x中,栈顶指针-1
  return true;
}

最后,我们还需要实现取栈顶元素(GetTop)和判断栈是否为空(IsEmpty):

bool GetTop(Stack * S, int * x) {
  if (S->top == -1) // 栈已空,无法取栈顶元素
    return false;
  *x = S->data[S->top]; // 将栈顶元素赋值给x
  return true;
}

bool IsEmpty(Stack * S) {
  return (S->top == -1);
}

链表实现栈

链表实现栈相较于数组实现,需要的内存空间不固定,但需要大量消耗内存来存储节点的指针和数据。链表实现栈的基本操作和数组实现栈的基本操作类似,这里不再赘述。

示例说明

示例1:使用栈实现字符串反转

我们可以使用栈来实现字符串反转。具体实现方法是先把字符串中的每个字符依次入栈,再依次出栈输出即可。

void reverse(char * str) {
  Stack S;
  InitStack(&S);
  int i = 0;
  while (str[i]) {
    Push(&S, str[i++]);
  }
  i = 0;
  while (!IsEmpty(&S)) {
    Pop(&S, &str[i++]);
  }
}

示例2:使用栈实现中缀表达式计算

我们可以使用栈来实现中缀表达式计算。将中缀表达式转换成后缀表达式(也称逆波兰式)后,再使用栈进行计算。这里简单介绍一下中缀表达式转后缀表达式的方法。

我们需要一个运算符栈和一个数字栈。从左到右依次扫描中缀表达式的每个元素,如果是数字就入数字栈,如果是运算符就比较优先级,如果该运算符优先级低于或等于栈顶运算符,则将栈顶运算符出栈并加入后缀表达式中,直至该运算符优先级高于栈顶运算符或运算符栈为空,最后将该运算符进栈。

void infix2postfix(char * infix, char * postfix) {
  Stack S;
  InitStack(&S); // 运算符栈
  int i = 0, j = 0;
  while (infix[i]) {
    if (isdigit(infix[i])) {
      postfix[j++] = infix[i++];
    } else {
      char op;
      if (infix[i] == '(') {
        Push(&S, infix[i]);
        i++;
      } else if (infix[i] == ')') {
        while (Pop(&S, &op) && op != '(') {
          postfix[j++] = op;
        }
        i++;
      } else {
        while (!IsEmpty(&S) && prio(S.data[S.top]) >= prio(infix[i])) {
          Pop(&S, &op);
          postfix[j++] = op;
        }
        Push(&S, infix[i++]);
      }
    }
  }
  while (!IsEmpty(&S)) {
    Pop(&S, &postfix[j++]);
  }
  postfix[j] = 0;
}

int prio(char op) { // 运算符优先级
  switch (op) {
    case '+':
    case '-':
      return 1;
    case '*':
    case '/':
      return 2;
    case '(':
    case ')':
      return 0;
  }
  return -1;
}

int postfix_eval(char * postfix) {
  Stack S; // 数字栈
  InitStack(&S);
  int i = 0, op1, op2, result;
  while (postfix[i]) {
    char ch = postfix[i];
    if (isdigit(ch)) {
      Push(&S, ch - '0');
    } else {
      Pop(&S, &op2);
      Pop(&S, &op1);
      switch (ch) {
        case '+':
          result = op1 + op2;
          break;
        case '-':
          result = op1 - op2;
          break;
        case '*':
          result = op1 * op2;
          break;
        case '/':
          result = op1 / op2;
          break;
        default:
          break;
      }
      Push(&S, result);
    }
    i++;
  }
  Pop(&S, &result);
  return result;
}

总结

以上是栈的实现及应用的详细讲解,希望有所帮助。在实际编程中,栈是非常常用的数据结构,掌握栈的实现及应用对于提高代码效率和可读性非常有帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言超详细讲解栈的实现及代码 - Python技术站

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

相关文章

  • C语言小程序 如何判断三角型类型

    要判断一个三角形的类型,需要先知道这个三角形的三边长度。以下是完整攻略: 首先,需要从用户处获取三角形的三条边长,可以采用以下代码读取用户输入的三边: double a, b, c; scanf("%lf%lf%lf", &a, &b, &c); 接下来,需要判断输入的边长是否可以组成三角形。可以用以下代码来实现:…

    C 2023年5月23日
    00
  • C语言源码实现停车场管理系统

    C语言源码实现停车场管理系统 介绍 停车场管理系统是一个常见的管理系统,可用于实现停车场入场、出场的车辆管理及计费功能。这个系统可以通过编程语言实现。C语言是一门广泛应用于工业界、应用界和学术界的计算机编程语言,在实现停车场管理系统方面也有良好的表现。 实现步骤 下面是一个简单的实现停车场管理系统的步骤: 1. 创建一个车辆结构体 创建一个车辆结构体并在其中…

    C 2023年5月30日
    00
  • Win7系统打开注册表提示注册表文件丢失或损坏0xc0000e9如何解决

    Win7系统打开注册表提示注册表文件丢失或损坏0xc0000e9如何解决 问题描述 当我们在Win7系统中尝试打开注册表(regedit.exe)时,可能会出现错误提示“注册表文件丢失或损坏, 错误代码0xc0000e9”。这在一些情况下会导致计算机无法正常启动,造成极大的困扰。 原因分析 该问题通常是由于硬盘存储数据出现问题导致系统文件受损引起的。最常见的…

    C 2023年5月23日
    00
  • win10系统运行帝国时代2提示错误代码0xc0000022的原因及解决方法

    问题描述 当使用win10系统运行帝国时代2游戏时,会提示错误代码0xc0000022,导致游戏无法正常运行。那么这个错误的出现原因是什么?该如何解决呢? 问题原因 错误代码0xc0000022通常是由于系统权限问题引起的,可能是由于以下原因导致: 游戏所在的目录或文件夹没有设置读写权限。 游戏所在的目录或文件夹被防病毒软件或其他安全软件阻止了读取或写入操作…

    C 2023年5月24日
    00
  • 基于Matlab制作一个不良图片检测系统

    下面是基于Matlab制作一个不良图片检测系统的完整攻略: 步骤1:数据准备 在制作不良图片检测系统之前,需要准备一些数据。首先需要准备一个包含正常图片和不良图片的数据集,这些图片最好都是经过标记的,以便后续的训练和测试。其次,还需要抽取这些图片的特征,这里我们使用的是灰度直方图特征和颜色直方图特征。 步骤2:特征提取 对于每一张图片,在计算其特征之前需要读…

    C 2023年5月23日
    00
  • Win11C盘空间不足怎么扩容?Win11给C盘扩容的方法

    Win11C盘空间不足怎么扩容?Win11给C盘扩容的方法,步骤如下: 操作前提 在进行操作之前,需要保证以下内容: 有一个可用的U盘或移动硬盘。 下载Windows系统的安装文件。 准备好备份重要数据的位置。 注:扩容C盘过程会涉及到更改系统分区的操作,有一定风险,如有不熟悉操作的风险,请在操作前进行备份数据以备万一。 步骤一:备份数据 在进行分区扩容之前…

    C 2023年5月23日
    00
  • C++初始化函数列表详细解析

    C++初始化函数列表详细解析 C++中的类成员变量可以在构造函数中进行初始化,也可以在定义时进行初始化。另外,C++还可以使用初始化函数列表对类成员变量进行初始化。使用初始化函数列表可以消除因多个成员变量初始化而产生的繁琐问题,同时也可以提升代码执行效率。 什么是初始化函数列表? 初始化函数列表是一个以冒号开头的语句块,在一对圆括号内列出类的数据成员及其初始…

    C 2023年5月22日
    00
  • 详解Spring/Spring boot异步任务编程WebAsyncTask

    详解Spring/Spring Boot异步任务编程WebAsyncTask 异步任务是指不需要等待某个操作完成就能继续执行下一个操作, Spring/Spring Boot提供了一种异步任务处理机制,可以在异步操作完成后返回结果给客户端,这就是WebAsyncTask。 对于Web应用程序而言,异步任务是必不可少的,比如上传文件、处理大数据等操作,会占用大…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部