递归法建立,根据书上的代码做了一些改变,但是算法不变。
// 根据前序序列创建二叉树 template <class T> //tree是要建立树的结点,pre是前序序列 void BinaryTree<T>::CreateBinTree1(BinTNode<T>*& tree, char* pre) { T tmp; tmp = *pre; for (int i = 0; i < strlen(pre); i++) //读取完字符,就把所有字符前移一位,覆盖掉第一个字符 pre[i] = pre[i + 1]; //以确保后面每次调用第一个字符不与之前重复 if (tmp != tag) //正向写入树中 { tree = new BinTNode<T>(tmp); CreateBinTree1(tree->lchild, pre); CreateBinTree1(tree->rchild, pre); } else tree = NULL; }错误的方法: 很多人会以为只需要调①中间建立的三步的顺序就行了,但是这样是错误的,因为后序序列为“左右根”,建立第一个一定读取“#”,也就是空结点,程序直接把树置空了,就无法再进行下去了。 正确的方法: 我们把用户输入的后序序列反向读取,这样就由“左右根”的顺序变为了“根右左”,这样就解决了读取的第一个元素直接将树置空的问题。
有了思路后,就可以这样建立:
// 根据后序序列创建二叉树 template <class T> //tree是要建立树的结点,post是后序序列 void BinaryTree<T>::CreateBinTree2(BinTNode<T>*& tree, char* post) { T tmp; int l = strlen(post) - 1; tmp = post[l]; post[l] = '\0'; //用完就封口,使得下一次l的值变为前一位 if (tmp != tag) //反向写入树中 { tree = new BinTNode<T>(tmp); CreateBinTree2(tree->rchild,post); CreateBinTree2(tree->lchild,post); } else tree = NULL; }前序:根左右 中序:左根右 根据序列的差异我们可以得出以下步骤: 1.找前序序列第一个结点,它是这棵树的根节点。 2.在中序中找这个结点,它左边就是左子树中序序列,右边就是右子树中序序列。 3.计算中序中确定的左子树结点个数n,在前序中除了根节点外的结点中取前n个,就是左子树的前序序列,剩余就是右子树前序序列。 4.由得到的左子树和右子树的前序、中序序列继续递归。当左右子树为空时递归结束。 举个例子: 前序序列:ABDC 中序序列:BDAC 由前序序列知,A为根节点。 在中序序列中查找A,找到它左边BD就是左子树中序序列,右边C就是右子树中序序列。 根据左子树中序序列BD的结点个数2,在前序序列除了根节点外的结点中找到前2个:BD就是左子树的前序序列,剩余C就是右子树的前序序列。 继续递归,左子树前序序列第一个是B,那么B就是左子树根节点。 在左子树中序序列BD中找到B,其左边没有结点,那么B的左子树为空。其右子树中序序列为:D。 在前序序列BD中找,除了根节点B以外的前0个节点是左子树前序序列,此处即左子树为空。剩余D就是右子树前序序列。 A的右子树为C。 这样就解得了二叉树的结构。 接下来我们只需要翻译以上算法即可。 代码如下:
// 根据前序+中序序列创建二叉树 template <class T> //tree是要建立树的结点,pre是前序序列,in是中序序列,n是序列长度 void BinaryTree<T>::CreateBinTree3(BinTNode<T>*& tree, char* pre, char* in, int n) { if (n <= 0) return;//递归结束条件,序列长度小于等于0 T tmp = *pre;//前序第一个节点必为根节点 tree = new BinTNode<T>(tmp); int m = 0; for (; m < n; m++)//找到根节点在中序中的下标 { if (tmp == in[m]) break; } //根据下标m分割序列,得到子树序列 CreateBinTree3(tree->lchild, pre + 1, in, m); CreateBinTree3(tree->rchild, pre + m + 1, in + m + 1, n - m - 1); }算法同③,只是获取根节点的方式从前序第一个变成了后序最后一个。 代码如下:
// 根据中序+后序序列创建二叉树 template <class T> //tree是要建立树的结点,in是中序序列,post是后序序列,n是序列长度 void BinaryTree<T>::CreateBinTree4(BinTNode<T>*& tree, char* in, char* post, int n) { if (n <= 0) return;//递归结束条件,序列长度小于等于0 T tmp = post[n - 1];//后序最后一个节点必为根节点 tree = new BinTNode<T>(tmp); int m = 0; for (; m < n; m++)//获得根节点在中序的下标 { if (tmp == in[m]) break; } //根据下标m分割序列,得到子树序列 CreateBinTree4(tree->lchild, in, post, m); CreateBinTree4(tree->rchild, in + m + 1, post + m, n - m - 1); }以上是我本人数据结构课程最近的一次作业所要求实现的功能,希望对大家有所帮助。 本人水平有限,如有出错之处,欢迎指正,谢谢大家。 最后一次修订:2020年10月29日.