二叉树详解

   树是一种比较重要的数据结构,尤其是二叉树。二叉树是一种特殊的树,在二叉树中每个节点最多有两个子节点,一般称为左子节点和右子节点(或左孩子和右孩子),并且二叉树的子树有左右之分,其次序不能任意颠倒。本篇博客将详细为大家解析二叉树。

 

首先介绍两个概念:

满二叉树:在一棵二叉树中,如果所有分支结点都有左孩子和右孩子结点,并且叶子结点都集中在二叉树的最下层,这样的树叫做满二叉树

 

如:



 

完全二叉树:若二叉树中最多只有最下面两层的结点的度数可以小于2,并且最下面一层的叶子结点都是依次排列在该层最左边的位置上,则称为完全二叉树

 

如:



 区别:满二叉树是完全二叉树的特例,因为满二叉树已经满了,而完全并不代表满。所以形态你也应该想象出来了吧,满指的是出了叶子节点外每个节点都有两个孩子,而完全的含义则是最后一层没有满,并没有满。

 

      

二叉树的链式存储结构是一类重要的数据结构,定义结果为:

Cpp代码  收藏代码
  1. //定义树的结构  
  2. struct node  
  3. {  
  4.     node * lchild;  
  5.     node * rchild;  
  6.     string data;  
  7.     //初始化  
  8.     node()  
  9.     {  
  10.         lchild=rchild=NULL;  
  11.     }  
  12. };  

 

二叉树的建立

 

首先我们用户输入生成一棵二叉树,要生的的二叉树如下图所示:

#代表空结点。

 下面我们根据上面图中所示的二叉树,利用先序依次输入ABDG###E#H##C#F##(即先序遍历)

生成二叉树的代码如下:

Cpp代码  收藏代码
  1. //二叉树生成--先序遍历输入要生成的二叉树数据,#代表空结点  
  2. void CreateTree(node * & root)  
  3. {  
  4.      char data;  
  5.      cin>>data;  
  6.      if(data!='#')  
  7.      {  
  8.          root=new node;  
  9.          root->data=data;  
  10.            
  11.          CreateTree(root->lchild);  
  12.           
  13.          CreateTree(root->rchild);  
  14.           
  15.      }  
  16. }  

 

二叉树节点查找

采用递归的方法在二叉树root里查找只为aim的结点,若找到此节点则返回其指针,否则返回NULL

查找代码如下:

Cpp代码  收藏代码
  1. //检查二叉树是否包含数据aim,有则返回其指针  
  2. node * Findnode(node * & root,string aim)  
  3. {  
  4.     node * p;  
  5.     if(root==NULL)//空树  
  6.         return NULL;  
  7.     else if(root->data==aim)  
  8.         return root;  
  9.     else  
  10.     {     
  11.         p=Findnode(root->lchild,aim);  
  12.         if(p!=NULL)  
  13.             return p;  
  14.         else  
  15.             return Findnode(root->rchild,aim);     
  16.     }  
  17. }  

 这里解释一下递归中的return的意思:

return 对当前函数来说是结束了,对调用它的父函数来说你这个函数执行完成了,父函数就会接着执行下一语句。
没想到父函数马上又遇到一个return,父函数结束了,对爷爷函数来说父函数执行完成了,爷爷函数就接着执行下一个语句

 

二叉树遍历

1.先序遍历

先序遍历过程是:

1)访问根结点

2)先序遍历左子树

3)先序遍历右子树

先序遍历代码为:

 

Cpp代码  收藏代码
  1. void  PreOrder(node * root)//先序遍历  
  2. {  
  3.     if(root!=NULL)  
  4.     {  
  5.         cout<<root->data;  
  6.         PreOrder(root->lchild);  
  7.         PreOrder(root->rchild);  
  8.     }  
  9. }  

 

2.中序遍历

中序遍历过程是:1)中序遍历左子树

2)访问根结点

3)中序遍历右子树

 

中序遍历的代码:

 

Cpp代码  收藏代码
  1. void  InOrder(node * root)//中序遍历  
  2. {  
  3.     if(root!=NULL)  
  4.     {  
  5.           
  6.         InOrder(root->lchild);  
  7.         cout<<root->data;  
  8.         InOrder(root->rchild);  
  9.     }  
  10. }  

 

3.后续遍历后序遍历过程是:

1)后序遍历左子树

2)后序遍历右子树3)访问根结点

 

后序遍历代码为:

 

Cpp代码  收藏代码
  1. void  PostOrder(node * root)//后序遍历  
  2. {  
  3.     if(root!=NULL)  
  4.     {  
  5.           
  6.         PostOrder(root->lchild);  
  7.         PostOrder(root->rchild);  
  8.         cout<<root->data;  
  9.     }  
  10. }  

 

二叉树高度计算

递归解法:
(1)如果二叉树为空,二叉树的深度为0
(2)如果二叉树不为空,二叉树的深度 = max(左子树深度, 右子树深度) + 1

代码如下:

Cpp代码  收藏代码
  1. int NodeHeight(node * root)//计算二叉树高度  
  2. {  
  3.     int lchild,rchlid;  
  4.     if(root==NULL)  
  5.         return 0;  
  6.     else  
  7.     {  
  8.         lchild=NodeHeight(root->lchild);  
  9.         rchlid=NodeHeight(root->rchild);  
  10.         return (lchild>rchlid)?(lchild+1):(rchlid+1);  
  11.     }  
  12. }  

 

 

输出二叉树叶子节点

递归解法:
参考代码如下:

Cpp代码  收藏代码
  1. void Showleaf(node * root)  
  2. {  
  3.     if(root!=NULL)  
  4.     {  
  5.         if(root->lchild==NULL&&root->rchild==NULL)  
  6.             cout<<root->data;  
  7.         Showleaf(root->lchild);//输出左子树叶子节点  
  8.         Showleaf(root->rchild);//输出右子树叶子节点  
  9.     }  
  10. }  

 

运行结果为:



 

附上源代码地址:https://github.com/longpo/algorithm/tree/master/Btree

 

递归分析

上面源代码中,大量运用了递归算法,

下面我们来分析其中一个递归的过程。

二叉树结构为:



 利用先序遍历,即代码为:

Cpp代码  收藏代码
  1. void  PreOrder(node * root)//先序遍历  
  2. {  
  3.     if(root!=NULL)  
  4.     {  
  5.         cout<<root->data;  
  6.         PreOrder(root->lchild);  
  7.         PreOrder(root->rchild);  
  8.     }  
  9. }  

 

画出其运行状态图:


posted @ 2019-07-31 15:49  那些年的代码  阅读(20959)  评论(1编辑  收藏  举报