C语言栈的表示与实现实例详解

C语言栈的表示与实现实例详解

栈的概念

栈是一种特殊的线性表,它具备后进先出(Last-In-First-Out,LIFO)的特性。栈实现的基本操作有入栈(push)和出栈(pop)两种。

栈的表示

栈可以通过数组或链表两种数据结构进行表示。

数组表示

数组表示的栈是一段连续的内存空间,可以使用数组下标代表每个栈元素的位置。数组的顶部指针用于标识当前栈顶元素所在的位置。

下面是C语言中数组表示栈的实现过程,其中使用了结构体Stack对栈进行封装。

typedef struct {
  int *array;     // 栈使用的数组
  int size;       // 栈的总容量
  int top;        // 栈顶的位置
} Stack;

// 初始化一个容量为size的栈
void initStack(Stack *s, int size) {
  s->array = (int *) malloc(size * sizeof(int));
  s->size = size;
  s->top = -1;
}

// 入栈操作
void push(Stack *s, int data) {
  if (s->top == s->size - 1) {
    printf("Stack is full\n");
    return;
  }
  s->array[++s->top] = data;
}

// 出栈操作
int pop(Stack *s) {
  if (s->top == -1) {
    printf("Stack is empty\n");
    return -1;
  }
  return s->array[s->top--];
}

链表表示

链表表示的栈利用了链表的指针域来建立每个栈元素之间的联系。链表的头指针指向栈顶元素。

下面是C语言中链表表示栈的实现过程,其中使用了结构体StackNode对栈元素进行封装。

typedef struct StackNode {
  int data;               // 栈元素的值
  struct StackNode *next; // 下一个栈元素的地址
} StackNode;

typedef struct {
  StackNode *top;         // 栈顶元素
} Stack;

// 初始化一个空栈
void initStack(Stack *s) {
  s->top = NULL;
}

// 入栈操作
void push(Stack *s, int data) {
  StackNode *newNode = (StackNode *) malloc(sizeof(StackNode));
  newNode->data = data;
  newNode->next = s->top;
  s->top = newNode;
}

// 出栈操作
int pop(Stack *s) {
  if (s->top == NULL) {
    printf("Stack is empty\n");
    return -1;
  }
  int result = s->top->data;
  StackNode *topNode = s->top;
  s->top = s->top->next;
  free(topNode);
  return result;
}

栈的实现实例

示例1:匹配括号

栈可以用于匹配括号的问题,常见的应用场景是在编写代码时,需要检查代码中的括号是否匹配。例如,检查下列代码中的括号是否匹配。

void func() {
  int a = 1;
  if (a > 0) {
    printf("a is positive.\n");
  } else {
    printf("a is negative.\n");
  }
}

可以发现,该代码中的括号是匹配的。具体解决方法是:使用一个栈来保存每个左括号出现的位置,当遇到右括号时,从栈中弹出一个左括号的位置,判断左右括号的位置是否匹配。如果栈为空或栈顶元素不是与当前右括号匹配的左括号,则出现括号不匹配的错误。

下面是使用数组表示栈的实现过程。

bool checkParenthesis(char *str) {
  Stack s;
  initStack(&s, strlen(str));

  for (int i = 0; i < strlen(str); i++) {
    if (str[i] == '(') {
      push(&s, i);
    } else if (str[i] == ')') {
      if (s.top == -1) {
        printf("Error: unmatched ')' at position %d\n", i);
        return false;
      }
      int leftIndex = pop(&s);
      printf("Matched '()' at positions %d and %d\n", leftIndex, i);
    }
  }

  if (s.top != -1) {
    printf("Error: unmatched '(' at position %d\n", s.array[s.top]);
    return false;
  }

  return true;
}

示例2:中缀表达式转后缀表达式

栈还可以用于中缀表达式转后缀表达式的问题,例如将“2+3*(4+5)-6”这个中缀表达式转换为后缀表达式。具体解决方法是:从左向右遍历中缀表达式,使用一个栈来保存运算符,如果遇到数字,则直接输出到后缀表达式中。如果遇到运算符,则将其压入栈中。需要注意的是,运算符有优先级,需要根据优先级来确定何时将运算符输出到后缀表达式中。当遇到左括号时,将其压入栈中。当遇到右括号时,将栈中的运算符弹出直到遇到左括号为止,并且左右括号都不在后缀表达式中输出。

下面是使用数组表示栈的实现过程。

bool isOperator(char c) {
  return c == '+' || c == '-' || c == '*' || c == '/';
}

int getOperatorPriority(char c) {
  switch (c) {
    case '+':
    case '-':
      return 1;
    case '*':
    case '/':
      return 2;
    default:
      return 0;
  }
}

