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日

相关文章

  • Java自动拆箱空指针异常的解决

    Java自动拆箱空指针异常通常发生在Java中使用装箱类型与基本数据类型混合运算的过程中。在这种情况下,装箱类型将被自动展开成基本数据类型,这个过程称为自动拆箱。如果装箱类型为null,则在自动拆箱时会抛出NullPointerException。下面是解决Java自动拆箱空指针异常的攻略: 解决方案1:显式进行空值判断 因为空指针异常是由于装箱类型为nul…

    C 2023年5月22日
    00
  • HP TPN-C116笔记本安装win7系统的方法分享

    HP TPN-C116笔记本安装win7系统的方法分享 介绍 在本文中,我们将分享在HP TPN-C116笔记本上安装Windows 7操作系统的步骤。此过程需要一定的计算机技能和经验。在执行本文中的步骤前,请务必备份重要的文件和数据,以免出现数据丢失的情况。 步骤 步骤一:下载Windows 7镜像文件 首先,您需要下载Windows 7系统的ISO镜像文…

    C 2023年5月23日
    00
  • Java IO流之字符流的使用详解

    Java IO流之字符流的使用详解 什么是字符流 字符流是一种能够处理字符数据的流,在字符流中,数据以字符的形式进行读写。 字符流的分类 字符流可以分为两类:输入字符流和输出字符流。其中,输入字符流用于读取字符数据,输出字符流用于写入字符数据。 输入字符流 输出字符流 Reader 抽象类 Writer 抽象类 FileReader 文件字符输入流 File…

    C 2023年5月23日
    00
  • C# XML与Json之间相互转换实例详解

    C# XML与Json之间相互转换实例详解 本文将详细讲解在C#中如何实现XML与Json之间的相互转换。 1. XML转Json实例 首先我们需要引入System.Xml和Newtonsoft.Json两个命名空间,代码如下: using System.Xml; using Newtonsoft.Json; 我们首先需要创建一个XML文档,然后将其转换成J…

    C 2023年5月23日
    00
  • C语言 strftime 格式化显示日期时间的实现

    C语言提供了strftime函数用于将日期时间按照指定格式转换为字符串,下面是使用步骤: 步骤一:头文件引入 #include <time.h> 步骤二:分配时间结构体 struct tm *tm; time_t timep; time(&timep); //获取秒数 tm = localtime(&timep); //转为日期时…

    C 2023年5月22日
    00
  • 如何创建支持FILESTREAM的数据库示例探讨

    下面是如何创建支持FILESTREAM的数据库示例探讨的完整攻略: 前置条件 在开始之前,请确保你已经安装了 SQL Server,并且确定使用的 SQL Server 版本支持 FILESTREAM 特性,同时需要进行以下配置: 选择启用 FILESTREAM,安装 SQL Server 实例时应勾选 FILESTREAM 特性; 配置 FILESTREA…

    C 2023年5月23日
    00
  • Rust处理错误的实现方法

    当我们在编写 Rust 代码时,不可避免地会遇到错误。Rust 的错误处理机制允许我们有效地处理和跟踪错误,以确保程序稳定的运行。 在 Rust 中,错误通常被表示为实现了 std::error::Error trait 的结构体。这个 trait 定义了两个方法,description() 和 cause(),分别用于返回错误信息和错误原因。我们也可以通过…

    C 2023年5月23日
    00
  • 型号为a1526的iphone5c 联通版4g网络怎么开启 联通版iphone5c a1526越狱后破解4g教程

    那么针对这个问题,我将分为两个部分来进行回答。 如何开启型号为a1526的iphone5c联通版4G网络? 首先,您需要确认您的手机是否支持4G网络。型号为a1526的iphone5c 联通版是支持4G网络的,但需满足以下条件: 手机系统为iOS 8.0及以上版本 必须使用联通的USIM卡 在中国大陆地区开通4G网络服务 确认您的手机符合以上条件后,您需要进…

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