ToB企服应用市场:ToB评测及商务社交产业平台

标题: 栈和相关算法 [打印本页]

作者: 吴旭华    时间: 2024-4-9 14:59
标题: 栈和相关算法


栈是一种抽象数据结构(ADT),其主要特性是后进先出LIFO(Last in First out)
可以用数组、链表实现,本质就是对一个列表进行后进先出的操作
栈的操作主要有push入栈、pop出栈、isEmpty判空、getTop获取栈顶元素
数组实现

首先进行最基本的数据结构和操作定义:
  1. //栈空条件
  2. top = -1
  3. //栈满条件
  4. top >= MAX - 1
复制代码
在stack.h头文件中定义栈的结构体和声明一些操作函数。一个栈由存放数据的数组data和栈顶指针top组成
  1. /*stack.h*/
  2. #ifndef __STACK_H__
  3. #define __STACK_H__
  4. #define MAX 10
  5. typedef struct stackNode {
  6.     int data[MAX];
  7.     int top;
  8. }Stack;
  9. int initStack(Stack* S);        //初始化栈
  10. int Push(Stack* S, int value);        //入栈
  11. int Pop(Stack* S);        //出栈
  12. int isEmpty(Stack S);        //判空
  13. int getTop(Stack S);        //获取栈顶元素
  14. #endif
  15. //为了防止重复引用一个头文件,使用预编译宏规范
复制代码
操作实现代码:
  1. /*stack.c*/
  2. #include <stdio.h>
  3. #include "stack.h"
  4. int initStack(Stack* S) {
  5.     S->top = -1;
  6.     return 1;
  7. }
  8. int isEmpty(Stack S) {
  9.     if(S.top == -1)
  10.     {
  11.         printf("stack is null\n");
  12.         return 1;
  13.     }
  14.     return 0;
  15. }
  16. /*
  17. 入栈时判断栈是否已满,由于本次实现栈顶指针指向的是最后一个入栈的元素,因此判断条件为top <= MAX - 1
  18. 满足入栈条件时则加入data数组,并top+1
  19. */
  20. int Push(Stack* S, int value) {
  21.     if(S->top >= MAX - 1)
  22.         return 0;
  23.     S->data[++S->top] = value;
  24.     return 1;
  25. }
  26. /*
  27. 出栈时先判断栈是否为空,接着下标减1
  28. */
  29. int Pop(Stack* S) {
  30.     if(isEmpty(*S))
  31.     {
  32.         printf("stack null\n");
  33.         return 0;
  34.     }
  35.     S->top--;
  36.     return 1;
  37. }
  38. int getTop(Stack S) {
  39.     if(isEmpty(S))
  40.         return 0;
  41.     return S.data[S.top];
  42. }
  43. void Print(Stack S) {
  44.     int i = 0;
  45.     if(isEmpty(S))
  46.     {
  47.         printf("stack null\n");
  48.         return;
  49.     }
  50.     for(;i <= S.top;i++)
  51.         printf("%d\t", S.data[i]);
  52.     printf("\n");
  53. }
  54. //测试代码
  55. int main() {
  56.     Stack S;
  57.     initStack(&S);
  58.     Push(&S, 1);
  59.     Push(&S, 2);
  60.     Push(&S, 3);
  61.     Push(&S, 4);
  62.     Push(&S, 5);
  63.     Push(&S, 6);
  64.     Push(&S, 7);
  65.     Push(&S, 8);
  66.     Push(&S, 9);
  67.     Push(&S, 10);
  68.     Push(&S, 11);
  69.     Print(S);
  70.     printf("%d\n", getTop(S));
  71.     return 0;
  72. }
复制代码
表达式计算

1.中缀表达式转后缀表达式

