一、树相关知识点
1.定义
Ⅰ 有且只有一个称为根的节点
Ⅱ 有若干个互不相交的子树,这些子树本身也是一棵树
2.术语
节点、父节点、子节点、子孙、堂兄弟
深度:从根节点到最底层节点的层数,根节点是第一层
叶子节点:没有子节点的节点
非终端节点:非叶子节点
度:子节点的个数
3.分类
Ⅰ 一般树木:任意一个节点的子节点个数不受限制
Ⅱ 二叉树:任意一个节点的子节点个数最多两个,且子节点位置不可更改
① 一般二叉树
② 满二叉树:每一层节点数都是最大的
③ 完全二叉树:如果只是删除了满二叉树最底层最右边的连续若干节点,这样形成的
树就是完全二叉树。
Ⅲ 森林:n个互不相交的树的集合
4.树的存储
Ⅰ 二叉树的存储
① 连续存储【完全二叉树】
优点:查找某个节点的子节点和父节点很快
缺点:占用内存很大
② 链式存储:
Ⅱ 一般树的存储
① 双亲表示法:求父节点方便
节点编号从根节点开始,如下图ABCDEF对应编号为012345,分别找到各自父节点的编号则为双亲表示法
② 孩子表示法:求子节点方便
在父节点分别存储各自子节点的地址即可
③ 双亲孩子表示法:上述两种方式结合
④ 二叉树表示法:把一个普通树转化成二叉树来存储(设法保证任意一个节点的做指针与指向他的第一个孩子,右指针域指向他的下一个兄弟)
Ⅲ 森林的存储
转化为二叉树,拆分为多个二叉树,二叉树根节点看作森林根节点的兄弟。
5.二叉树遍历
Ⅰ 先序遍历
先访问根节点,再先序访问左子树,再先序访问右子树
Ⅱ 中序遍历
中序遍历左子树,再访问根节点,再中序遍历右子树
Ⅲ 后序遍历
中序遍历左子树,中序遍历右子树,再访问根节点
6.已知两种遍历序列求原始二叉树
Ⅰ 先序+中序 求 后序:
因为先序是先访问根节点,所以以先序为基准找到根节点,中序中以找到的根节点为界,左侧为左子树,右侧为右子树,以此循环还原出原始的二叉树。
例:先序 ABCDEFGH 中序 BDCEAFHG 求后序 DECBHGFA
Ⅱ 中序+后序 求 先序:
后序是后访问根节点,所以将后序倒着看就是根节点,再使用Ⅰ中的方法还原原始的二叉树。
例:中序 BDCEAFHG 后序 DECBHGFA 求先序 ABCDEFGH
7.树的应用
Ⅰ 树是数据库中数据组织的一种重要形式
Ⅱ 操作系统子父进程的关系本身就是一棵树
Ⅲ 面向对象语言中类的继承
Ⅳ 赫夫曼树等
二、c++创建二叉树并遍历
1.先定义节点类:
val保存数据,pL表示指向左子树的指针域,pR表示指向右子树的指针域
class NODE {
public:
int val = 0;
NODE* pL = NULL;
NODE* pR = NULL ;
};
2.创建树类:
具体创建过程在构造函数中使用递归来实现:析构函数需要传入四个参数,arr表示数据存放的数组,需要将数组中的数据一个一个的放入树中,pos表示当前数据所在数组的位置,len表是数组长度,NODE* &p表示指向节点的指针。
该析构函数第一步需要为当前数据在堆区开辟一块节点类型的空间来保存,然后在递归过程中将pos换成pos*2+1(每一层左子节点序号都是父节点序号的2倍+1),用父节点的左指针域在堆区开辟即可生成左子树,右子树也是如此。
class CreatTree :public NODE {
public:
CreatTree(int* arr,int pos,int len,NODE* &p) {
if (pos >= len) {
return;
}
else {
p = new NODE();
p->val = arr[pos];
CreatTree(arr, pos * 2 + 1, len, p->pL);
CreatTree(arr, pos * 2 + 2, len, p->pR);
}
}
};
3.遍历:
通过每个节点的左指针域和右指针域递归实现,只要节点指针域不为空就继续
void Print(NODE* p)
{
if (NULL == p)
return;
cout << " " << p->val;
Print(p->pL);
Print(p->pR);
}
4.测试
void test() {
NODE* p = new NODE();
int arr[10]={1,2,3,4,5,6,7,8,9,10 };
int len = sizeof(arr) / sizeof(int);
CreatTree tree1(arr,0,len,p);
cout << "前序遍历结果为: ";
tree1.Print(p);
return;
}
5.结果
三、全部代码
#include<iostream>
#include<string>
using namespace std;
class NODE {
public:
int val = 0;
NODE* pL = NULL;
NODE* pR = NULL ;
};
class CreatTree :public NODE {
public:
CreatTree(int* arr,int pos,int len,NODE* &p) {
if (pos >= len) {
return;
}
else {
p = new NODE();
p->val = arr[pos];
CreatTree(arr, pos * 2 + 1, len, p->pL);
CreatTree(arr, pos * 2 + 2, len, p->pR);
}
}
void Print(NODE* p)
{
if (NULL == p)
return;
cout << " " << p->val;
Print(p->pL);
Print(p->pR);
}
};
void test() {
NODE* p = new NODE();
int arr[10]={1,2,3,4,5,6,7,8,9,10 };
int len = sizeof(arr) / sizeof(int);
CreatTree tree1(arr,0,len,p);
cout << "前序遍历结果为: ";
tree1.Print(p);
return;
}
void main() {
test();
return;
}