当前位置: 首页 > news >正文

怎么描述网站主页做的好全球网站排名前100

怎么描述网站主页做的好,全球网站排名前100,重庆seo公司,沧浪企业建设网站公司3、前缀、中缀和后缀表达式 计算机是从左到右处理数据的,类似(A (B * C))这样的完全括号表达式,计算机如何跳到内部括号计算乘法,然后跳到外部括号计算加法呢? 一种直观的方法是将运算符移到操作数外,分离运算符和操…
3、前缀、中缀和后缀表达式

计算机是从左到右处理数据的,类似(A + (B * C))这样的完全括号表达式,计算机如何跳到内部括号计算乘法,然后跳到外部括号计算加法呢?

一种直观的方法是将运算符移到操作数外,分离运算符和操作数。计算时先取运算符再取操作数,计算结果则作为当前值参与后面的运算,直到完成对整个表达式的计算。

可将中缀表达式A + B中的“+”移出来,既可以放前面,也可以放后面,得到的将是+ A B和A B +。这两种不同的表达式分别被称为前缀表达式和后缀表达式。

前缀表达式要求所有运算符在处理的两个操作数之前,后缀表达式则要求所有运算符在相应的操作数之后。

在这里插入图片描述

前缀、中缀和后缀表达式

在这里插入图片描述

将中缀表达式转换为前缀和后缀表达式

这里规定:运算符只有+ - * /,操作数则被定义为任何大写字母A~Z或数字0~9。

代码如下:

