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日

相关文章

  • rtmc.exe – rtmc是什么进程 有什么用

    首先,rtmc.exe是Realtek音频设备的管理程序,常驻在后台。它在Windows系统启动时自动启动,并且负责控制Realtek音频设备的相关设置和功能。 具体来说,rtmc.exe进程的作用有以下几点: Realtek音频驱动的控制。Realtek音频芯片需要使用rtmc.exe进程来控制设置。例如:音量控制、音效选择等等,都需要通过rtmc.exe…

    C 2023年5月30日
    00
  • python 与c++相互调用实现

    下面是关于Python和C++相互调用实现的完整攻略。 概述 Python和C++都是广泛使用的编程语言,在某些场景下,调用C++代码可以有效提高Python的执行效率。而Python也可以供C++使用高级编程能力。因此,Python和C++之间的相互调用具有很大的实用价值。接下来,我们将介绍如何在Python和C++之间实现相互调用。 实现方法 Pytho…

    C 2023年5月24日
    00
  • JSON传递bool类型数据的处理方式介绍

    JSON(JavaScript Object Notation)是一种用于数据交换的轻量级文本格式,被广泛应用于前后端通信中。在JSON中,bool类型数据表示为true或false。在传递bool类型数据时,我们需要明确如何对其进行处理。 在PHP中,我们需要使用json_encode()函数将bool类型数据转换为JSON字符串,使用json_decod…

    C 2023年5月23日
    00
  • C字符串操作函数的实现详细解析

    C字符串操作函数的实现详细解析 1. 什么是C字符串 C语言中的字符串是由一组字符序列组成,以’\0’(空字符)结尾,其在内存中的存储方式是顺序存储的字符数组。由于C语言本身并没有提供字符串类型,所以需要通过字符数组及一些函数来操作字符串。 2. 常用C字符串操作函数 常用的C字符串操作函数有以下几种: strlen:计算字符串的长度 strcpy:将一个字…

    C 2023年5月23日
    00
  • C++ 类this及返回自身对象的引用方式

    C++ 类this及返回自身对象的引用方式 this指针 每个非静态成员函数都有一个隐含的形参,即指向该类对象的指针。这个指针就是this指针。通过this指针,我们可以访问到类的所有成员变量和成员函数。 在C++中,关键字this用来指向当前对象。this指针是一个隐式参数,它在成员函数内部使用。 返回自身对象的引用 在C++中,返回自身对象的引用是一种常…

    C 2023年5月22日
    00
  • C语言实现24点游戏计算器的示例代码

    C语言实现24点游戏计算器的示例代码 1. 需求分析 本游戏需要实现的功能有:1. 生成指定数量的随机数2. 针对生成的数字进行四则运算3. 检查计算结果是否等于24,并输出计算过程 2. 示范代码 下面是C语言实现24点游戏计算器的示例代码: #include <stdio.h> #include <stdlib.h> #inclu…

    C 2023年5月23日
    00
  • c++中堆栈及创建对象示例代码

    在C++中,堆栈就是一种特定的内存管理方法。通过堆栈,我们可以方便地动态分配内存空间。在C++代码中,堆栈可以使用stack类嵌套类型来定义。下面是一个简单的堆栈示例代码: #include <iostream> #include <stack> using namespace std; int main() { stack<i…

    C 2023年5月22日
    00
  • C++动态内存分配超详细讲解

    C++动态内存分配超详细讲解 什么是动态内存分配 C++中内存的分配共有两种方式:静态内存分配和动态内存分配。其中静态内存分配通常是由编译器完成,而动态内存分配则需要程序员手动完成。动态内存分配可以在程序运行过程中动态地申请和释放内存,从而提高了程序的灵活性。 C++中的动态内存分配 C++中通过new运算符来进行动态内存分配,动态分配的内存需要手动释放,否…

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