二叉树的四种遍历方式:
- 前序遍历:根--左--右
- 中序遍历:左--根--右
- 后序遍历:左--右--根 (发现规律了吗,前中后是相对于根结点而言的)
- 层序遍历:从上往下,从左往右
我画了一个图,应该是写对了,能看懂就应该算是理解了吧
请忽略这些大小不一的圆,本人强迫症最近没心情犯
通过两个遍历顺序构造二叉树:
注意:只能由前序中序和中序后序构造二叉树,不能由前序和后序构造二叉树(必须要有中序)
1、前序和中序
(1)前序遍历的第一个结点是根结点
(2)中序遍历中,根结点的左边为左子树,右边为右子树
(3)根据(1)和(2)的特性设置算法如下
先确定当前节点、左子树、右子树
分别在左子树和右子树中递归
看下图我的详细分解
2、中序和后序
(1)后序遍历的最后一个结点是根结点
(2)中序遍历中,根结点的左边为左子树,右边为右子树
(3)根据(1)和(2)的特性设置算法如下
先确定当前节点、左子树、右子树
分别在左子树和右子树中递归
看下图我的详细分解
接下来就是代码的实现,我先去码代码吧
ok写完啦,我的代码函数包括
- 二叉树的链式存储结构
- 前序遍历创建二叉树
- 前序、中序、后序遍历二叉树
- 前序和中序还原二叉树
- 中序和后序还原二叉树
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #define datatype int//二叉树数据的类型 //二叉树的存储结构 typedef struct BiNode { datatype data;//数据域 struct BiNode* lchild;//左孩子 struct BiNode* rchild;//右孩子 }BiNode,*BiTree; // 先序遍历创建二叉链 //输入:ABC##DE#G##F### (#表示树为空) //可以自己画画这个二叉树是什么样子的,我在文章最后也画了 void CreateBiTree(BiTree& T) { datatype value; scanf("%d", &value); if (value == '#') T = NULL; else { T = new BiNode; T->data = value; CreateBiTree(T->lchild); CreateBiTree(T->rchild); } } //前序遍历二叉树(根-左-右) void PreOrderTraverse(BiTree& T) { if (T) { printf("%d ", T->data); PreOrderTraverse(T->lchild); PreOrderTraverse(T->rchild); } } //中序遍历二叉树(左-根-右) void InOrderTraverse(BiTree& T) { if (T) { InOrderTraverse(T->lchild); printf("%d ", T->data); InOrderTraverse(T->rchild); } } // 后序遍历二叉树(左-右-根) void PostOrderTraverse(BiTree &T) { if (T) { PostOrderTraverse(T->lchild); PostOrderTraverse(T->rchild); printf("%d ", T->data); } } //由先序和中序构建二叉树 //(1)已知先序序列(根、左、右)和中序序列(左、根、右)的遍历顺序 //(2)由先序序列的第一个数据是根节点,可得中序序列中的根节点位置 //(3)由中序根节点位置,可确定左右两边的子序列分别为左子树和右子树序列 void CreateBiTree_Pre_In(BiTree &T, datatype* PreStr, datatype* InStr, int pre1, int pre2, int in1, int in2) { // 创建新的结点 T = (BiTree)malloc(sizeof(BiNode)); // 新结点数据为 先序序列 的第一个数据,即根节点数据 T->data = PreStr[pre1]; // 根据先序第一个元素为根结点元素,寻找中序序列中的根结点位置 int root;//根结点在中序中的位置 for (root = 0; root <= in2; root++) { if (PreStr[pre1] == InStr[root]) { //printf("先序序列根节点(%c)在中序的位置 = %d\n", PreStr[L1], root); break; } } // 判断中序序列中<root>的左边是否存在左子序列 if (root - in1 != 0) { CreateBiTree_Pre_In(T->lchild, PreStr, InStr, pre1 + 1, pre1 + (root - in1), in1, root - 1); } else { T->lchild = NULL; } // 判断中序序列中<root>的右边是否存在右子序列 pre2 - (in2 - root) + 1 if (in2 - root != 0) { CreateBiTree_Pre_In(T->rchild, PreStr, InStr, pre1 + root - in1 + 1, pre2, root + 1, in2); } else { T->rchild = NULL; } } //由中序和后序构建二叉树 void CreateBiTree_In_Post(BiTree& T, datatype* InStr, datatype* PostStr, int in1, int in2, int post1, int post2) { // 创建新的结点 T = (BiTree)malloc(sizeof(BiNode)); // 新结点数据为 后序序列 的第一个数据,即根节点数据 T->data = PostStr[post2]; // 根据后序最后一个元素为根结点元素,寻找中序序列中的根结点位置 int root;//根结点在中序中的位置 for (root = 0; root <= in2; root++) { if (PostStr[post2] == InStr[root]) { //printf("后序序列根节点(%c)在中序的位置 = %d\n", PreStr[L1], root); break; } } // 判断中序序列中<root>的左边是否存在左子序列 if (root - in1 != 0) { CreateBiTree_In_Post(T->lchild, InStr,PostStr, in1, root-1, post1, post1+root -in1- 1); } //其实这个分割区间很好理解的,你们自己理解吧我懒得讲 else //看看别的博主也行 { T->lchild = NULL; } // 判断中序序列中<root>的右边是否存在右子序列 if (in2 - root != 0) { CreateBiTree_In_Post(T->rchild, InStr,PostStr,root+1, in2, post1+root-in1 , post2-1); } else { T->rchild = NULL; } } int main() { BiTree T; int preStr[] = { 1,2,4,7,3,5,6,8 }; int pre1 = 0, pre2 = 7; int inStr[] = { 4,7,2,1,5,3,8,6 }; int in1 = 0, in2 = 7; int postStr[] = { 7,4,2,5,8,6,3,1 }; int post1 = 0, post2 = 7; //测试 //CreateBiTree_Pre_In(T, preStr, inStr, pre1, pre2, in1, in2); //PostOrderTraverse(T); //测试 /* CreateBiTree_In_Post(T, inStr, postStr, in1, in2, post1, post2); PreOrderTraverse(T);*/ }
前序序列 ABC##DE#G##F### 是什么样的二叉树,帮我看一下我画的对不对(orz)