#[derive(Debug)]
struct Stack<T> {size: usize,  // 栈大小data: Vec<T>, // 栈数据
}impl<T> Stack<T> {// 初始化空栈fn new() -> Self {Self {size: 0,data: Vec::new(), // 以 Vec 为低层}}fn is_empty(&self) -> bool {0 == self.size}fn len(&self) -> usize {self.size}// 清空栈fn clear(&mut self) {self.size = 0;self.data.clear();}// 将数据保存在 Vec 的末尾fn push(&mut self, val: T) {self.data.push(val);self.size += 1;}// 将栈顶减 1 后,弹出数据fn pop(&mut self) -> Option<T> {if 0 == self.size {return None;};self.size -= 1;self.data.pop()}// 返回栈顶数据引用和可变引用fn peek(&self) -> Option<&T> {if 0 == self.size {return None;}self.data.get(self.size - 1)}fn peek_mut(&mut self) -> Option<&mut T> {if 0 == self.size {return None;}self.data.get_mut(self.size - 1)}// 以下是为栈实现的迭代功能// into_iter: 栈改变,成为迭代器// iter: 栈不变,得到不可变迭代器// iter_mut:栈不变,得到可变迭代器fn into_iter(self) -> IntoIter<T> {// into_iter()方法获取了一个迭代器,然后进行迭代IntoIter(self)}fn iter(&self) -> Iter<T> {let mut iterator = Iter { stack: Vec::new() };for item in self.data.iter() {iterator.stack.push(item);}iterator}fn iter_mut(&mut self) -> IterMut<T> {let mut iterator = IterMut { stack: Vec::new() };for item in self.data.iter_mut() {iterator.stack.push(item);}iterator}
}
// 实现三种迭代功能
struct IntoIter<T>(Stack<T>);
// Iterator 是 Rust 的迭代器 迭代器(iterator)负责遍历序列中的每一项和决定序列何时结束的逻辑。当使用迭代器时,我们无需重新实现这些逻辑。
impl<T: Clone> Iterator for IntoIter<T> {// into_iter()方法获取了一个迭代器,然后进行迭代。type Item = T;fn next(&mut self) -> Option<Self::Item> {// 迭代器之所以成为迭代器,是因为实现了Iterator trait。要实现该特征,最主要的就是实现其中的 next 方法,该方法控制如何从集合中取值,最终返回值的类型是关联类型 Item。if !self.0.is_empty() {self.0.size -= 1;self.0.data.pop()} else {None}}
}
// 'a 生命周期标识 用于帮助编译器检查引用的有效性,避免悬垂引用和使用已被释放的内存。
// 从所有权的角度来理解,就是它可以避免因为Copy或者clone的造成的不必要开销
struct Iter<'a, T: 'a> {stack: Vec<&'a T>, // 'a 被用在了传参类型 T 上
}
impl<'a, T> Iterator for Iter<'a, T> {type Item = &'a T; // 生命周期标识只作用于引用上,且放在&符号之后 如这里的 &'a Tfn next(&mut self) -> Option<Self::Item> {self.stack.pop()}
}struct IterMut<'a, T: 'a> {stack: Vec<&'a mut T>,
}
impl<'a, T> Iterator for IterMut<'a, T> {type Item = &'a mut T;fn next(&mut self) -> Option<Self::Item> {self.stack.pop()}
}use std::collections::HashMap;fn main() {let infix = "( A + B ) * ( C + D )";let postfix = infix_to_postfix(infix);match postfix {Some(val) => {println!("{infix} -> {val}");},None => {println!("{infix} is not a correct infix string");}}let infix = "( 1 + 2 ) * 3";let postfix = infix_to_postfix(infix);match postfix {Some(val) => {println!("{infix} -> {val}");},None => {println!("{infix} is not a correct infix string");}}
}// 中缀转后缀
fn infix_to_postfix(infix:&str) -> Option<String> {// 括号匹配检验if !par_checker3(infix) { return None;};// 设置各个运算符的优先级let mut prec = HashMap::new();//  HashMap<K, V> 类型储存了一个键类型 K 对应一个值类型 V 的映射。它通过一个 哈希函数(hashing function)来实现映射,决定如何将键和值放入内存中。prec.insert("(", 1);prec.insert(")", 1);prec.insert("+", 2);prec.insert("-", 2);prec.insert("*", 3);prec.insert("/", 3);// ops 用于保存运算符, postfix 用于保存后缀表达式let mut ops = Stack::new(); // 保存运算符let mut postfix = Vec::new(); // 保存后缀表达式for token in infix.split_whitespace() { // 按空格分割字符串切片// 将数字 0 - 9 和 大写字母 A - Z 入栈if ("A" <= token && token <= "Z") || ("0" <= token && token <= "9") {postfix.push(token); // 如果是字符或数字就存入 postfix}else if "(" == token {// 遇到开始符号,将运算符入栈ops.push(token); // 如果是开始括号运算符 ( 就存储 ops}else if ")" == token {// 比如 infix 为 (1 + 2) * 3,此时 postfix 类似为 [1,2],ops 类似为 [(,+]  // 遇到结束符号,将操作数入栈let mut top = ops.pop().unwrap(); // 如果是结束括号运算符 就去 ops 中匹配 对应的 开始 括号运算符 此时 ops 类似为 [(],因为 + 已经被 pop 出去了while top !="(" { // 如果匹配到的不是 ( 开始括号运算符,则说明是 + - * / 运算符 此时 top 比如为 +postfix.push(top); // 将 + - * / 运算符入栈至 postfix,比如 infix 为 (1 + 2) * 3,此时 postfix 类似为 [1,2,+]top = ops.pop().unwrap(); // 此时 ops 类似为 [],top = "(",到这里 while 就结束了 因为 top = "("}// 到这里时 ops 类似为 [],infix 为 (1 + 2) * 3 中的 () 就被丢弃了,而 postfix 已经为,如:[1,2,+]}else {// + - * / 运算符// 比较运算符的优先级以决定是否将运算符添加到 postfix 列表中while (!ops.is_empty()) && (prec[ops.peek().unwrap()] >= prec[token]) {postfix.push(ops.pop().unwrap()); // 比如 peek 是 *,而 当前 token 是 + ,则直接把 * 放入 postfix }ops.push(token); // 此时将 * push 了进去// 此时 ops 如 [*]}}// 比如:infix 为 (1 + 2) * 3//  此时 ops 如 [*]// 此时 postfix 如 [1,2,+,3]// 将剩下的操作数入栈while !ops.is_empty() {postfix.push(ops.pop().unwrap()); // 此时 postfix 如 [1,2,+,3,*]}// 出栈并组成字符串let mut postfix_str = "".to_string();for c in postfix {postfix_str += &c.to_string();postfix_str += " "; // 加上空格}Some(postfix_str)
}// 同时检测多种开始符号和结束符号是否匹配
fn par_match(open: char, close: char) -> bool {let opens = "([{";let closers = ")]}";opens.find(open) == closers.find(close)
}
// 基于栈的符号匹配
fn par_checker3(par: &str) -> bool {let mut char_list = Vec::new();for c in par.chars() {char_list.push(c);}let mut index = 0;let mut balance = true;let mut stack = Stack::new();while index < char_list.len() && balance {let c = char_list[index];// 将开始符号入栈if '(' == c || '[' == c || '{' == c {stack.push(c);}// 如果是结束符号,则判断是否平衡if ')' == c || ']' == c || '}' == c {if stack.is_empty() {balance = false;} else {let top = stack.pop().unwrap();if !par_match(top, c) {balance = false;}}}// 非括号字符直接跳过index += 1;}balance && stack.is_empty()
}

运行结果:

在这里插入图片描述

http://www.khdw.cn/news/53522.html

相关文章:

  • 浪起科技做的网站怎么样网络推广 公司 200个网站
  • dw网站制作流程百度网页版主页
  • 衡水如何做企业网站竞价推广营销
  • 私服网站去哪买空间啊公司网站域名续费一年多少钱
  • wordpress默认登录地址修改优化设计七年级下册语文答案
  • 泉州网站建站公司网站搜索引擎推广
  • 软件开发和网站开发区别上海自动seo
  • 如何做古诗词网站百度收录入口
  • wordpress图片压缩软件旺道优化软件
  • 一个空间可以做多个网站吗网络软营销
  • 济南网站制作0531soso什么软件可以刷网站排名
  • 网站建设中国站需求分析报告个人seo外包
  • 怎么做加密网站网络营销的主要传播渠道是
  • wordpress支持PHP吗seo公司是什么意思
  • 青岛做网站多少钱站长素材免费下载
  • 宜昌营销型网站建设郑州百度快照优化排名
  • 中天建设集团有限公司第九建设公司优化seo方案
  • seo网站推广推荐人工智能的关键词
  • 创建自己的网站需要多少钱广州百度推广客服电话多少
  • 浏阳做网站报价网络服务器配置与管理
  • 做网站密云网店怎么推广和宣传
  • 高清图片素材网站免费百度收录规则2022
  • 网站有必要使用伪静态么百度客服联系方式
  • 郑州网站制作汉狮网站优化的方法有哪些
  • 衡水学校网站建设化妆培训
  • 学会了php的语法怎么做网站百度seo推广计划类型包含
  • 可以做免费的网站吗seo网络推广优化教程
  • 网站开发留学镇江网站建设方案
  • 网站便民服务平台怎么做免费web服务器网站
  • seo推广话术廊坊seo排名收费