二叉树和栈构建的表达式树

这是另外另一个根据后缀表达式进行翻译的实现方法,主要利用栈和二叉树

利用的自定义头文件如下

1.二叉树基本定义

btree.h

 1 #ifndef _btree_h_
 2 #define _btree_h_
 3
 4 #include "iostream"
 5 #include "stdlib.h"
 6
 7 typedef struct _btree_
 8 {
 9     char data;
10     struct _btree_ *leftTree;
11     struct _btree_ *rightTree;
12 }BTree;
13
14 /*初始化根节点,返回的是根节点地址*/
15 BTree*
16 initRoot(const char &data)
17 {
18     BTree *root = (BTree *)malloc(sizeof(BTree));
19     root->data = data;
20     root->leftTree = nullptr;
21     root->rightTree = nullptr;
22     return root;
23 }
24
25 /*打印出所有节点的数据*/
26 void
27 printOut(BTree *root)
28 {
29     if (root->leftTree)
30     {
31         printOut(root->leftTree);
32     }
33
34     if (root)
35         std::cout << root->data << std::endl;
36     else
37         return;
38
39     if (root->rightTree)
40     {
41         printOut(root->rightTree);
42     }
43 }
44
45 #endif //btree_h

使用输出的方式是中序遍历。

2.栈的定义和实现

stack.h

 1 #ifndef _stack_h_
 2 #define _stack_h_
 3
 4 #include "iostream"
 5 #include "stdlib.h"
 6 #include "btree.h"
 7
 8 #define  minSize 5
 9 #define  emptyStack -1
10
11 #define log(s); std::cout<<s<<std::endl;
12
13 typedef struct _stack_
14 {
15     int capacity;
16     int topOfStack;
17     BTree* *Array;//注意数组保存的是指向BTree的指针,Array是指向数组的指针
18 }stack;
19
20 stack *createStack(int maxSize)
21 {
22     stack *s;
23     if (maxSize < minSize)
24     {
25         log("Stack size is too small");
26     }
27     s = (stack *)malloc(sizeof(stack));
28     s->Array = (BTree **)malloc(sizeof(BTree *) * maxSize);
29     s->capacity = maxSize;
30     s->topOfStack = emptyStack;/*初始化为空栈*/
31     return s;
32 }
33
34 int isFull(stack *s)/*检测是否为满栈*/
35 {
36     if (s == nullptr)
37     {
38         log("the stack has not inital");
39         return 1;
40     }
41     return s->topOfStack == s->capacity;
42 }
43
44 int isEmpty(stack *s)/*是否为空栈*/
45 {
46     if (s == nullptr)
47     {
48         log("the stack has not inital");
49         return 1;
50     }
51     return s->topOfStack == emptyStack;
52 }
53
54 void push(stack *s, BTree *&data)/*压栈*/ /*此处data是对BTree类型的引用*/
55 {
56     if (isFull(s))
57     {
58         log("Full of Stack");
59         return;
60     }
61     ++s->topOfStack;
62     s->Array[s->topOfStack] = data;
63 }
64
65 void pop(stack *s)/*弹出栈*/
66 {
67     if (isEmpty(s))
68     {
69         log("Out of Stack");
70         return;
71     }
72     --s->topOfStack;
73 }
74
75 BTree* top(stack *s)/*访问栈顶元素*/
76 {
77     if (isEmpty(s))
78     {
79         std::cout << "Out of Stack,Code is ";
80         return nullptr;
81     }
82     return s->Array[s->topOfStack];
83 }
84
85 void makeEmpty(stack *&s)/*置空栈*/
86 {
87     free(s->Array);
88     free(s);
89     s = nullptr;
90 }
91
92 #endif /*stack_h*/

因为向根节点的左右节点添加数据是在主函数中实现的,因此不在树定义中再保留实现;

下面是主函数

main.cpp

 1 #include "btree.h"
 2 #include "stack.h"
 3 #include "iostream"
 4 #include "stdlib.h"
 5
 6 int isSymbal(const char &c)
 7 {
 8     if (c == ‘+‘ || c == ‘-‘ || c == ‘/‘ || c == ‘*‘)
 9         return 1;
10     else
11         return 0;
12 }
13
14 int main(void)
15 {
16     stack *s = createStack(20);
17     BTree *new_b = nullptr;
18     char c;
19     while (std::cin >> c)
20     {
21         if (c == ‘=‘)
22             break;
23         new_b = initRoot(c);
24         if (!isSymbal(c))//如果读入的不是符号,将枝叶的地址入栈
25             push(s, new_b);
26         else//如果读入的是符号
27         {
28             new_b->rightTree = top(s);//将栈顶的地址赋给右子树,后弹栈,将新栈顶赋给左子树,再弹栈,将新生成的根节点入栈
29             pop(s);
30             new_b->leftTree = top(s);
31             pop(s);
32             push(s, new_b);
33         }
34     }
35     printOut(top(s));
36     free(new_b);
37     makeEmpty(s);
38     system("pause");
39     return 0;
40 }

