二叉树
二叉树定义
树是由n( n ≥ 0 n\geq0 n≥0)个节点组成的有序集合,二叉树则是有两个节点的树结构,二叉树的每个结点至多只有二棵子树,通常称为“左子树”和“右子树”。如下图:
1
/ \
2 3
/ \ / \
4 5 6 7
二叉树的基本概念
- 树的特点
- 没有父节点的节点称为根节点
- 每个非根节点只有一个父节点
- 除了根节点外,每个节点可以分为多个不相交的节点
- 树的基本术语
- 节点的度:节点拥有子树的数目,如上树节点“2”拥有子节点“4”和“5”,所以它的度为‘2’,节点“4”没有子节点,所以其度为‘0’
- 叶子节点:度为零的节点
- 分支节点:度不为零的节点
- 树的度:树中节点最大的度
- 层次:根节点的层次为“1”,其余节点的层次为其父节点的层次加 1
- 树的高度:树中节点的最大层次
- 二叉树的性质
- 二叉树的第 i i i层上节点的数目最大为 2 i − 1 , i ≥ 1 {2^{i-1},i\geq1} 2i−1,i≥1
- 深度为 k k k的二叉树最大有 2 k − 1 {2^{k}-1} 2k−1个节点, k ≥ 1 k\geq1 k≥1
- 在任意一棵二叉树中,若终端结点的个数为 n 0 n_0 n0,度为2的结点数为 n 2 n_2 n2,则 n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1
- 二叉树的类型
-
满二叉树:高度为 h h h,并且有 2 h − 1 {2^{h}-1} 2h−1个节点的二叉树
1 / \ 2 3 / \ / \ 4 5 6 7 满二叉树 1 / \ 2 3 / / \ 4 6 7 非满二叉树
-
完全二叉树:一棵二叉树中,只有最下面两层结点的度可以小于2,并且最下一层的叶结点集中在靠左的若干位置上。这样的二叉树称为完全二叉树
-
特点:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。显然,一棵满二叉树必定是一棵完全二叉树,而完全二叉树未必是满二叉树
1 / \ 2 3 / \ / \ 4 5 6 7 满二叉树也是完全二叉树 1 / \ 2 3 / \ / 4 5 6 完全二叉树 1 / \ 2 3 / \ \ 4 5 7 不是完全二叉树
-
-
二叉查找树
-
定义:二叉查找树(Binary Search Tree),又被称为二叉搜索树。设 x x x为二叉查找树中的一个结点, x x x节点包含关键字 k e y key key,节点 x x x的 k e y key key值记为 k e y [ x ] key[x] key[x]。如果 y y y是 x x x的左子树中的一个结点,则 k e y [ y ] ≤ k e y [ x ] key[y] \leq key[x] key[y]≤key[x];如果y是x的右子树的一个结点,则 k e y [ y ] ≥ k e y [ x ] key[y] \geq key[x] key[y]≥key[x]
7 / \ / \ 4 9 / \ / \ 2 6 8 10 / \ / 1 3 5
-
性质1: 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值,如节点1<2
-
性质2:任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;如节点3>2
-
性质3:任意节点的左右子树也是二叉查找树
-
性质4:没有键值相等的节点
-
-
其他二叉树:线索二叉树、平衡二叉树在此先不叙述
-
二叉树的存储结构
- 顺序结构:用数组来存储,并且结点的存储位置,也就是数组的下标要能体现结点之间的逻辑关系。顺序存储结构一般只用于完全二叉树
- 链式结构:用链表存储,每个节点包含指向左右两个节点的指针
二叉树的遍历
-
二叉树如下:
7 / \ / \ 4 9 / \ / \ 2 6 8 10 / \ / 1 3 5
-
前序遍历:先访问根节点->左子树->右子树,则上二叉树前序遍历顺序为:7->4->2->1->3->6->5->9->8->10
-
中序遍历:先访问左子树->根节点->右子树,则访问顺序为:1->2->3->4->5->6->7->8->9->10
-
后序遍历:先访问左子树->右子树->根节点,则访问顺序为:1->3->2->5->6->4->8->10->9->7
代码
二叉树的创建
-
例如要创建以下二叉树(非完全二叉树):输入‘#’表示节点为空
4 / \ 1 7 / \ / \ 9 3 a b / \ / 8 6 0
则按照先序顺序输入为:
4->1->9->8->#->#->6->#->#->3->#->#->7->a->0->#->#->#->b->#->#
- 如果选择char型数据,可以直接输入:> 4198##6##3##7a0##b##
//定义包含左右两个子节点指针的结构体 typedef struct node { // int data;//存储int型数据 char data; struct node *Lchild; struct node *Rchild; } BittreeNode;
-
创建:利用递归,先指定一个根节点,然后在此先递归左子树,后递归右子树
//建立二叉树,从根节点x补全为二叉树,先序输入#(或者0)表示空节点,代表子树结尾(*&x:指针的引用,因为后面会修改x的地址)
void CreateBitree(BittreeNode *&x)
{
char c;
// int c;
cin >> c;
//如果输入字符为 # ,则令该节点指针为空
if (c == '#')
{
x = nullptr;
}
// if (c == 0)
// {
// x = nullptr;
// }
// 否则创建一个节点,并把x指向该节点
else
{
x = new BittreeNode;
x->data = c;
CreateBitree(x->Lchild); //递归创建左子树
CreateBitree(x->Rchild);
}
}
前序输出
// 递归 先序遍历,先根后左再右
void preTraverse(BittreeNode *T)
{
if (T)
{
cout << T->data << " ";
preTraverse(T->Lchild);
preTraverse(T->Rchild);
}
}
主函数
int main()
{
BittreeNode *X = new BittreeNode; //指针类型
CreateBitree(X);
cout << "二叉树创建完成!" << endl;
cout << "前序遍历二叉树:" << endl;
preTraverse(X);
cin.get();
return 0;
}