思路:从左到右遍历一次中缀表达式,按下面的算法进行转换,将中缀表达式转换为后缀表达式
算法:
(1)字符为操作数
加入后缀表达式,在这还需加入一些逻辑来获取大于等于10的数字或者小数,比如循环读取连续的数字组成一个完整的数字,然后用空格或其他操作数分隔
(2)字符为左括号
直接入栈
(3)字符为右括号
连续出栈,并将出栈元素加入后缀表达式,直到栈顶元素为左括号,将左括号出栈但不加入后缀表达式
(4)字符为运算符
若栈空,直接入栈。
若栈非空,判断运算符优先级是否高于栈顶运算符,高于则入栈,否则连续出栈,直到该运算符优先级高于栈顶运算符或栈空
(5)遍历完中缀表达式后,还需判断栈是否非空,非空则将全部元素出栈,加入后缀表达式
  1. void Reserse(Link head) {
  2.     Link temp = head;
  3.    
  4.     if(!head) return;
  5.     //为了方便演示,直接使用的c++的标准库中的栈定义
  6.     stack<Link> S;
  7.    
  8.     //首先将链表所有节点入栈
  9.     while(temp != NULL) {
  10.         S.push(temp);
  11.         temp = temp->next;
  12.     }
  13.    
  14.     //获取栈顶节点,最后一个入栈的即为新的链表头节点
  15.     temp = S.top();
  16.     S.pop();
  17.     head = temp;        //此时head和temp都指向新链表的第一个节点
  18.    
  19.     while(!S.empty()) {
  20.         //当栈非空时,将temp->next指针指向当前栈顶的节点
  21.         //出栈一次
  22.         //更新temp指针,使其指向刚反转的新节点
  23.         temp->next = S.top();
  24.         S.pop();
  25.         temp = temp->next;
  26.         }
  27.     //最后将最后一个节点的next置为NULL
  28.     temp->next = NULL;
  29. }
复制代码
2.后缀表达式计算

算法:
(1)字符为操作数
直接入栈
(2)字符为运算符
连续出栈两次,与运算符进行运算,结果入栈
(3)重复以上步骤直到遍历完后缀表达式
  1. string InfixToPostfix(string expression) {
  2.     stack<char> S;
  3.     string postfix = "";
  4.     for(int i = 0;i < expression.length();i++) {
  5.         if(expression[i] == ' ' || expression[i] == ',') continue;
  6.         
  7.         if(IsOperator(expression[i])) { //字符=运算符
  8.             while(!S.empty() && '(' != S.top() && !HigherPrecedence(S.top(), expression[i])) {
  9.                 //当栈非空,且操作符优先级未大于栈顶元素时,出栈并加入postfix
  10.                 postfix += S.top();
  11.                 S.pop();
  12.             }
  13.             S.push(expression[i]);
  14.         }else if(IsOperand(expression[i])) {    //字符=操作数
  15.             while(IsOperand(expression[i])) {
  16.                 postfix += expression[i];
  17.                 i += 1;
  18.             }
  19.             postfix += ' ';
  20.             i--;
  21.         }else if('(' == expression[i]) {    //字符=左括号
  22.             S.push(expression[i]);
  23.         }else if(')' == expression[i]) {
  24.             while (!S.empty() && S.top() != '(')    //字符=右括号
  25.             {
  26.                 postfix += S.top();
  27.                 S.pop();
  28.             }
  29.             S.pop();
  30.         }
  31.     }
  32.             //将剩余元素出栈
  33.     while(!S.empty()) {
  34.         postfix += S.top();
  35.         S.pop();
  36.     }
  37.     return postfix;
  38. }
复制代码
3.完整代码

[code]#include #include #include using namespace std;//计算后缀表达式函数int EvaluetionPostfix(string expression);//二元表达式计算int PerformOperation(char operation, int operand1, int operand2);//中缀转后缀string InfixToPostfix(string expression);//运算符判断bool IsOperator(char c);//操作数判断bool IsOperand(char c);//获取运算符权重int GetOperatorWeight(char op);//运算符优先级比较bool HigherPrecedence(char op1, char op2);int main() {    string expression = "";    cout




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4