树
节点的分类:
节点拥有的子树数称为:节点的度 (degree),度为0的节点称为叶节点(leaf)或终端节点,度不为0的节点称为非终端节点或分支节点。树的度是树内各节点度的最大值。 在树中没有孩子的节点称为叶子。
二叉树的性质
每个节点最多有两个子树。 第i层有2^(i-1)个节点,深度为k的二叉树最多有2 ^(k)-1. 度为2的节点数比叶子数多1。例如下图2中的数量关系为:1号+2号+3号+4号 = 8号+9号+10号。 满二叉树:每个节点的度为2。 一棵二叉树有n个元素,n>0, 它有n-1条边。 一棵二叉树的高度为h, h≥0, 它最少有h个元素,最多有2^n-1个元素。 一棵二叉树有n个元素, n>0,它的高度最大为n,最小高度为[log2 (n+ 1)](向上取整)。 设完全二叉树的一元素其编号为i, 1≤i≤n。有以下关系成立: 1 .如果i=1, 则该元素为二叉树的根。若i>1, 则其父节点的编号为[i/2」。 2 .如果2i>n, 则该元素无左孩子。否则,其左孩子的编号为2i。 3 .如果2i+1>n, 则该元素无右孩子。否则,其右孩子的编号为2i+1。
完全二叉树:第k-1层和满二叉树一样,最后一层的叶子节点尽量靠左。 具有n个节点的完全二叉树的深度为:[log2(n)]+1。 如果对一棵有 n个结点的完全二叉树的结点按层序编号,对任一结点i (1<i≤n) 1.如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是结点[i/2」。 2.如果2i>n,则结点i无左孩子(结点i为叶子结点);否则其左孩子是结点 3.如果2i+1>n,则结点i无右孩子;否则其右孩子是结点2i+1。
遍历二叉树
先序遍历
先遍历根节点,再遍历左子树,再遍历右子树。
void show_tree ( binary_tree* b1)
{
if ( b1 == nullptr )
{
printf ( "本分支结束!!!\n\n" ) ;
return ;
}
printf ( "root_data = %d\n\n" , * ( int * ) b1-> user_data) ;
show_tree ( b1-> left) ;
show_tree ( b1-> right) ;
}
中序遍历
先遍历左子树,再遍历根,再遍历右子树。
void show_tree ( binary_tree* b1)
{
if ( b1 == nullptr )
{
printf ( "本分支结束!!!\n\n" ) ;
return ;
}
show_tree ( b1-> left) ;
printf ( "root_data = %d\n\n" , * ( int * ) b1-> user_data) ;
show_tree ( b1-> right) ;
}
后序遍历
先遍历左子树,再遍历右子树,再遍历根。
void show_tree ( binary_tree* b1)
{
if ( b1 == nullptr )
{
printf ( "本分支结束!!!\n\n" ) ;
return ;
}
show_tree ( b1-> left) ;
show_tree ( b1-> right) ;
printf ( "root_data = %d\n\n" , * ( int * ) b1-> user_data) ;
}
三种遍历方式总结
如果去掉printf,从递归角度看,这三种算法是完全相同的,即访问路径相同。
例子:
# include <stdio.h>
# include <malloc.h>
# include <string.h>
# include <stdlib.h>
# include <windows.h>
typedef struct Binary_tree
{
void * user_data;
Binary_tree* left;
Binary_tree* right;
} binary_tree;
void show_tree ( binary_tree* b1)
{
if ( b1 == nullptr )
{
printf ( "本分支结束!!!\n\n" ) ;
return ;
}
printf ( "root_data = %d\n\n" , * ( int * ) b1-> user_data) ;
show_tree ( b1-> left) ;
show_tree ( b1-> right) ;
}
int main ( )
{
binary_tree* b1 = ( binary_tree* ) malloc ( sizeof ( binary_tree) ) ;
binary_tree* b2 = ( binary_tree* ) malloc ( sizeof ( binary_tree) ) ;
binary_tree* b3 = ( binary_tree* ) malloc ( sizeof ( binary_tree) ) ;
binary_tree* b4 = ( binary_tree* ) malloc ( sizeof ( binary_tree) ) ;
binary_tree* b5 = ( binary_tree* ) malloc ( sizeof ( binary_tree) ) ;
binary_tree* b6 = ( binary_tree* ) malloc ( sizeof ( binary_tree) ) ;
binary_tree* b7 = ( binary_tree* ) malloc ( sizeof ( binary_tree) ) ;
binary_tree* b8 = ( binary_tree* ) malloc ( sizeof ( binary_tree) ) ;
int u1 = 1111 ;
b1-> user_data = ( void * ) & u1;
int u2 = 2222 ;
b2-> user_data = ( void * ) & u2;
int u3 = 3333 ;
b3-> user_data = ( void * ) & u3;
int u4 = 4444 ;
b4-> user_data = ( void * ) & u4;
int u5 = 5555 ;
b5-> user_data = ( void * ) & u5;
int u6 = 6666 ;
b6-> user_data = ( void * ) & u6;
int u7 = 7777 ;
b7-> user_data = ( void * ) & u7;
int u8 = 8888 ;
b8-> user_data = ( void * ) & u8;
b1-> left = b2;
b1-> right = b3;
b2-> left = b4;
b2-> right = b5;
b3-> left = b6;
b3-> right = b7;
b4-> left = b8;
b4-> right = nullptr ;
b5-> left = nullptr ;
b5-> right = nullptr ;
b6-> left = nullptr ;
b6-> right = nullptr ;
b7-> left = nullptr ;
b7-> right = nullptr ;
b8-> left = nullptr ;
b8-> right = nullptr ;
show_tree ( b1) ;
return 0 ;
}
求树的深度
求二叉树的深度:
int deep ( binary_tree* b1)
{
int left = 0 ;
int right = 0 ;
int root = 0 ;
if ( b1 == nullptr )
{
return 0 ;
}
left = deep ( b1-> left) ;
right = deep ( b1-> right) ;
root = 1 + ( left > right ? left : right) ;
return root;
}
树的拷贝
binary_tree* copy_tree ( binary_tree* b1)
{
printf ( "开始拷贝树!\n\n" ) ;
binary_tree* left = nullptr ;
binary_tree* right = nullptr ;
binary_tree* new_root = nullptr ;
if ( b1 == nullptr )
{
printf ( "树为空,无法拷贝!\n" ) ;
return nullptr ;
}
if ( b1-> left != nullptr )
{
left = copy_tree ( b1-> left) ;
}
else
{
left = nullptr ;
}
if ( b1-> right != nullptr )
{
right = copy_tree ( b1-> right) ;
}
else
{
right = nullptr ;
}
new_root = ( binary_tree* ) malloc ( sizeof ( binary_tree) ) ;
if ( new_root == nullptr )
{
printf ( "空间开辟错误!\n" ) ;
return nullptr ;
}
new_root-> left = left;
new_root-> right = right;
new_root-> user_data = b1-> user_data;
return new_root;
}