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

yizhihongxing

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++11中的右值引用、转移语义和完美转发

    浅析C++11中的右值引用、转移语义和完美转发 本文主要介绍C++11中的三个新特性:右值引用、转移语义和完美转发,以及它们在实践中的应用。本文假设读者已经对C++语言有一定的了解,了解引用和复制构造函数的相关概念。 右值引用 右值引用是C++11中引入的新概念,它是指用于绑定右值(rvalue)的引用。右值是指在表达式中只能出现在赋值语句右侧的表达式,通常…

    C 2023年5月23日
    00
  • 用C# 控制Windows系统音量的实现方法

    以下是详细讲解“用C# 控制Windows系统音量的实现方法”的完整攻略。 1. 需要的工具和环境 .NET Framework 4或以上版本 C# 编程环境,如Visual Studio 2. 获取音量调节API 要控制系统音量,我们需要使用Windows API,具体来说是Core Audio API。这是一个Windows自带的API,可以让我们访问和…

    C 2023年5月23日
    00
  • Python基础面试20题

    来为大家详细讲解一下“Python基础面试20题”的完整攻略。 一、背景介绍 在Python开发的面试过程中,常常会遇到一些基础的编程题目,这些题目需要求职者对Python语言的基础知识有着较深入的掌握。下面我们就来简要介绍一下“Python基础面试20题”的一些攻略。 二、题目列表 本次面试题共包含20个小题目,我们先来看一下具体的列表: Python的函…

    C 2023年5月22日
    00
  • C程序 打印简单的半右星金字塔图案

    以下是详细讲解“C程序 打印简单的半右星金字塔图案”的完整使用攻略。 程序代码 #include <stdio.h> int main() { int i, j, row; printf("请输入要打印的行数:"); scanf("%d", &row); for(i=1; i<=row; i+…

    C 2023年5月9日
    00
  • C++入门浅谈之类和对象

    C++入门浅谈之类和对象 什么是类和对象? 在 C++ 中,类是一种用户自定义的数据类型,它可以包含数据成员(属性)和成员函数(方法)。对象是类的实例化,即通过类来创建出来的一个具体的变量。 类的定义 定义一个类,可以使用以下的语法结构: class ClassName { private: // 私有成员变量 int privateVar; public:…

    C 2023年5月22日
    00
  • mysql 的load data infile

    MySQL 的 LOAD DATA INFILE 命令可以通过加载本地或远程文件的方式,将数据快速地导入到数据库中,具有导入速度快、效率高等优点。 以下是使用 LOAD DATA INFILE 导入数据的步骤: 1. 准备数据文件 首先要准备好要导入的数据文件,该文件的格式必须与要导入到的表的字段格式完全相同。可以采用各种格式的文件,如 .csv、.txt、…

    C 2023年5月22日
    00
  • C++JSON库CJsonObject详解(轻量简单好用)

    C++JSON库CJsonObject详解 什么是CJsonObject CJsonObject是一个C++ JSON的解析器,它是轻量级而简单易用的。 CJsonObject的特点 优秀的可移植性:用C++编写,依赖于标准库和STL 轻量级:只有两个文件(h和cpp),几乎无外部依赖 易于使用:丰富的API帮助你快速实现JSON的解析和生成 高效性:使用S…

    C 2023年5月23日
    00
  • C++中各种可调用对象深入讲解

    C++中可调用对象的深入讲解 什么是可调用对象? 在C++中,可调用对象是指可以被调用、执行的实体。常见的可调用对象包括函数、类成员函数、lambda表达式等。C++中的可调用对象都可以作为函数参数或返回值进行传递。 函数指针作为可调用对象 在C++中,函数指针也是可调用对象之一。定义函数指针的方式如下: int (*funcPtr)(int, int); …

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