void infixToPostfix(char *infix, char *postfix) {
  Stack s;
  initStack(&s, strlen(infix));
  int j = 0;
  for (int i = 0; i < strlen(infix); i++) {
    if (isdigit(infix[i])) {
      postfix[j++] = infix[i];
    } else if (isOperator(infix[i])) {
      while (s.top != -1 && getOperatorPriority(infix[i]) <= getOperatorPriority(s.array[s.top])) {
        postfix[j++] = pop(&s);
      }
      push(&s, infix[i]);
    } else if (infix[i] == '(') {
      push(&s, infix[i]);
    } else if (infix[i] == ')') {
      while (s.top != -1 && s.array[s.top] != '(') {
        postfix[j++] = pop(&s);
      }
      if (s.top == -1) {
        printf("Error: unmatched '(' at position %d\n", i);
        return;
      }
      pop(&s);
    } else {
      printf("Error: invalid character '%c' at position %d\n", infix[i], i);
      return;
    }
  }
  while (s.top != -1) {
    if (s.array[s.top] == '(') {
      printf("Error: unmatched '(' at position %d\n", s.top);
      return;
    }
    postfix[j++] = pop(&s);
  }
  postfix[j] = '\0';
}

结语

栈是一种非常常用的数据结构,可以用于很多实际问题的解决。本文介绍了栈的基本概念、表示方法和实现实例,希望能对读者有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言栈的表示与实现实例详解 - Python技术站

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

相关文章

  • C/C++实现线性顺序表的示例代码

    下面是关于“C/C++实现线性顺序表”的完整攻略: 什么是线性顺序表 在计算机科学中,线性顺序表(Linear Sequences List)是一种连续的数据结构,也被称为数组,它由一组元素组成,并按线性顺序排列。线性顺序表中,每个元素和其相邻元素之间仅有了顺序关系,它们之间没有其他关系。通常情况下,线性顺序表采用数组来实现,支持随机访问操作。 C/C++实…

    C 2023年5月24日
    00
  • C++实现教务管理系统

    C++实现教务管理系统攻略 1. 简介 教务管理系统是学校行政管理的重要组成部分,方便教务管理人员进行课程管理、考试管理、成绩管理、学籍管理等工作。C++作为一种高级编程语言,具有良好的可移植性、强大的数据处理能力和较高的运行效率,适合用于教务管理系统的开发。 本文将介绍如何使用C++编程语言实现教务管理系统的开发,包括如何进行需求分析、系统设计、数据结构选…

    C 2023年5月23日
    00
  • C语言实现扫雷程序

    为了更好地阐述如何实现扫雷程序,我将按照以下步骤给出完整攻略: 1. 设计游戏界面 首先,我们需要一个游戏界面,在游戏界面中需要有一个地图、雷区和计分板。可以使用图形化界面库如GTK、QT等来完成界面的搭建,也可以使用控制台界面(命令行界面)以字符方式来实现。在这里,我们将以控制台界面为例进行演示。 在终端中,使用字符来显示方格和数字,用字母来代表是否被扫。…

    C 2023年5月23日
    00
  • C++破坏MBR的代码

    如您所说,破坏MBR的代码足以引起恶意行为,为避免安全问题,我不会提供完整的攻击攻略,但我可以为您提供一些基础知识。 MBR,即主引导记录,是位于计算机存储器媒介(例如硬盘或闪存驱动器)的最前面的一段代码。MBR包含有关媒介分区和引导程序的信息,以便启动从选定分区的操作系统。因此,MBR的完整性对于系统的正常启动至关重要。如果MRR被破坏,系统将无法启动或无…

    C 2023年5月24日
    00
  • C/C++实现矩阵的转置(示例代码)

    C/C++实现矩阵的转置(示例代码) 矩阵的转置指的是将矩阵的行和列互换的一个操作。在编程中,实现矩阵的转置可以用来优化矩阵变换的计算,也可以用来解决图像处理、信号处理等问题。下面我们将介绍如何使用C/C++来实现矩阵的转置。 一、矩阵转置的实现方法 方法一:使用二维数组 在C/C++中,使用二维数组可以很方便地表示矩阵。我们可以通过遍历矩阵元素的方式,将矩…

    C 2023年5月24日
    00
  • C if else if ladder

    C 语言中的 if else if 梯形结构又被称作 if else if ladder,它是多个条件语句的嵌套,可以用来实现复杂的条件判断。以下是 if else if ladder 的完整使用攻略: 梯形结构语法格式 if (condition1) { statement1; } else if (condition2) { statement2; } …

    C 2023年5月9日
    00
  • Android中的JSON详细总结

    下面是关于“Android中的JSON详细总结”的攻略。 什么是JSON JSON(JavaScript Object Notation)是一种数据格式,常用于网络传输数据。它是在JavaScript中创建的对象,但现在已经成为一种独立的数据交换格式。 与XML相比,JSON更加简单、轻量级。在Android开发中,JSON也是比较流行的一种数据格式。 JS…

    C 2023年5月23日
    00
  • Win7旗舰版升级Win10提示错误代码C1900107的解决方法

    下面是详细讲解“Win7旗舰版升级Win10提示错误代码C1900107的解决方法”的完整攻略。 问题描述 在升级Win7旗舰版到Win10时,可能会出现错误代码C1900107的提示,导致升级失败。这个错误通常是由于系统内存不足或硬盘空间不足所导致的。 解决方法 针对这个问题,可以采取以下几个步骤来解决: 步骤1:清理硬盘空间 由于Win10系统占用的空间…

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