注意使用等号结束输入,为了简便,默认输入的后缀表达式是完全正确的。

使用示例:

上述代码未经严格测试,如果读者发现问题希望能不吝赐教,不胜感激。

以上。

时间: 2024-11-10 00:37:50

二叉树和栈构建的表达式树的相关文章

07_2.二叉数,二叉树的简单应用:表达式树

""" 二叉树的list实现 """ def BinTree(data, left=None, right=None): """ 二叉树 :param data: 根结点的元素 :param left: 左子树元素 :param right: 右子树元素 :return: """ return [data, left, right] def is_empty_BinTree(btree)

关于Expression表达式树的拼接

最近在做项目中遇到一个问题,需求是这样的: 我要对已经存在的用户进行检索,可以根据用户的id 或者用户名其中的一部分字符来检索出来,这样就出现了三种情况 只有id,只有用户名中一部字符,或者全部都有. 我们用的MVC+EF5.0的框架,在BLL层进行查询的 时候需要构建lambda表达式来作为查询条件,但是,我们怎么来构建lambda来确定查询的条件呢?我们知道Express<Func<T,bool>>这样的一个参数可以是lambda表达式,但是这里的按条件拼接式不能使用委托链的形

Lambda表达式和表达式树

在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在不牺牲可读性的前提下,进一步简化了委托. LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态.这些操作表示了各种关于数据的逻辑,例如数据筛选,数据排序等等.通常这些操作都是用委托来表示.Lambda表达式是对LINQ数据操作的一种符合语言习惯的表示方式. Lambda表达式不仅可以用来创

16.C#初见Lambda表达式及表达式树(九章9.1-9.3)

在说明Lambda相关知识前,我们需要了解Lambda表达式常用于LINQ,那么我们来聊下LINQ. LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态.这些操作表示了各种关于数据的逻辑:如何过滤.如何排序以及如何将不同的数据源连接在一起,等等.执行委托只是LINQ的众多能力之一.为了富有效率地使用数据库和其他查询引擎,我们需要以一种不同的方式来表示管道中的各个操作.这种不同的方式就可以使用Lambda表达式来表现.下面分别使用委托(使用匿名函数)和Lambda表达式来作出同样的事情

Lambda表达式和Lambda表达式树

LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态. 为了富有效率的使用数据库和其他查询引擎,我们需要一种不同的方式表示管道中的各个操作.即把代码当作可在编程中进行检查的数据. Lambda表达式不仅可以用他们创建委托实例,而且C#编译器也能将他们转换成表达式树——用于表示Lambda表达式逻辑的一种数据结构.简言之——Lambda表达式用符号语言习惯的方法来表示LINQ数据管线中的操作. 作为委托的Lambda表达式 Lambda有特殊转换规则:表达式的类型本身并非委托类型,但它可

C#中的Lambda表达式和表达式树

在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在不牺牲可读性的前提下,进一步简化了委托. LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态.这些操作表示了各种关于数据的逻辑,例如数据筛选,数据排序等等.通常这些操作都是用委托来表示.Lambda表达式是对LINQ数据操作的一种符合语言习惯的表示方式. Lambda表达式不仅可以用来创

C#复习笔记(4)--C#3:革新写代码的方式(Lambda表达式和表达式树)

Lambda表达式和表达式树 先放一张委托转换的进化图 看一看到lambda简化了委托的使用. lambda可以隐式的转换成委托或者表达式树.转换成委托的话如下面的代码: Func<string, int> getLength = s => s.Length; 转换成表达式树的话是下面的代码: Expression<Func<string, int>> getLength = s => s.Length; 委托方面的东西前面都做了详细的介绍.我们主要学习表达

【C#复习总结】细说表达式树

1 前言 系类1:细说委托 系类2:细说匿名方法 系列3:细说Lambda表达式 系列4:细说泛型委托 系列5:细说表达式树 系列6:细说事件 涛声依旧,再续前言,接着用大佬的文章作为开头. 表达式树其实与委托已经没什么关系了,非要扯上关系,那就这么说吧,表达式树是存放委托的容器.如果非要说的更专业一些,表达式树是存取Lambda表达式的一种数据结构.要用Lambda表达式的时候,直接从表达式中获取出来,Compile()就可以直接用了.如下代码: using System; using Sys

[转] 利用表达式树构建委托改善反射性能

最近搞一个系统时由于在比较关键地方用到反射了,所以要关注了一下反射的性能问题.搜索一下,不难搜到老赵的这篇文章,下面是一些杂乱的笔记.(建议先看老赵的文章) .Net4.0反射性能改善 看老赵的文章,老赵得到的结果是这样的: 1 00:00:00.0125539 (Directly invoke) 2 00:00:04.5349626 (Reflection invoke) 3 00:00:00.0322555 (Dynamic executor) 而我把代码搞下来自己运行得到这样的结果: 1