九、树类相关算法


树既可以保证查找的高效又可以保证插入的效率

  • 叶子节点---------------没有子节点的节点

  • 节点的权---------------节点的值

  • 路径--------------------从根节点到找到节点的路线

  • 数的高度--------------层数

  • 森林--------------------多可子树构成森林

9.1 二叉树

概念:

  • 二叉树 :每个节点最多两个子节点

  • 满二叉树:所有叶子节点都在最后一层,并且节点总数为 2^n-1 n为层数

  • 完全二叉树:所有叶子节点都在最后一层或者倒数第二层,并且在这两层各自分别都不间断(就是中间节点都存在)

9.1.1遍历方式(判断方式都是看父节点遍历的位置):

先序遍历 -----------先从父节点遍历

遍历结果为 : 1 2 3 5 4

中序遍历 ------------先从左子节点遍历 然后父节点 ,注意:每次遍历都要判断当前节点有没有左右子树

遍历结果为: 2 1 5 3 4

后序遍历

遍历结果为: 2 5 4 3 1

代码实现:

这里面需要注意:我开始一直希望在二叉树类中实现遍历的代码,但发现行不通;;最后还是在节点中去实现遍历,然后再二叉树类中直接去调用,,面向对象的思维

首先是节点类,方法都在节点中实现

<span style="background-color:#333333"><span style="color:#da924a">//创建节点类</span>
<span style="color:#c88fd0">class</span> <span style="color:#8d8df0">treeNode</span> {
 <span style="color:#c88fd0">private</span> <span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">object</span>;<span style="color:#da924a">//存放数据</span>
 <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">left</span>;<span style="color:#da924a">//左节点</span>
 <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">right</span>;<span style="color:#da924a">//右节点</span>
​
 <span style="color:#b8bfc6">treeNode</span>(<span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">o</span>) {
     <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">object</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">o</span>;
 }
​
​
 <span style="color:#da924a">//    先序遍历</span>
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">preTraversal</span>() {
     <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">print</span>(<span style="color:#c88fd0">this</span> <span style="color:#b8bfc6">+</span> <span style="color:#d26b6b">"  "</span>);
​
     <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">!=</span> <span style="color:#84b6cb">null</span>) {
         <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">preTraversal</span>();
     }
​
     <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">!=</span> <span style="color:#84b6cb">null</span>) {
         <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">preTraversal</span>();
     }
 }
​
 <span style="color:#da924a">//    中序遍历</span>
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">midTraversal</span>() {
​
​
     <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">!=</span> <span style="color:#84b6cb">null</span>) {
         <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">midTraversal</span>();
     }
     <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">print</span>(<span style="color:#c88fd0">this</span> <span style="color:#b8bfc6">+</span> <span style="color:#d26b6b">"  "</span>);
     <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">!=</span> <span style="color:#84b6cb">null</span>) {
         <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">midTraversal</span>();
     }
 }
​
 <span style="color:#da924a">//    后序遍历</span>
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">lastTraversal</span>() {
​
​
     <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">!=</span> <span style="color:#84b6cb">null</span>) {
         <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">lastTraversal</span>();
     }
​
     <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">!=</span> <span style="color:#84b6cb">null</span>) {
         <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">lastTraversal</span>();
     }
     <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">print</span>(<span style="color:#c88fd0">this</span> <span style="color:#b8bfc6">+</span> <span style="color:#d26b6b">"  "</span>);
 }
​
 <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">getLeft</span>() {
     <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">left</span>;
 }
​
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setLeft</span>(<span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">left</span>) {
     <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">left</span>;
 }
​
 <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">getRight</span>() {
     <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">right</span>;
 }
​
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setRight</span>(<span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">right</span>) {
     <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">right</span>;
 }
​
 <span style="color:#b7b3b3">@Override</span>
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">String</span> <span style="color:#b8bfc6">toString</span>() {
     <span style="color:#c88fd0">return</span> <span style="color:#d26b6b">"treeNode{"</span> <span style="color:#b8bfc6">+</span>
             <span style="color:#d26b6b">"object="</span> <span style="color:#b8bfc6">+</span> <span style="color:#b8bfc6">object</span> <span style="color:#b8bfc6">+</span>
             <span style="color:#d26b6b">'}'</span>;
 }
}</span>

然后是二叉树类 对外暴露的类和方法

<span style="background-color:#333333"><span style="color:#c88fd0">class</span> <span style="color:#8d8df0">biTree</span> {
 <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">head</span>;<span style="color:#da924a">//头结点</span>
 <span style="color:#da924a">//    先序遍历</span>
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">preTraversal</span>() {
     <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">head</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>) {
         <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"当前树中没有节点"</span>);
         <span style="color:#c88fd0">return</span>;
     }
     <span style="color:#b8bfc6">head</span>.<span style="color:#b8bfc6">preTraversal</span>();
 }
​
 <span style="color:#da924a">//    中序遍历</span>
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">midTraversal</span>() {
     <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">head</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>) {
         <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"当前树中没有节点"</span>);
         <span style="color:#c88fd0">return</span>;
     }
     <span style="color:#b8bfc6">head</span>.<span style="color:#b8bfc6">midTraversal</span>();
 }
​
 <span style="color:#da924a">//    后序遍历</span>
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">lastTraversal</span>() {
     <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">head</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>) {
         <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"当前树中没有节点"</span>);
         <span style="color:#c88fd0">return</span>;
     }
     <span style="color:#b8bfc6">head</span>.<span style="color:#b8bfc6">lastTraversal</span>();
 }
​
 <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">getHead</span>() {
     <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">head</span>;
 }
​
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setHead</span>(<span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">head</span>) {
     <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">head</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">head</span>;
 }
}</span>
9.1.2查找方法

学会了遍历对于查找就应该很容易理解,但是还是不能理解为简单的在遍历过程中去判断每一次遍历的结果和目标值相等就行,中间需要注意细节的处理问题,比如遍历过程中什么时候该返回,返回值的判断条件是是什么

代码:注意在判断返回时的逻辑,尤其是在左右递归过程中的返回条件,一定是当前递归获得的节点不为空才返回,如果为空说明整个递归过程中没有找到;;;注意返回条件绝对不能是目标值和递归中返回的节点值相等,因为如果没找到就会报空指针异常。 然后注意 真正的查找实际上就只有那几行代码

<span style="background-color:#333333">     <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">value</span> <span style="color:#b8bfc6">==</span> (<span style="color:#1cc685">int</span>)(<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">object</span>)){   <span style="color:#da924a">//真正查找还是在这里进行的</span>
         <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"找到了"</span><span style="color:#b8bfc6">+</span><span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">object</span>);
         <span style="color:#c88fd0">return</span> <span style="color:#c88fd0">this</span>;
     }</span>

<span style="background-color:#333333">​
<span style="color:#c88fd0">class</span> <span style="color:#8d8df0">biTree</span> {
 <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">head</span>;<span style="color:#da924a">//头结点</span>
 <span style="color:#da924a">//    先序查找</span>
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">preTraversalSearch</span>() {
     <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">head</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>) {
         <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"当前树中没有节点"</span>);
         <span style="color:#c88fd0">return</span>;
     }
     <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">head</span>.<span style="color:#b8bfc6">preTraversalSearch</span>(<span style="color:#64ab8f">5</span>);
     <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">treeNode</span><span style="color:#b8bfc6">==</span><span style="color:#84b6cb">null</span>){
         <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"没有这个元素"</span>);
     }
 }
​
 <span style="color:#da924a">//    中序查找</span>
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">midTraversalSearch</span>() {
     <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">head</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>) {
         <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"当前树中没有节点"</span>);
         <span style="color:#c88fd0">return</span>;
     }
     <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">head</span>.<span style="color:#b8bfc6">midTraversalSearch</span>(<span style="color:#64ab8f">5</span>);
     <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">treeNode</span><span style="color:#b8bfc6">==</span><span style="color:#84b6cb">null</span>){
         <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"没有这个元素"</span>);
     }
 }
​
 <span style="color:#da924a">//    后序查找</span>
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">lastTraversalSearch</span>() {
     <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">head</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>) {
         <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"当前树中没有节点"</span>);
         <span style="color:#c88fd0">return</span>;
     }
     <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">head</span>.<span style="color:#b8bfc6">lastTraversalSearch</span>(<span style="color:#64ab8f">5</span>);
     <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">treeNode</span><span style="color:#b8bfc6">==</span><span style="color:#84b6cb">null</span>){
         <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"没有这个元素"</span>);
     }
 }
​
 <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">getHead</span>() {
     <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">head</span>;
 }
​
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setHead</span>(<span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">head</span>) {
     <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">head</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">head</span>;
 }
}
​
<span style="color:#da924a">//创建节点类</span>
<span style="color:#c88fd0">class</span> <span style="color:#8d8df0">treeNode</span> {
 <span style="color:#c88fd0">private</span> <span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">object</span>;<span style="color:#da924a">//存放数据</span>
 <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">left</span>;<span style="color:#da924a">//左节点</span>
 <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">right</span>;<span style="color:#da924a">//右节点</span>
​
 <span style="color:#b8bfc6">treeNode</span>(<span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">o</span>) {
     <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">object</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">o</span>;
 }
​
​
 <span style="color:#da924a">//    先序查找</span>
 <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">preTraversalSearch</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">value</span>) {
     <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">print</span>(<span style="color:#c88fd0">this</span> <span style="color:#b8bfc6">+</span> <span style="color:#d26b6b">"  "</span>);<span style="color:#da924a">//进来就查找</span>
     <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">value</span> <span style="color:#b8bfc6">==</span> (<span style="color:#1cc685">int</span>)(<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">object</span>)){   <span style="color:#da924a">//真正查找还是在这里进行的</span>
         <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"找到了"</span><span style="color:#b8bfc6">+</span><span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">object</span>);
         <span style="color:#c88fd0">return</span> <span style="color:#c88fd0">this</span>;
     }
         <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">!=</span> <span style="color:#84b6cb">null</span>) {
              <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">=</span> <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">preTraversalSearch</span>(<span style="color:#b8bfc6">value</span>);
<span style="color:#da924a">//                 判断做递归的节点是不是要找的,如果是就返回</span>
             <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">treeNode</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
                 <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">treeNode</span>;
             }
         }
​
     <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">!=</span> <span style="color:#84b6cb">null</span>) {
        <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">treeNode</span>  <span style="color:#b8bfc6">=</span> <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">preTraversalSearch</span>(<span style="color:#b8bfc6">value</span>);
         <span style="color:#da924a">//真正查找的方法还是前面的判断  f (value == (int)(this.object))</span>
         <span style="color:#da924a">//所以这里返回条件是这个treeNode不为空 而不是去判断这个节点的值是否和目标值相等  这样会报空指针异常,如果为空说明没找到</span>
         <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">treeNode</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
             <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">treeNode</span>;
         }
     }
<span style="color:#da924a">//        如果都没返回那就是没找到</span>
     <span style="color:#c88fd0">return</span> <span style="color:#84b6cb">null</span>;
 }
​
​
​
 <span style="color:#da924a">//    中序查找</span>
 <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">midTraversalSearch</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">value</span>) {
<span style="color:#da924a">//        System.out.print(this + "  ");</span>
​
     <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">!=</span> <span style="color:#84b6cb">null</span>) {<span style="color:#da924a">//首先进行左递归</span>
         <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">=</span>  <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">midTraversalSearch</span>(<span style="color:#b8bfc6">value</span>);
<span style="color:#da924a">//            判断左节点是不是要找的,是的就返回</span>
         <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">treeNode</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
             <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">treeNode</span>;
         }
     }
     <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">print</span>(<span style="color:#c88fd0">this</span> <span style="color:#b8bfc6">+</span> <span style="color:#d26b6b">"  "</span>);
     <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">value</span> <span style="color:#b8bfc6">==</span> (<span style="color:#1cc685">int</span>)(<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">object</span>)){<span style="color:#da924a">//判断父节点是否等于子节点</span>
         <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"在父节点找到了"</span><span style="color:#b8bfc6">+</span><span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">object</span>);
         <span style="color:#c88fd0">return</span> <span style="color:#c88fd0">this</span>;
     }
     <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">!=</span> <span style="color:#84b6cb">null</span>) {
         <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">=</span>  <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">midTraversalSearch</span>(<span style="color:#b8bfc6">value</span>);
         <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">treeNode</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
             <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">treeNode</span>;
         }
     }
​
     <span style="color:#c88fd0">return</span> <span style="color:#84b6cb">null</span>;
 }
​
​
 <span style="color:#da924a">//    后序查找</span>
 <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">lastTraversalSearch</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">value</span>) {
​
     <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">!=</span> <span style="color:#84b6cb">null</span>) {<span style="color:#da924a">//首先进行左递归</span>
         <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">=</span>  <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">lastTraversalSearch</span>(<span style="color:#b8bfc6">value</span>);
<span style="color:#da924a">//            判断左节点是不是要找的,是的就返回</span>
         <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">treeNode</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
             <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">treeNode</span>;
         }
     }
     <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">!=</span> <span style="color:#84b6cb">null</span>) {
         <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">=</span>  <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">lastTraversalSearch</span>(<span style="color:#b8bfc6">value</span>);
         <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">treeNode</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
             <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">treeNode</span>;
         }
     }
     <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">print</span>(<span style="color:#c88fd0">this</span> <span style="color:#b8bfc6">+</span> <span style="color:#d26b6b">"  "</span>);
     <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">value</span> <span style="color:#b8bfc6">==</span> (<span style="color:#1cc685">int</span>)(<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">object</span>)){<span style="color:#da924a">//判断父节点是否等于子节点</span>
         <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"在父节点找到了"</span><span style="color:#b8bfc6">+</span><span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">object</span>);
         <span style="color:#c88fd0">return</span> <span style="color:#c88fd0">this</span>;
     }
     <span style="color:#c88fd0">return</span> <span style="color:#84b6cb">null</span>;
 }
​
 <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">getLeft</span>() {
     <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">left</span>;
 }
​
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setLeft</span>(<span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">left</span>) {
     <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">left</span>;
 }
​
 <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">getRight</span>() {
     <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">right</span>;
 }
​
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setRight</span>(<span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">right</span>) {
     <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">right</span>;
 }
​
 <span style="color:#b7b3b3">@Override</span>
 <span style="color:#c88fd0">public</span> <span style="color:#1cc685">String</span> <span style="color:#b8bfc6">toString</span>() {
     <span style="color:#c88fd0">return</span> <span style="color:#d26b6b">"treeNode{"</span> <span style="color:#b8bfc6">+</span>
             <span style="color:#d26b6b">"object="</span> <span style="color:#b8bfc6">+</span> <span style="color:#b8bfc6">object</span> <span style="color:#b8bfc6">+</span>
             <span style="color:#d26b6b">'}'</span>;
 }
}</span>

9.1.3 删除方法

特别注意二叉树的删除是单向的,所以在删除的时候必须首先找到他的父节点,然后再父节点进行判断子节点是不是要删除的元素,如果是就在父节点位置进行删除;;;;    还有一点需要注意,那就是root需要首先进行判断,这是为了防止如果要删除的是root就需要在外面直接将root置空,,,,,,在里面的递归就直接传入root进行左右递归就行

<span style="background-color:#333333"><span style="color:#b8bfc6">​
<span style="color:#c88fd0">class</span> <span style="color:#8d8df0">biTree</span> {
    <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">head</span>;<span style="color:#da924a">//头结点</span>
​
<span style="color:#da924a">//    删除节点</span>
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">delete</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">value</span>){
        <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">head</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>){
            <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"当前二叉树为空"</span>);
            <span style="color:#c88fd0">return</span>;
        }<span style="color:#c88fd0">else</span> {
            <span style="color:#c88fd0">if</span> ((<span style="color:#1cc685">int</span>)<span style="color:#b8bfc6">head</span>.<span style="color:#b8bfc6">getObject</span>() <span style="color:#b8bfc6">==</span> <span style="color:#b8bfc6">value</span>){<span style="color:#da924a">//需要在此处判断一下删除的位置是不是root根结点</span>
                <span style="color:#b8bfc6">head</span> <span style="color:#b8bfc6">=</span> <span style="color:#84b6cb">null</span>;
            }<span style="color:#c88fd0">else</span> {
                <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">delete</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">head</span>.<span style="color:#b8bfc6">delete</span>(<span style="color:#b8bfc6">value</span>);
                <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">delete</span><span style="color:#b8bfc6">==</span><span style="color:#84b6cb">null</span>){
                    <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"当前二叉树中没有您要删除的元素"</span>);
                }<span style="color:#c88fd0">else</span> {
                    <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"删除节点父节点为:"</span><span style="color:#b8bfc6">+</span><span style="color:#b8bfc6">delete</span>);
                }
            }
        }
    }
   
    <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">getHead</span>() {
        <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">head</span>;
    }
​
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setHead</span>(<span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">head</span>) {
        <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">head</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">head</span>;
    }
}
​
<span style="color:#da924a">//创建节点类</span>
<span style="color:#c88fd0">class</span> <span style="color:#8d8df0">treeNode</span> {
    <span style="color:#c88fd0">private</span> <span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">object</span>;<span style="color:#da924a">//存放数据</span>
    <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">left</span>;<span style="color:#da924a">//左节点</span>
    <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">right</span>;<span style="color:#da924a">//右节点</span>
​
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">getObject</span>() {
        <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">object</span>;
    }
​
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setObject</span>(<span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">object</span>) {
        <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">object</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">object</span>;
    }
​
    <span style="color:#b8bfc6">treeNode</span>(<span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">o</span>) {
        <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">object</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">o</span>;
    }
​
<span style="color:#da924a">//    删除</span>
    <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">delete</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">val</span>){
<span style="color:#da924a">//       二叉树是单向的,所以要删除一个元素必须在上一个元素进行判断,然后再上一个元素进行删除</span>
<span style="color:#da924a">//        首先判断当前元素的做节点是不是要删的元素</span>
        <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span> <span style="color:#b8bfc6">&&</span> (<span style="color:#1cc685">int</span>)<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">object</span> <span style="color:#b8bfc6">==</span><span style="color:#b8bfc6">val</span>){
<span style="color:#da924a">//            找到了将当前节点的左节点值为空、</span>
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">=</span> <span style="color:#84b6cb">null</span>;
            <span style="color:#c88fd0">return</span> <span style="color:#c88fd0">this</span>;
        }
​
<span style="color:#da924a">//        判断右侧</span>
        <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span> <span style="color:#b8bfc6">&&</span> (<span style="color:#1cc685">int</span>) <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">object</span> <span style="color:#b8bfc6">==</span><span style="color:#b8bfc6">val</span>){
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">=</span> <span style="color:#84b6cb">null</span>;
            <span style="color:#c88fd0">return</span> <span style="color:#c88fd0">this</span>;
        }
​
<span style="color:#da924a">//        如果左右都没找到然后进行递归</span>
        <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){<span style="color:#da924a">//先进行左递归</span>
            <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">delete</span> <span style="color:#b8bfc6">=</span> <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">delete</span>(<span style="color:#b8bfc6">val</span>);
            <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">delete</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
                <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">delete</span>;
            }
        }
        <span style="color:#da924a">//        如果左右都没找到然后进行递归</span>
        <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){<span style="color:#da924a">//右递归</span>
            <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">delete</span> <span style="color:#b8bfc6">=</span> <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">delete</span>(<span style="color:#b8bfc6">val</span>);
            <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">delete</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
                <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">delete</span>;
            }
        }
​
        <span style="color:#c88fd0">return</span> <span style="color:#84b6cb">null</span>;
​
    }
​
    <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">getLeft</span>() {
        <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">left</span>;
    }
​
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setLeft</span>(<span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">left</span>) {
        <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">left</span>;
    }
​
    <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">getRight</span>() {
        <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">right</span>;
    }
​
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setRight</span>(<span style="color:#b8bfc6">treeNode</span> <span style="color:#b8bfc6">right</span>) {
        <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">right</span>;
    }
​
    <span style="color:#b7b3b3">@Override</span>
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">String</span> <span style="color:#b8bfc6">toString</span>() {
        <span style="color:#c88fd0">return</span> <span style="color:#d26b6b">"treeNode{"</span> <span style="color:#b8bfc6">+</span>
                <span style="color:#d26b6b">"object="</span> <span style="color:#b8bfc6">+</span> <span style="color:#b8bfc6">object</span> <span style="color:#b8bfc6">+</span>
                <span style="color:#d26b6b">'}'</span>;
    }
}</span></span>

9.1.4 顺序存储二叉树

顺序存储就是在内存中是连续的一片空间,将二叉树以数组的形式实现:

一般顺序表存储的都是完全二叉树

顺序存储二叉树概念

<span style="background-color:#333333"><span style="color:#b8bfc6"><span style="color:#da924a">//    顺序存储二叉树</span>
​
<span style="color:#da924a">/**</span>
     <span style="color:#da924a">*</span>
     <span style="color:#da924a">* @param list 传入的数组</span>
     <span style="color:#da924a">* @param index 根节点下标 一般就是0</span>
     <span style="color:#da924a">*/</span>
<span style="color:#c88fd0">public</span> <span style="color:#c88fd0">static</span> <span style="color:#1cc685">void</span> <span style="color:#8d8df0">sequenceBinaryTree</span>( <span style="color:#1cc685">int</span> [] <span style="color:#b8bfc6">list</span>,<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">index</span>){
    <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">list</span><span style="color:#b8bfc6">==</span><span style="color:#84b6cb">null</span> <span style="color:#b8bfc6">||</span> <span style="color:#b8bfc6">list</span>.<span style="color:#b8bfc6">length</span><span style="color:#b8bfc6">==</span><span style="color:#64ab8f">0</span>){
        <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"数组为空"</span>);
        <span style="color:#c88fd0">return</span>;
    }
    <span style="color:#da924a">//        先序遍历输出:</span>
    <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#b8bfc6">list</span>[<span style="color:#b8bfc6">index</span>]);<span style="color:#da924a">//输出当前元素</span>
    <span style="color:#da924a">//        左递归</span>
    <span style="color:#c88fd0">if</span> ((<span style="color:#b8bfc6">index</span><span style="color:#b8bfc6">*</span><span style="color:#64ab8f">2</span><span style="color:#b8bfc6">+</span><span style="color:#64ab8f">1</span>)<span style="color:#b8bfc6"><</span><span style="color:#b8bfc6">list</span>.<span style="color:#b8bfc6">length</span>){
        <span style="color:#b8bfc6">sequenceBinaryTree</span>(<span style="color:#b8bfc6">list</span>,<span style="color:#b8bfc6">index</span><span style="color:#b8bfc6">*</span><span style="color:#64ab8f">2</span><span style="color:#b8bfc6">+</span><span style="color:#64ab8f">1</span>);
    }
    <span style="color:#da924a">//        右递归</span>
    <span style="color:#c88fd0">if</span> ((<span style="color:#b8bfc6">index</span><span style="color:#b8bfc6">*</span><span style="color:#64ab8f">2</span><span style="color:#b8bfc6">+</span><span style="color:#64ab8f">2</span>)<span style="color:#b8bfc6"><</span><span style="color:#b8bfc6">list</span>.<span style="color:#b8bfc6">length</span>){
        <span style="color:#b8bfc6">sequenceBinaryTree</span>(<span style="color:#b8bfc6">list</span>,<span style="color:#b8bfc6">index</span><span style="color:#b8bfc6">*</span><span style="color:#64ab8f">2</span><span style="color:#b8bfc6">+</span><span style="color:#64ab8f">2</span>);
    }
}
​</span></span>
9.1.5 线索化二叉树

线索化二叉树是为了有效的防止节点浪费,将所有的节点空指针都利用起来。。一个n个节点的二叉树一共有 n + 1 个空指针

线索化二叉树分为中序遍历线索先序遍历线索后续遍历线索,他们的左右节点指针指向分别为前置节点后后置节点,这个前置和后置是相对于你采用哪种遍历来说的,比如我对二叉树采用中序遍历后结果为{ 1 3 5 7 8} , 那么节点为1的前置节点就为空,后置节点就为3

跟普通节点不同的是线索二叉树节点多了两个属性 一个leftType 一个rightType 他们分别代表着每个节点的左右指针指向的是左右子节点还是前置和后置节点。

线索化二叉树难点在pre节点的理解,,,,我现在任然是糊涂的!!!!!!!!

代码:

<span style="background-color:#333333"><span style="color:#b8bfc6">​
    <span style="color:#da924a">//创建树节点</span>
    <span style="color:#c88fd0">class</span> <span style="color:#8d8df0">TreeNode2</span> {
        <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">left</span>;
        <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">right</span>;
        <span style="color:#c88fd0">private</span> <span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">data</span>;
        <span style="color:#c88fd0">private</span> <span style="color:#1cc685">int</span> <span style="color:#b8bfc6">leftNodeType</span>;<span style="color:#da924a">//左节点类型,0为节点,1为前置节点</span>
        <span style="color:#c88fd0">private</span> <span style="color:#1cc685">int</span> <span style="color:#b8bfc6">rightNodeType</span>;<span style="color:#da924a">//右节点类型,0为节点,1为后置节点</span>
​
        <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">TreeNode2</span>(<span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">data</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">data</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">data</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">getLeft</span>() {
            <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">left</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setLeft</span>(<span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">left</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">left</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">getRight</span>() {
            <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">right</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setRight</span>(<span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">right</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">right</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">getData</span>() {
            <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">data</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setData</span>(<span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">data</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">data</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">data</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">int</span> <span style="color:#b8bfc6">getLeftNodeType</span>() {
            <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">leftNodeType</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setLeftNodeType</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">leftNodeType</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">leftNodeType</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">leftNodeType</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">int</span> <span style="color:#b8bfc6">getRightNodeType</span>() {
            <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">rightNodeType</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setRightNodeType</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">rightNodeType</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">rightNodeType</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">rightNodeType</span>;
        }
    }   
​
​
​
<span style="color:#da924a">//创建线索化二叉树</span>
    <span style="color:#c88fd0">class</span> <span style="color:#8d8df0">ThreadedBinaryTree2</span> {
        <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">root</span>;<span style="color:#da924a">//根节点</span>
        <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">pre</span>;<span style="color:#da924a">//当前节点前一个节点</span>
​
        <span style="color:#da924a">//进行二叉树中序遍历线索化的方法</span>
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">ThreadTree</span>(<span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">Node</span>) {
            <span style="color:#da924a">//进行递归退出条件</span>
            <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">Node</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>) {
                <span style="color:#c88fd0">return</span>;
            }
​
<span style="color:#da924a">//            如果不为空那么就进行左递归</span>
            <span style="color:#b8bfc6">ThreadTree</span>(<span style="color:#b8bfc6">Node</span>.<span style="color:#b8bfc6">left</span>);
<span style="color:#da924a">//            找到相应的节点后进行线索化</span>
            <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">Node</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>) {<span style="color:#da924a">//设置前置节点</span>
                <span style="color:#b8bfc6">Node</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">pre</span>;<span style="color:#da924a">//当前节点左节点指向前一个节点</span>
                <span style="color:#b8bfc6">Node</span>.<span style="color:#b8bfc6">leftNodeType</span><span style="color:#b8bfc6">=</span><span style="color:#64ab8f">1</span>;
            }
<span style="color:#da924a">//            设置右节点为后置节点  设置后置节点必须知道我的后置节点是谁</span>
<span style="color:#da924a">//            每次进行右递归完后pre节点都会指向当前有递归的对象,,,,然后返回如果这个有递归对象可以设置后置节点那么</span>
<span style="color:#da924a">//            就可以直接将pre右节点指向当前节点</span>
            <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">pre</span> <span style="color:#b8bfc6">!=</span> <span style="color:#84b6cb">null</span> <span style="color:#b8bfc6">&&</span> <span style="color:#b8bfc6">pre</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>) {
                <span style="color:#b8bfc6">pre</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">=</span><span style="color:#b8bfc6">Node</span>;
                <span style="color:#b8bfc6">pre</span>.<span style="color:#b8bfc6">rightNodeType</span> <span style="color:#b8bfc6">=</span> <span style="color:#64ab8f">1</span>;
            }
<span style="color:#da924a">//            递归进行,Node会后移,那么pre也要跟着后移</span>
            <span style="color:#b8bfc6">pre</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">Node</span>;
<span style="color:#da924a">//            然后进行右递归</span>
            <span style="color:#b8bfc6">ThreadTree</span>(<span style="color:#b8bfc6">Node</span>.<span style="color:#b8bfc6">right</span>);
        }
​
​
​
        <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">getRoot</span>() {
            <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">root</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setRoot</span>(<span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">root</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">root</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">root</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">ThreadedBinaryTree2</span>(<span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">root</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">root</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">root</span>;
        }
    }</span></span>

重点还是理解,,,,,通过debug会比较好理解

9.1.6 线索化二叉树遍历
<span style="background-color:#333333"><span style="color:#b8bfc6">    <span style="color:#da924a">//创建树节点</span>
    <span style="color:#c88fd0">class</span> <span style="color:#8d8df0">TreeNode2</span> {
        <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">left</span>;
        <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">right</span>;
        <span style="color:#c88fd0">private</span> <span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">data</span>;
        <span style="color:#c88fd0">private</span> <span style="color:#1cc685">int</span> <span style="color:#b8bfc6">leftNodeType</span>;<span style="color:#da924a">//左节点类型,0为节点,1为前置节点</span>
        <span style="color:#c88fd0">private</span> <span style="color:#1cc685">int</span> <span style="color:#b8bfc6">rightNodeType</span>;<span style="color:#da924a">//右节点类型,0为节点,1为后置节点</span>
​
​
        <span style="color:#da924a">//        遍历线索化二叉树</span>
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">Traversal</span>(){
            <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span> <span style="color:#b8bfc6">&&</span> <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">leftNodeType</span><span style="color:#b8bfc6">!=</span><span style="color:#64ab8f">1</span>){
                <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">Traversal</span>();
            }
            <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"节点为:"</span><span style="color:#b8bfc6">+</span><span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">data</span>);
            <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span> <span style="color:#b8bfc6">&&</span> <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">rightNodeType</span><span style="color:#b8bfc6">!=</span><span style="color:#64ab8f">1</span>){
                <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">Traversal</span>();
            }
        }
        <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">TreeNode2</span>(<span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">data</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">data</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">data</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">getLeft</span>() {
            <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">left</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setLeft</span>(<span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">left</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">left</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">getRight</span>() {
            <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">right</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setRight</span>(<span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">right</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">right</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">getData</span>() {
            <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">data</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setData</span>(<span style="color:#1cc685">Object</span> <span style="color:#b8bfc6">data</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">data</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">data</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">int</span> <span style="color:#b8bfc6">getLeftNodeType</span>() {
            <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">leftNodeType</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setLeftNodeType</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">leftNodeType</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">leftNodeType</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">leftNodeType</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">int</span> <span style="color:#b8bfc6">getRightNodeType</span>() {
            <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">rightNodeType</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setRightNodeType</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">rightNodeType</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">rightNodeType</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">rightNodeType</span>;
        }
    }
​
    <span style="color:#da924a">//创建线索化二叉树</span>
    <span style="color:#c88fd0">class</span> <span style="color:#8d8df0">ThreadedBinaryTree2</span> {
        <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">root</span>;<span style="color:#da924a">//根节点</span>
        <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">pre</span>;<span style="color:#da924a">//当前节点前一个节点</span>
​
        <span style="color:#da924a">//进行二叉树中序遍历线索化的方法</span>
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">ThreadTree</span>(<span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">Node</span>) {
            <span style="color:#da924a">//进行递归退出条件</span>
            <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">Node</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>) {
                <span style="color:#c88fd0">return</span>;
            }
​
<span style="color:#da924a">//            如果不为空那么就进行左递归</span>
            <span style="color:#b8bfc6">ThreadTree</span>(<span style="color:#b8bfc6">Node</span>.<span style="color:#b8bfc6">left</span>);
<span style="color:#da924a">//            找到相应的节点后进行线索化</span>
            <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">Node</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>) {<span style="color:#da924a">//设置前置节点</span>
                <span style="color:#b8bfc6">Node</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">pre</span>;<span style="color:#da924a">//当前节点左节点指向前一个节点</span>
                <span style="color:#b8bfc6">Node</span>.<span style="color:#b8bfc6">leftNodeType</span><span style="color:#b8bfc6">=</span><span style="color:#64ab8f">1</span>;
            }
<span style="color:#da924a">//            设置右节点为后置节点  设置后置节点必须知道我的后置节点是谁</span>
<span style="color:#da924a">//            每次进行右递归完后pre节点都会指向当前有递归的对象,,,,然后返回如果这个有递归对象可以设置后置节点那么</span>
<span style="color:#da924a">//            就可以直接将pre右节点指向当前节点</span>
            <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">pre</span> <span style="color:#b8bfc6">!=</span> <span style="color:#84b6cb">null</span> <span style="color:#b8bfc6">&&</span> <span style="color:#b8bfc6">pre</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>) {
                <span style="color:#b8bfc6">pre</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">=</span><span style="color:#b8bfc6">Node</span>;
                <span style="color:#b8bfc6">pre</span>.<span style="color:#b8bfc6">rightNodeType</span> <span style="color:#b8bfc6">=</span> <span style="color:#64ab8f">1</span>;
            }
<span style="color:#da924a">//            递归进行,Node会后移,那么pre也要跟着后移</span>
            <span style="color:#b8bfc6">pre</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">Node</span>;
<span style="color:#da924a">//            然后进行右递归</span>
            <span style="color:#b8bfc6">ThreadTree</span>(<span style="color:#b8bfc6">Node</span>.<span style="color:#b8bfc6">right</span>);
        }
​
​
<span style="color:#da924a">//        进行二叉树遍历</span>
        <span style="color:#c88fd0">public</span>  <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">TreeTraversal</span>(){
            <span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">Traversal</span>();
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">getRoot</span>() {
            <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">root</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">setRoot</span>(<span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">root</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">root</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">root</span>;
        }
​
        <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">ThreadedBinaryTree2</span>(<span style="color:#b8bfc6">TreeNode2</span> <span style="color:#b8bfc6">root</span>) {
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">root</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">root</span>;
        }
    }</span></span>

9.1.7 二叉树的实际应用
1. 堆排序

说实话我没太理解这个排序,大致思路是有,但是在编码的时候没太看懂,基本上是对照着代码敲下来的!!!!

这里先说一下我目前的理解情况吧:

  • 首先堆排序是用到了顺序存储二叉树,实际数据时存储在数组中的,只是假设他的结构是一颗二叉树

  • 大根堆就是每个非叶子节点和他的子节点相比都是最大的,他的两个子节点大小顺序无关

  • 堆排序大致思路是:

    先将数组排序为大根堆,然后再每次将堆顶元素拿出来放在数组最后面,然后将数组最后那个元素放到堆顶位置,接着再次进行大根堆的构建,此时构建大根堆的数组长度是原长度-1,直到遍历完成堆排序完成。

    下面代码没理解的是:为什么在构建大根堆时循环后操作条件为 i=i*2+1

    <span style="background-color:#333333"><span style="color:#c88fd0">package</span> <span style="color:#8d8df0">com</span>.<span style="color:#b8bfc6">hubei</span>.<span style="color:#b8bfc6">didi</span>;
    ​
    <span style="color:#da924a">/**</span>
     <span style="color:#da924a">* @Author: 大空</span>
     <span style="color:#da924a">* @Data: 2023-04-28 21:43</span>
     <span style="color:#da924a">* @Description: 描述</span>
     <span style="color:#da924a">* @Version:1.0.0</span>
     <span style="color:#da924a">*/</span>
    <span style="color:#c88fd0">public</span> <span style="color:#c88fd0">class</span> <span style="color:#8d8df0">test2</span> <span style="color:#c88fd0">implements</span> <span style="color:#b8bfc6">Serializable</span> {
    ​
        <span style="color:#b7b3b3">@Test</span>
        <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">sortTest</span>() {
            <span style="color:#1cc685">int</span>[] <span style="color:#b8bfc6">arr</span> <span style="color:#b8bfc6">=</span> {<span style="color:#64ab8f">4</span>, <span style="color:#64ab8f">6</span>, <span style="color:#64ab8f">8</span>, <span style="color:#64ab8f">5</span>, <span style="color:#64ab8f">9</span>};
            <span style="color:#b8bfc6">sort</span>(<span style="color:#b8bfc6">arr</span>);
            <span style="color:#1cc685">int</span>[] <span style="color:#b8bfc6">arr2</span> <span style="color:#b8bfc6">=</span> {<span style="color:#64ab8f">99</span>, <span style="color:#64ab8f">4</span>, <span style="color:#64ab8f">6</span>, <span style="color:#64ab8f">8</span>, <span style="color:#64ab8f">5</span>, <span style="color:#64ab8f">9</span>, <span style="color:#b8bfc6">-</span><span style="color:#64ab8f">1</span>, <span style="color:#b8bfc6">-</span><span style="color:#64ab8f">2</span>, <span style="color:#64ab8f">100</span>};
            <span style="color:#b8bfc6">sort</span>(<span style="color:#b8bfc6">arr2</span>);
        }
    ​
        <span style="color:#c88fd0">private</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">sort</span>(<span style="color:#1cc685">int</span>[] <span style="color:#b8bfc6">arr</span>) {
            <span style="color:#da924a">// =====  1. 构造初始堆</span>
            <span style="color:#da924a">// 从第一个非叶子节点开始调整</span>
            <span style="color:#da924a">// 4,9,8,5,6</span>
            <span style="color:#da924a">//  adjustHeap(arr, arr.length / 2 - 1, arr.length);</span>
    ​
            <span style="color:#da924a">// 循环调整</span>
            <span style="color:#da924a">// 从第一个非叶子节点开始调整,自低向上</span>
            <span style="color:#c88fd0">for</span> (<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">i</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">arr</span>.<span style="color:#b8bfc6">length</span> <span style="color:#b8bfc6">/</span> <span style="color:#64ab8f">2</span> <span style="color:#b8bfc6">-</span> <span style="color:#64ab8f">1</span>; <span style="color:#b8bfc6">i</span> <span style="color:#b8bfc6">>=</span> <span style="color:#64ab8f">0</span>; <span style="color:#b8bfc6">i</span><span style="color:#b8bfc6">--</span>) {
                <span style="color:#b8bfc6">adjustHeap</span>(<span style="color:#b8bfc6">arr</span>, <span style="color:#b8bfc6">i</span>, <span style="color:#b8bfc6">arr</span>.<span style="color:#b8bfc6">length</span>);
            }
            <span style="color:#da924a">// 第一轮调整了 3 个堆后:结果为:9,6,8,5,4</span>
            <span style="color:#da924a">// System.out.println(Arrays.toString(arr));</span>
    ​
            <span style="color:#da924a">// 2. 将堆顶元素与末尾元素进行交换,然后再重新调整</span>
            <span style="color:#1cc685">int</span> <span style="color:#b8bfc6">temp</span> <span style="color:#b8bfc6">=</span> <span style="color:#64ab8f">0</span>;
            <span style="color:#c88fd0">for</span> (<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">j</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">arr</span>.<span style="color:#b8bfc6">length</span> <span style="color:#b8bfc6">-</span> <span style="color:#64ab8f">1</span>; <span style="color:#b8bfc6">j</span> <span style="color:#b8bfc6">></span> <span style="color:#64ab8f">0</span>; <span style="color:#b8bfc6">j</span><span style="color:#b8bfc6">--</span>) {
                <span style="color:#b8bfc6">temp</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">arr</span>[<span style="color:#b8bfc6">j</span>];  <span style="color:#da924a">// j 是末尾元素</span>
                <span style="color:#b8bfc6">arr</span>[<span style="color:#b8bfc6">j</span>] <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">arr</span>[<span style="color:#64ab8f">0</span>];
                <span style="color:#b8bfc6">arr</span>[<span style="color:#64ab8f">0</span>] <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">temp</span>;
                <span style="color:#da924a">// 这里是从第一个节点开始: 不是构建初始堆了</span>
                <span style="color:#da924a">// 如果</span>
                <span style="color:#b8bfc6">adjustHeap</span>(<span style="color:#b8bfc6">arr</span>, <span style="color:#64ab8f">0</span>, <span style="color:#b8bfc6">j</span>);
            }
            <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#b8bfc6">Arrays</span>.<span style="color:#b8bfc6">toString</span>(<span style="color:#b8bfc6">arr</span>));
        }
    ​
        <span style="color:#da924a">/**</span>
         <span style="color:#da924a">* 调整堆</span>
         <span style="color:#da924a">*</span>
         <span style="color:#da924a">* @param arr</span>
         <span style="color:#da924a">* @param i      非叶子节点,以此节点为基础,将它、它的左、右,调整为一个大顶堆</span>
         <span style="color:#da924a">* @param length</span>
         <span style="color:#da924a">*/</span>
        <span style="color:#c88fd0">private</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">adjustHeap</span>(<span style="color:#1cc685">int</span>[] <span style="color:#b8bfc6">arr</span>, <span style="color:#1cc685">int</span> <span style="color:#b8bfc6">i</span>, <span style="color:#1cc685">int</span> <span style="color:#b8bfc6">length</span>) {
            <span style="color:#da924a">// 难点是将当前的堆调整之后,影响了它后面节点堆的混乱,如何继续对影响的堆进行调整</span>
            <span style="color:#da924a">// 所以第一步中:是额外循环的从 低向上调整的</span>
            <span style="color:#da924a">//    第三步中:就是本代码的,从上到下调整的;这个很重要,一定要明白</span>
            <span style="color:#1cc685">int</span> <span style="color:#b8bfc6">temp</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">arr</span>[<span style="color:#b8bfc6">i</span>];
            <span style="color:#da924a">// 从传入节点的左节点开始处理,下一次则是以该节点为顶堆的左节点进行调整</span>
            <span style="color:#c88fd0">for</span> (<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">k</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">i</span> <span style="color:#b8bfc6">*</span> <span style="color:#64ab8f">2</span> <span style="color:#b8bfc6">+</span> <span style="color:#64ab8f">1</span>; <span style="color:#b8bfc6">k</span> <span style="color:#b8bfc6"><</span> <span style="color:#b8bfc6">length</span>; <span style="color:#b8bfc6">k</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">k</span> <span style="color:#b8bfc6">*</span> <span style="color:#64ab8f">2</span> <span style="color:#b8bfc6">+</span> <span style="color:#64ab8f">1</span>) {
                <span style="color:#da924a">// 要将这三个数(堆),调整为一个大顶堆</span>
                <span style="color:#da924a">// i 的左节点小于右节点</span>
                <span style="color:#da924a">// k+1 < length : 当调整长度为 2 时,也就是数组的前两个元素,其实它没有第三个节点了,就不能走这个判定</span>
                <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">k</span> <span style="color:#b8bfc6">+</span> <span style="color:#64ab8f">1</span> <span style="color:#b8bfc6"><</span> <span style="color:#b8bfc6">length</span> <span style="color:#b8bfc6">&&</span> <span style="color:#b8bfc6">arr</span>[<span style="color:#b8bfc6">k</span>] <span style="color:#b8bfc6"><</span> <span style="color:#b8bfc6">arr</span>[<span style="color:#b8bfc6">k</span> <span style="color:#b8bfc6">+</span> <span style="color:#64ab8f">1</span>]) {
                    <span style="color:#b8bfc6">k</span><span style="color:#b8bfc6">++</span>; <span style="color:#da924a">// 右边的大,则将 k 变成最大的那一个</span>
                }
                <span style="color:#da924a">// 如果左右中最大的一个数,比 i 大。则调整它</span>
                <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">arr</span>[<span style="color:#b8bfc6">k</span>] <span style="color:#b8bfc6">></span> <span style="color:#b8bfc6">temp</span>) {
                    <span style="color:#b8bfc6">arr</span>[<span style="color:#b8bfc6">i</span>] <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">arr</span>[<span style="color:#b8bfc6">k</span>];
                    <span style="color:#b8bfc6">i</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">k</span>; <span style="color:#da924a">// i 记录被调整后的索引。</span>
                } <span style="color:#c88fd0">else</span> {
                    <span style="color:#c88fd0">break</span>;
                    <span style="color:#da924a">// 由于初始堆,就已经是大顶堆了,每个子堆的顶,都是比他的左右两个大的</span>
                    <span style="color:#da924a">// 当这里没有进行调整的话,那么就可以直接退出了</span>
                    <span style="color:#da924a">// 如果上面进行了调整。那么在初始堆之后,每次都是从 0 节点开始 自左到右,自上而下调整的</span>
                    <span style="color:#da924a">//    就会一层一层的往下进行调整</span>
                }
            }
            <span style="color:#b8bfc6">arr</span>[<span style="color:#b8bfc6">i</span>] <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">temp</span>;
        }
    }</span>
2.霍夫曼树

霍夫曼树是一种特殊的二叉树,他的要求是保证目标值所在的树权路径值最小,例如我给一个数组 [0,2,44,15,67] 你必须保证保证我的这些值在你构造的二叉树中权值路径最小(就是权值 * 层数 和最小);;;;

构建霍夫曼树:将给定数组从小到大排序,然后选取最小的两个值构成二叉树,root为两个值的和,然后将这个root值插入到原数组中,最后再将前面两个数移除,然后接着进行排序,接着构成二叉树,知道最后将所有哦数据都遍历完为止。

代码:

<span style="background-color:#333333"><span style="color:#b8bfc6">package com.hubei.didi.tree;

import com.sun.scenario.effect.impl.prism.PrImage;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Test;

import java.util.*;

/**
 * @Author: 大空
 * @Data: 2023-05-18 8:54
 * @Description: 构造霍夫曼树
 * @Version:1.0.0 基本思路:
 * 霍夫曼树是将数组构成整颗树的带权路径值最小的树。
 * 先将给定数组进行排序,从小到大,然后第一次取最小的两个值和这两个值的和为root节点构成一颗二叉树,然后将root值放进原数组并重新排序,
 * 然后再次重复上一步操作构成新的二叉树,每次构成二叉树都需要将用过的值移除。
 */
public class HuffmanTree {


    public static void main(String[] args) {
        int arr[] = {12, 15, 4, 1, 0, 31, 459, 75, 421};
        HuffmanTree huffmanTree = new HuffmanTree();
        Node node = huffmanTree.huffmanSort(arr);
        System.out.println(node.getLeft());
        node.midsTraversal();

    }

    /**
     * @param arr 传入的数组
     *            记性huffman树的构建
     */

    public Node huffmanSort(int arr[]) {

//        存放Node节点
        ArrayList<Node> nodes = new ArrayList<>();
//        首先对数组进行排序 从小到大
        Arrays.sort(arr);
        System.out.println("Arrays.toString(arr) = " + Arrays.toString(arr));
        for (int i = 0; i < arr.length; i++) {
            nodes.add(new Node(arr[i]));
        }
        System.out.println(nodes);

//        当List中只有节点数大于一时说明没有遍历完
        while (nodes.size() > 1) {

//            取出前两个节点构成二叉树
            Node node1 = nodes.get(0);
            Node node2 = nodes.get(1);
            Node node = new Node(node1.getData() + node2.getData());
            node.setLeft(node1);
            node.setRight(node2);

//            将构成的新的root节点放进list
            nodes.add(node);
//            移除遍历过得两个节点
            nodes.remove(0);
            nodes.remove(0);
//            重新对list进行排序
            Collections.sort(nodes, new MyCompare());
            System.out.println("nodes = " + nodes);
        }
//        最后剩下的一个节点就是最终构成霍夫曼树的root节点
        return nodes.get(0);


    }


}

@Data
@NoArgsConstructor
@AllArgsConstructor
//构建节点
class Node {
    private int data;//值
    private Node left;//左节点
    private Node right;//右节点

//    中序遍历
    public void midsTraversal(){
        if (this.left!=null){
            this.left.midsTraversal();
        }
        System.out.print(this.data+"   ");
        if (this.right!=null){
            this.right.midsTraversal();
        }
    }
    public Node(Integer data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "Node{" +
                "data=" + data +
                '}';
    }
}

class MyCompare implements Comparator<Node> {

    @Override
    public int compare(Node o1, Node o2) {
        return o1.getData() - o2.getData();
    }
}
</span></span>
3.赫夫曼编码

赫夫曼编码是通过赫夫曼树实现的一种数据无损压缩技术;;;;通过赫夫曼编码实现的是一种前缀编码,也就是所有字符经过编码后从前往后进行传输都只能找到唯一的编码与之对应。最终会被压缩为8位字节数组进行传输

具体实现思路:

  • 首先需要统计出要传输数据中的各个字符的个数,包括空格出现的次数

  • 然后将各个字符按照出现的次数作为权值进行赫夫曼树的构建

  • 进行赫夫曼树的构建时这里需要注意的是输的左侧路径规定为0,右侧为1;

  • 赫夫曼树构建完成后就按照路径值对各个字符进行编码赋值

例如:d出现次数为1,j出现次数为2,构成赫夫曼树后d的编码就是 100110 j的编码就是 0000

代码实现:

<span style="background-color:#333333">package com.hubei.didi.tree;
/**
 * @Author: 大空
 * @Data: 2023-05-20 10:19
 * @Description: 霍夫曼编码实现
 * @Version:1.0.0
 */
public class HuffmanCode {

    public static void main(String[] args) {
        String data = "i like like like java do you like a java";
        System.out.println("data.length() = " + data.length());
        HuffmanCode huffmanCode = new HuffmanCode();
        Node abcaad = huffmanCode.createHuffmanTree(data);
        abcaad.preTraversal();
        huffmanCode.huffmanCodeTomap(abcaad,"",new StringBuilder());
        System.out.println(huffmanCode.hashMap);
        String huffmanCode1 = huffmanCode.dataToHuffmanCode(data);
        System.out.println(huffmanCode1);
        System.out.println("huffmanCode1.length() = " + huffmanCode1.length());
        System.out.println("huffmanCode.zip(huffmanCode1) = " +Arrays.toString( huffmanCode.zip(huffmanCode1)));
    }

    //    首先创建节点
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    class Node implements Comparable<Node>{
        private Byte data;//存储数据
        private Integer weight;//存储权值,即数据出现的次数
        Node left;
        Node right;

        public Node(Byte data, int weight) {
            this.data = data;
            this.weight = weight;
        }


        //        前序遍历
        public  void  preTraversal(){
            if (null == this.weight){
                System.out.println("当前树为空");
                return;
            }
            System.out.println(this.weight);
            if (this.left!=null){
                this.left.preTraversal();
            }
            if (this.right!=null){
                this.right.preTraversal();
            }
        }
        //重写conpareTo方法
        @Override
        public int compareTo(Node o) {
            return this.weight-o.weight;//从小到大排序
        }
    }


    //构建霍夫曼树
    /**
     *
     * @param str 传进去的是原数据
     */
    public Node createHuffmanTree(String str){
        //        将字符串转换为字节数组
        byte []data =str.getBytes();
        //        创建一个List保存Node节点
        ArrayList<Node> nodes = new ArrayList<>();
        //        首先统计出原数据中各个字符的个数
        //        封装进一个map中
        HashMap<Byte,Integer> dataMap = new HashMap<>();
        for (int i = 0; i < data.length; i++) {
            if (dataMap.get(data[i]) == null){//第一次存
                dataMap.put( data[i],1);
            }else {
                dataMap.put(data[i],dataMap.get(data[i])+1);
            }
        }
        System.out.println("字符Map集合:"+dataMap);

        //        将得到的字符出现的个数封装成一个list便于后面进行赫夫曼树的构建
        for (Map.Entry<Byte, Integer> byteIntegerEntry : dataMap.entrySet()) {
            nodes.add(new Node(byteIntegerEntry.getKey(),byteIntegerEntry.getValue()));
        }
        Collections.sort(nodes);
        System.out.println("节点List:"+nodes);

        //        构建huffman树

        while (nodes.size()>1){
            Collections.sort(nodes);
            //            获取第一个节点
            Node node = nodes.get(0);
            //            获取第二个节点
            Node node1 = nodes.get(1);
            //            权值和相加构成新的节点
            Node node2 = new Node(null, node.weight + node1.weight);
            System.out.println("node2:"+node2);
            if (node.weight>node1.weight){
                node2.left = node1;
                node2.right = node;
            }else {
                node2.left = node;
                node2.right = node1;
            }

            nodes.add(node2);
            nodes.remove(0);
            nodes.remove(0);
        }
        return nodes.get(0);

    }


    //    进行霍夫曼编码
    //    首先定义一个Map存储每个字符的编码
    private HashMap<Byte,String> hashMap = new HashMap();


    /**
     *将各个字符转换为相应的编码存储到map中
     * @param node 霍夫曼树的根节点
     * @param index 向左是0,向右是1 最开始根节点传空串
     */
    public void  huffmanCodeTomap(Node node,String index,StringBuilder stringBuilder2){
        //        传入stringBuilder记录
        StringBuilder stringBuilder = new StringBuilder(stringBuilder2);
        stringBuilder.append(index);
        if (node==null){
            return;
        }
        if (node.data==null){//data为空说明是非叶子结点
            huffmanCodeTomap(node.left,"0",stringBuilder);
            huffmanCodeTomap(node.right,"1",stringBuilder);
        }else {//进入到了叶子结点,也就是我的字符
            hashMap.put(node.data,stringBuilder.toString());
        }
    }


    /**
     *返回最终数据转变的霍夫曼编码
     * @param str
     * @return  霍夫曼编码
     */
    public String dataToHuffmanCode(String str){
        StringBuilder stringBuilder = new StringBuilder();
        byte[] bytes = str.getBytes();
        for (byte aByte : bytes) {
            stringBuilder.append(hashMap.get(aByte));
        }
        return stringBuilder.toString();
    }


    /**
     * 对霍夫曼编码进行压缩,压缩成8位字节进新传输
     * @param str  实现的霍夫曼编码
     * @return   返回压缩后的字节数组
     */
    public byte[] zip(String str){
        //        判断字节数组长度需要多大
        int size = 0;
        if (str.length() % 8 ==0){
            size =  str.length()/8;
        }else {
            size = str.length()/8+1;
        }

        //        将编码截取后封装到字节数组中去
        byte huffmanByte[] = new byte[size];
        int index = 0;
        for (int i = 0; i < str.length(); i+=8) {
            if (i+8>str.length()){//如果最后截取的字符串不到8位就只截取到最后一位
                huffmanByte[index] = (byte) Integer.parseInt(str.substring(i),2);
            }else {
                huffmanByte[index] = (byte) Integer.parseInt(str.substring(i,i+8),2);
                index++;
            }
        }
        //        System.out.println(Arrays.toString(huffmanByte));
        //        返回哈夫曼字节数组
        return huffmanByte;

    }




}
</span>

4.二叉排序树

二叉排序树就是将二叉树按照一定顺序进行构建,比父节点小的放在父节点左边,比父节点大的放在父节点右边,最终构成一颗根节点左侧所有值都小于根节点值,右侧都大于根节点值的二叉树叫做二叉排序树

二叉排序树的删除:

参考链接:

[(36条消息) 二叉排序树的定义及基本操作(构造、查找、插入、删除)递归及非递归算法_薛定谔的猫ovo的博客-CSDN博客]:

  1. 删除的是叶子结点(注意删除根节点时进行判断)

    找到父节点直接删除

  2. 删除的是非叶子结点(注意删除根节点时进行判断)

    1. 只有一颗子树(左子树或者有子树)

      让子树替代删除节点位置

    2. 有两颗子树

      让待删除节点的直接前驱节点或者直接后驱节点去替换(中序遍历方式)

代码实现:

<span style="background-color:#333333"><span style="color:#b8bfc6"><span style="color:#c88fd0">package</span> <span style="color:#8d8df0">com</span>.<span style="color:#b8bfc6">hubei</span>.<span style="color:#b8bfc6">didi</span>.<span style="color:#b8bfc6">tree</span>;
​
<span style="color:#c88fd0">import</span> <span style="color:#b8bfc6">lombok</span>.<span style="color:#b8bfc6">AllArgsConstructor</span>;
<span style="color:#c88fd0">import</span> <span style="color:#b8bfc6">lombok</span>.<span style="color:#b8bfc6">Data</span>;
<span style="color:#c88fd0">import</span> <span style="color:#b8bfc6">lombok</span>.<span style="color:#b8bfc6">NoArgsConstructor</span>;
​
<span style="color:#da924a">/**</span>
 <span style="color:#da924a">* @Author: 大空</span>
 <span style="color:#da924a">* @Data: 2023-05-23 9:02</span>
 <span style="color:#da924a">* @Description: 二叉排序树</span>
 <span style="color:#da924a">* @Version:1.0.0</span>
 <span style="color:#da924a">*/</span>
<span style="color:#c88fd0">public</span> <span style="color:#c88fd0">class</span> <span style="color:#8d8df0">binarySortTree</span> {
​
​
    <span style="color:#c88fd0">public</span> <span style="color:#c88fd0">static</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">main</span>(<span style="color:#1cc685">String</span>[] <span style="color:#b8bfc6">args</span>) {
        <span style="color:#b8bfc6">BST</span> <span style="color:#b8bfc6">bst</span> <span style="color:#b8bfc6">=</span> <span style="color:#c88fd0">new</span> <span style="color:#b8bfc6">BST</span>();
        <span style="color:#1cc685">int</span> []<span style="color:#b8bfc6">arr</span> <span style="color:#b8bfc6">=</span> {<span style="color:#64ab8f">7</span>,<span style="color:#64ab8f">3</span>,<span style="color:#64ab8f">1</span>};
        <span style="color:#c88fd0">for</span> (<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">i</span> <span style="color:#b8bfc6">=</span> <span style="color:#64ab8f">0</span>; <span style="color:#b8bfc6">i</span> <span style="color:#b8bfc6"><</span> <span style="color:#b8bfc6">arr</span>.<span style="color:#b8bfc6">length</span>; <span style="color:#b8bfc6">i</span><span style="color:#b8bfc6">++</span>) {
            <span style="color:#b8bfc6">bst</span>.<span style="color:#b8bfc6">add</span>(<span style="color:#c88fd0">new</span> <span style="color:#b8bfc6">Nodes</span>(<span style="color:#b8bfc6">arr</span>[<span style="color:#b8bfc6">i</span>]));
        }
        <span style="color:#b8bfc6">bst</span>.<span style="color:#b8bfc6">midTraversal</span>();
        <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>();
<span style="color:#da924a">//        System.out.println("bst.getDeleteNode(7) = " + bst.getDeleteNode(12));</span>
<span style="color:#da924a">//        System.out.println("bst.getParentNode(12) = " + bst.getParentNode(12));</span>
        <span style="color:#b8bfc6">bst</span>.<span style="color:#b8bfc6">deleteNode</span>(<span style="color:#64ab8f">7</span>);
        <span style="color:#b8bfc6">bst</span>.<span style="color:#b8bfc6">deleteNode</span>(<span style="color:#64ab8f">3</span>);
<span style="color:#da924a">//        bst.deleteNode(1);</span>
        <span style="color:#b8bfc6">bst</span>.<span style="color:#b8bfc6">midTraversal</span>();
    }
​
}
<span style="color:#da924a">/**</span>
 <span style="color:#da924a">* 构造节点</span>
 <span style="color:#da924a">*/</span>
<span style="color:#b7b3b3">@Data</span>
<span style="color:#b7b3b3">@NoArgsConstructor</span>
<span style="color:#b7b3b3">@AllArgsConstructor</span>
<span style="color:#c88fd0">class</span> <span style="color:#8d8df0">Nodes</span> {
    <span style="color:#c88fd0">private</span> <span style="color:#1cc685">int</span> <span style="color:#b8bfc6">data</span>;<span style="color:#da924a">//存储数据</span>
    <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">Nodes</span> <span style="color:#b8bfc6">left</span>;<span style="color:#da924a">//左节点</span>
    <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">Nodes</span> <span style="color:#b8bfc6">right</span>;<span style="color:#da924a">//有节点</span>
    <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">Nodes</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">data</span>) {
        <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">data</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">data</span>;
    }
​
    <span style="color:#da924a">/**</span>
     <span style="color:#da924a">* 获取要删除节点的父节点</span>
     <span style="color:#da924a">* @param  value  要删除的值</span>
     <span style="color:#da924a">* @return</span>
     <span style="color:#da924a">*/</span>
    <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">Nodes</span> <span style="color:#b8bfc6">getParentNode</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">value</span>){
        <span style="color:#c88fd0">if</span> ((<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span> <span style="color:#b8bfc6">&&</span> <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">data</span> <span style="color:#b8bfc6">==</span> <span style="color:#b8bfc6">value</span>) <span style="color:#b8bfc6">||</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span> <span style="color:#b8bfc6">&&</span> <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">data</span> <span style="color:#b8bfc6">==</span> <span style="color:#b8bfc6">value</span>)){
<span style="color:#da924a">//            不是根节点</span>
            <span style="color:#c88fd0">return</span> <span style="color:#c88fd0">this</span>;
        }<span style="color:#c88fd0">else</span> {
​
           <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">value</span><span style="color:#b8bfc6"><</span><span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">data</span> <span style="color:#b8bfc6">&&</span> <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
               <span style="color:#c88fd0">return</span>  <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">getParentNode</span>(<span style="color:#b8bfc6">value</span>);
           }<span style="color:#c88fd0">else</span> <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">value</span><span style="color:#b8bfc6">>=</span><span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">data</span> <span style="color:#b8bfc6">&&</span> <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
               <span style="color:#c88fd0">return</span> <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">getParentNode</span>(<span style="color:#b8bfc6">value</span>);
           }<span style="color:#c88fd0">else</span> {
               <span style="color:#c88fd0">return</span> <span style="color:#84b6cb">null</span>;<span style="color:#da924a">//没找到</span>
           }
        }
​
    }
​
​
    <span style="color:#da924a">/**</span>
     <span style="color:#da924a">* 找到当前需要删除的节点</span>
     <span style="color:#da924a">* @param value 传入需要删除的值</span>
     <span style="color:#da924a">* @return</span>
     <span style="color:#da924a">*/</span>
​
    <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">Nodes</span> <span style="color:#b8bfc6">getDeleteNode</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">value</span>){
        <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">data</span> <span style="color:#b8bfc6">==</span> <span style="color:#b8bfc6">value</span>){
            <span style="color:#c88fd0">return</span> <span style="color:#c88fd0">this</span>;
        }<span style="color:#c88fd0">else</span> <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">value</span><span style="color:#b8bfc6">></span><span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">data</span>){<span style="color:#da924a">//大于向右找</span>
​
            <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
                <span style="color:#c88fd0">return</span>  <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">getDeleteNode</span>(<span style="color:#b8bfc6">value</span>);
            }
            <span style="color:#c88fd0">return</span> <span style="color:#84b6cb">null</span>;
​
        }<span style="color:#c88fd0">else</span> {<span style="color:#da924a">//小于向左找</span>
            <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
                <span style="color:#c88fd0">return</span>  <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">getDeleteNode</span>(<span style="color:#b8bfc6">value</span>);
            }
            <span style="color:#c88fd0">return</span> <span style="color:#84b6cb">null</span>;
        }
    }
​
    <span style="color:#da924a">/**</span>
     <span style="color:#da924a">* 添加节点</span>
     <span style="color:#da924a">*/</span>
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">add</span>(<span style="color:#b8bfc6">Nodes</span> <span style="color:#b8bfc6">nodes</span>){
        <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">data</span> <span style="color:#b8bfc6">></span> <span style="color:#b8bfc6">nodes</span>.<span style="color:#b8bfc6">data</span>){<span style="color:#da924a">//比对当前节点和提那家节点的大小  小的放左边,大的放右边</span>
            <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span><span style="color:#b8bfc6">==</span><span style="color:#84b6cb">null</span>){
                <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">nodes</span>;<span style="color:#da924a">//当前左节点为空就直接放到左节点</span>
            }<span style="color:#c88fd0">else</span>{
                <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">add</span>(<span style="color:#b8bfc6">nodes</span>);<span style="color:#da924a">//左递归</span>
            }
        }<span style="color:#c88fd0">else</span> {
            <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>){
                <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">nodes</span>;
            }<span style="color:#c88fd0">else</span> {
                <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">add</span>(<span style="color:#b8bfc6">nodes</span>);<span style="color:#da924a">//右递归</span>
            }
        }
    }
​
    <span style="color:#da924a">/**</span>
     <span style="color:#da924a">* 中序遍历</span>
     <span style="color:#da924a">*/</span>
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">midTraversal</span>(){
        <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">midTraversal</span>();
        }
        <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">print</span>(<span style="color:#d26b6b">"this.data = "</span> <span style="color:#b8bfc6">+</span> <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">data</span><span style="color:#b8bfc6">+</span><span style="color:#d26b6b">"\t"</span>);
        <span style="color:#c88fd0">if</span> (<span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span><span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
            <span style="color:#c88fd0">this</span>.<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">midTraversal</span>();
        }
    }
​
​
    <span style="color:#b7b3b3">@Override</span>
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">String</span> <span style="color:#b8bfc6">toString</span>() {
        <span style="color:#c88fd0">return</span> <span style="color:#d26b6b">"Node{"</span> <span style="color:#b8bfc6">+</span>
                <span style="color:#d26b6b">"data="</span> <span style="color:#b8bfc6">+</span> <span style="color:#b8bfc6">data</span> <span style="color:#b8bfc6">+</span>
                <span style="color:#d26b6b">'}'</span>;
    }
}
​
​
<span style="color:#da924a">/**</span>
 <span style="color:#da924a">* 二叉排序树</span>
 <span style="color:#da924a">*/</span>
<span style="color:#c88fd0">class</span> <span style="color:#8d8df0">BST</span>{
    <span style="color:#c88fd0">private</span> <span style="color:#b8bfc6">Nodes</span> <span style="color:#b8bfc6">root</span>;<span style="color:#da924a">//根节点</span>
​
​
    <span style="color:#da924a">/**</span>
     <span style="color:#da924a">* 构造删除节点的方法</span>
     <span style="color:#da924a">* @param value</span>
     <span style="color:#da924a">*/</span>
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">deleteNode</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">value</span>){
<span style="color:#da924a">//        首先获取要删除的节点</span>
        <span style="color:#b8bfc6">Nodes</span> <span style="color:#b8bfc6">deleteNode</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">getDeleteNode</span>(<span style="color:#b8bfc6">value</span>);
<span style="color:#da924a">//        获取要删除节点的父节点</span>
        <span style="color:#b8bfc6">Nodes</span> <span style="color:#b8bfc6">parentNode</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">getParentNode</span>(<span style="color:#b8bfc6">value</span>);
        <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">deleteNode</span>.<span style="color:#b8bfc6">getLeft</span>() <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span> <span style="color:#b8bfc6">&&</span> <span style="color:#b8bfc6">deleteNode</span>.<span style="color:#b8bfc6">getRight</span>() <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>){
​
            <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">parentNode</span>.<span style="color:#b8bfc6">getData</span>() <span style="color:#b8bfc6">==</span> <span style="color:#b8bfc6">value</span>){<span style="color:#da924a">//删除的是根节点</span>
                <span style="color:#b8bfc6">root</span> <span style="color:#b8bfc6">=</span> <span style="color:#84b6cb">null</span>;
                <span style="color:#c88fd0">return</span>;
            }
<span style="color:#da924a">//            如果要删除的是叶子结点  直接删除</span>
            <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">parentNode</span>.<span style="color:#b8bfc6">getLeft</span>()<span style="color:#b8bfc6">==</span><span style="color:#b8bfc6">deleteNode</span>){
                <span style="color:#b8bfc6">parentNode</span>.<span style="color:#b8bfc6">setLeft</span>(<span style="color:#84b6cb">null</span>);
            }<span style="color:#c88fd0">else</span> {
                <span style="color:#b8bfc6">parentNode</span>.<span style="color:#b8bfc6">setRight</span>(<span style="color:#84b6cb">null</span>);
            }
        }<span style="color:#c88fd0">else</span> {<span style="color:#da924a">//要删除的是非叶子节点</span>
​
            <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">deleteNode</span>.<span style="color:#b8bfc6">getLeft</span>()<span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span> <span style="color:#b8bfc6">&&</span> <span style="color:#b8bfc6">deleteNode</span>.<span style="color:#b8bfc6">getRight</span>()<span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){<span style="color:#da924a">//删除飞叶子节点有两颗子树情况</span>
<span style="color:#da924a">//                找到以中序遍历方式的直接前驱节点(直接后继节点)替换要删除的节点  即找到待删除节点左树的最右节点(右树的最左节点)</span>
                <span style="color:#b8bfc6">Nodes</span> <span style="color:#b8bfc6">tempNode</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">deleteNode</span>.<span style="color:#b8bfc6">getLeft</span>();
                <span style="color:#c88fd0">while</span> (<span style="color:#b8bfc6">tempNode</span>.<span style="color:#b8bfc6">getRight</span>()<span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
                    <span style="color:#b8bfc6">tempNode</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">tempNode</span>.<span style="color:#b8bfc6">getRight</span>();
                }
<span style="color:#da924a">//                找到后先删除这个找到的节点 然后替换</span>
                <span style="color:#b8bfc6">Nodes</span> <span style="color:#b8bfc6">parentNode1</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">getParentNode</span>(<span style="color:#b8bfc6">tempNode</span>.<span style="color:#b8bfc6">getData</span>());
                <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">parentNode1</span>.<span style="color:#b8bfc6">getLeft</span>()<span style="color:#b8bfc6">==</span><span style="color:#b8bfc6">tempNode</span>){
                    <span style="color:#b8bfc6">parentNode1</span>.<span style="color:#b8bfc6">setLeft</span>(<span style="color:#84b6cb">null</span>);
                }<span style="color:#c88fd0">else</span> {
                    <span style="color:#b8bfc6">parentNode1</span>.<span style="color:#b8bfc6">setRight</span>(<span style="color:#84b6cb">null</span>);
                }
                <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"tempNode = "</span> <span style="color:#b8bfc6">+</span> <span style="color:#b8bfc6">tempNode</span>);
                <span style="color:#da924a">/*替换*/</span>
                <span style="color:#b8bfc6">tempNode</span>.<span style="color:#b8bfc6">setLeft</span>(<span style="color:#b8bfc6">deleteNode</span>.<span style="color:#b8bfc6">getLeft</span>());
                <span style="color:#b8bfc6">tempNode</span>.<span style="color:#b8bfc6">setRight</span>(<span style="color:#b8bfc6">deleteNode</span>.<span style="color:#b8bfc6">getRight</span>());
                <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">parentNode</span>.<span style="color:#b8bfc6">getData</span>()<span style="color:#b8bfc6">==</span><span style="color:#b8bfc6">value</span>){<span style="color:#da924a">//删除的是root节点情况</span>
                    <span style="color:#b8bfc6">root</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">tempNode</span>;
                    <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"null"</span>);
                    <span style="color:#c88fd0">return</span>;
                }
                <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">parentNode</span>.<span style="color:#b8bfc6">getLeft</span>()<span style="color:#b8bfc6">==</span><span style="color:#b8bfc6">deleteNode</span>){<span style="color:#da924a">//删除的是feiroot节点</span>
                    <span style="color:#b8bfc6">parentNode</span>.<span style="color:#b8bfc6">setLeft</span>(<span style="color:#b8bfc6">tempNode</span>);
                }<span style="color:#c88fd0">else</span> {
                    <span style="color:#b8bfc6">parentNode</span>.<span style="color:#b8bfc6">setRight</span>(<span style="color:#b8bfc6">tempNode</span>);
                }
​
            }<span style="color:#c88fd0">else</span> {<span style="color:#da924a">//删除非叶子节点只有一颗子树情况</span>
<span style="color:#da924a">//                只有一颗子树直接让子树替换它</span>
                <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">parentNode</span>.<span style="color:#b8bfc6">getData</span>() <span style="color:#b8bfc6">==</span> <span style="color:#b8bfc6">value</span>){<span style="color:#da924a">//删除的是根节点</span>
                    <span style="color:#b8bfc6">root</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">deleteNode</span>.<span style="color:#b8bfc6">getLeft</span>();
                    <span style="color:#c88fd0">return</span>;
                }
                <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">parentNode</span>.<span style="color:#b8bfc6">getLeft</span>()<span style="color:#b8bfc6">==</span><span style="color:#b8bfc6">deleteNode</span>){
                    <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">deleteNode</span>.<span style="color:#b8bfc6">getLeft</span>()<span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
                        <span style="color:#b8bfc6">parentNode</span>.<span style="color:#b8bfc6">setLeft</span>(<span style="color:#b8bfc6">deleteNode</span>.<span style="color:#b8bfc6">getLeft</span>());
                    }<span style="color:#c88fd0">else</span> {
                        <span style="color:#b8bfc6">parentNode</span>.<span style="color:#b8bfc6">setLeft</span>(<span style="color:#b8bfc6">deleteNode</span>.<span style="color:#b8bfc6">getRight</span>());
                    }
​
                }<span style="color:#c88fd0">else</span> {
                    <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">deleteNode</span>.<span style="color:#b8bfc6">getLeft</span>()<span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span>){
                        <span style="color:#b8bfc6">parentNode</span>.<span style="color:#b8bfc6">setLeft</span>(<span style="color:#b8bfc6">deleteNode</span>.<span style="color:#b8bfc6">getLeft</span>());
                    }<span style="color:#c88fd0">else</span> {
                        <span style="color:#b8bfc6">parentNode</span>.<span style="color:#b8bfc6">setLeft</span>(<span style="color:#b8bfc6">deleteNode</span>.<span style="color:#b8bfc6">getRight</span>());
                    }
                }
            }
        }
​
    }
​
​
    <span style="color:#da924a">/**</span>
     <span style="color:#da924a">* 获取要删除节点的父节点</span>
     <span style="color:#da924a">* @param value 要删除的值</span>
     <span style="color:#da924a">* @return</span>
     <span style="color:#da924a">*/</span>
    <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">Nodes</span> <span style="color:#b8bfc6">getParentNode</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">value</span>) {
        <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">root</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>) {
            <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">err</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"当前二叉排序树没有节点!!!"</span>);
            <span style="color:#c88fd0">return</span> <span style="color:#84b6cb">null</span>;
        } <span style="color:#c88fd0">else</span> <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getData</span>() <span style="color:#b8bfc6">==</span> <span style="color:#b8bfc6">value</span>) {
            <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">out</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"要删除节点就是根节点"</span>);
            <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">root</span>;
        } <span style="color:#c88fd0">else</span> {
        <span style="color:#c88fd0">return</span>     <span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getParentNode</span>(<span style="color:#b8bfc6">value</span>);
        }
    }
​
    <span style="color:#da924a">/**</span>
     <span style="color:#da924a">* 获取要删除的节点</span>
     <span style="color:#da924a">*/</span>
    <span style="color:#c88fd0">public</span> <span style="color:#b8bfc6">Nodes</span> <span style="color:#b8bfc6">getDeleteNode</span>(<span style="color:#1cc685">int</span> <span style="color:#b8bfc6">value</span>){
        <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">root</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>){
            <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">err</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"当前二叉排序树没有节点!!!"</span>);
            <span style="color:#c88fd0">return</span> <span style="color:#84b6cb">null</span>;
        }<span style="color:#c88fd0">else</span> {
            <span style="color:#b8bfc6">Nodes</span> <span style="color:#b8bfc6">deleteNode</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getDeleteNode</span>(<span style="color:#b8bfc6">value</span>);
            <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">deleteNode</span>;
        }
    }
​
    <span style="color:#da924a">/**</span>
     <span style="color:#da924a">* 添加节点</span>
     <span style="color:#da924a">* @param nodes 传入要添加的节点</span>
     <span style="color:#da924a">*/</span>
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">add</span>(<span style="color:#b8bfc6">Nodes</span> <span style="color:#b8bfc6">nodes</span>){
        <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">root</span><span style="color:#b8bfc6">==</span><span style="color:#84b6cb">null</span>){
            <span style="color:#b8bfc6">root</span> <span style="color:#b8bfc6">=</span> <span style="color:#b8bfc6">nodes</span>;
        }<span style="color:#c88fd0">else</span>{
            <span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">add</span>(<span style="color:#b8bfc6">nodes</span>);
        }
    }
​
    <span style="color:#da924a">/**</span>
     <span style="color:#da924a">* 中序遍历</span>
     <span style="color:#da924a">*/</span>
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span> <span style="color:#b8bfc6">midTraversal</span>(){
        <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">root</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>){
            <span style="color:#b8bfc6">System</span>.<span style="color:#b8bfc6">err</span>.<span style="color:#b8bfc6">println</span>(<span style="color:#d26b6b">"当前二叉排序树没有节点!!!"</span>);
        }<span style="color:#c88fd0">else</span> {
            <span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">midTraversal</span>();
        }
    }
​
}</span></span>

5.平衡二叉树

平衡二叉树是在二叉排序树的基础上规定左子树的高度减去右子树的高度的绝对值不大于1可以是一颗空树,,这样的二叉树叫做平衡二叉树---》还是一颗二叉排序树

因为如果一棵二叉排序树没有左子树,只有右子树,那么构成的就像一个单链表,但是每次查找 二叉排序树都需要判断,效率不比如链表

类似这种情况

大致思路:

平衡二叉树是通过二叉排序树实现的,所以过程是在构建二叉平衡树的过程中进行AVL树的构建,一旦发现左子树于右子树的差值大于1,此时就需要进行左旋或者右旋让其变为一颗平衡二叉树。

左旋: 右子树高度过高

左旋案例

孤立root节点的第一个有节点

<span style="background-color:#333333"><span style="color:#da924a">//左旋</span>
<span style="color:#64ab8f">1.</span> <span style="color:#b8bfc6">新建一个节点newNode,让其值等于root节点值</span>
    <span style="color:#64ab8f">2.</span> <span style="color:#b8bfc6">让newNode的left指向root节点的左节点</span> <span style="color:#b8bfc6">newNode的right指向root右节点的left</span>
    <span style="color:#64ab8f">3.</span> <span style="color:#b8bfc6">让root节点的值等于root右节点的值</span>
    <span style="color:#64ab8f">4.</span> <span style="color:#b8bfc6">让root节点的left指向newNode</span>
    <span style="color:#64ab8f">5.</span> <span style="color:#b8bfc6">让root节点的right节点指向其右节点的right</span>
​
    <span style="color:#da924a">/**</span>
     <span style="color:#da924a">* 左旋</span>
     <span style="color:#da924a">*/</span>
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">void</span>  <span style="color:#8d8df0">leftRotate</span>(){
    <span style="color:#da924a">//        首先创建出一个新的节点       将当前根节点值赋给新创建的节点</span>
    <span style="color:#b8bfc6">averageNode</span> <span style="color:#b8bfc6">averageNode</span> <span style="color:#b8bfc6">=</span> <span style="color:#c88fd0">new</span> <span style="color:#b8bfc6">averageNode</span>(<span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getData</span>());
    <span style="color:#da924a">//       然后将新节点的left指向root节点的left</span>
    <span style="color:#b8bfc6">averageNode</span>.<span style="color:#b8bfc6">setLeft</span>(<span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getLeft</span>());
    <span style="color:#da924a">//        接着将ROOT节点的 值变为root节点右节点的值</span>
    <span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">setData</span>(<span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getRight</span>().<span style="color:#b8bfc6">getData</span>());
    <span style="color:#da924a">//        然后将root节点的left指向新节点</span>
    <span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">setLeft</span>(<span style="color:#b8bfc6">averageNode</span>);
    <span style="color:#da924a">//        root节点的右节点指向root左节点的右节点</span>
    <span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">setRight</span>(<span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getRight</span>().<span style="color:#b8bfc6">getRight</span>());
    <span style="color:#da924a">//        新节点的right指向root节点有节点的左节点</span>
    <span style="color:#b8bfc6">averageNode</span>.<span style="color:#b8bfc6">setRight</span>(<span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getRight</span>().<span style="color:#b8bfc6">getLeft</span>());
​
}</span>

右旋:左子树过高

右旋案例

孤立root节点的第一个左节点

<span style="background-color:#333333">1.新建一个节点newNode 让其值等于root节点
    2.让newNode节点的right指向root节点的right newNode节点的left指向root左节点的rught
    3.让root节点的值等于root节点的左节点值
    4.让root节点的left指向root左节点的left
    5. 让root节点的right指向newNode
    /**
     * 右旋
     * 左子树高度减去右子树高度大于一
     */
    public void rightRotate(){
    //        首先创建一个新的节点  将当前root节点赋值给新节点
    averageNode averageNode = new averageNode(root.getData());
    //        然后将新创建的节点的right指向root节点的右节点
    averageNode.setRight(root.getRight());
    //        接着将root节点的值变为root左节点的值
    root.setData(root.getLeft().getData());
    //        将root节点的left指向root左节点的left
    root.setLeft(root.getLeft().getLeft());
    //        root节点的right指向新节点
    root.setRight(averageNode);
    //        新节点的left指向root左节点的right
    averageNode.setLeft(root.getLeft().getRight());
}
</span>

左旋右旋判断中重要的是判断树的高度:

<span style="background-color:#333333">    <span style="color:#da924a">/**</span>
     <span style="color:#da924a">* 获取从该节点开始整棵树的高度</span>
     <span style="color:#da924a">* @return</span>
     <span style="color:#da924a">*/</span>
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">int</span> <span style="color:#8d8df0">getHeight</span>(){   
        <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">Math</span>.<span style="color:#b8bfc6">max</span>(<span style="color:#b8bfc6">left</span><span style="color:#b8bfc6">==</span><span style="color:#84b6cb">null</span><span style="color:#b8bfc6">?</span><span style="color:#64ab8f">0</span>:<span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">getHeight</span>(),<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span><span style="color:#b8bfc6">?</span><span style="color:#64ab8f">0</span>:<span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">getHeight</span>())<span style="color:#b8bfc6">+</span><span style="color:#64ab8f">1</span>;
    }
   <span style="color:#da924a">/**</span>
     <span style="color:#da924a">* 获取左子树的高度</span>
     <span style="color:#da924a">* @return</span>
     <span style="color:#da924a">*/</span>
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">int</span> <span style="color:#8d8df0">getLeftTreeHeight</span>(){
        <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">left</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>){
            <span style="color:#c88fd0">return</span>  <span style="color:#64ab8f">0</span>;
        }
        <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">left</span>.<span style="color:#b8bfc6">getHeight</span>();
    }
    <span style="color:#da924a">/**</span>
     <span style="color:#da924a">* 获取右子树的高度</span>
     <span style="color:#da924a">* @return</span>
     <span style="color:#da924a">*/</span>
    <span style="color:#c88fd0">public</span> <span style="color:#1cc685">int</span> <span style="color:#8d8df0">getRightTreeHeight</span>(){
        <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">right</span> <span style="color:#b8bfc6">==</span> <span style="color:#84b6cb">null</span>){
            <span style="color:#c88fd0">return</span>  <span style="color:#64ab8f">0</span>;
        }
        <span style="color:#c88fd0">return</span> <span style="color:#b8bfc6">right</span>.<span style="color:#b8bfc6">getHeight</span>();
    }</span>

双旋转:可能进行旋转后得到的二叉树还是一颗非平衡的二叉树,此时就需进行两次旋转

双循环案例

当需要进行左旋或者右旋时区判断是否需要进行双循环:如果进行左旋时,root节点的right的左子树高度大于右子树,此时就需要以root节点的right作为根节点进行右旋,然后在以root节点进行左旋;;;;;反之亦然

<span style="background-color:#333333"><span style="color:#da924a">//            添加后判断是否需要进行左旋</span>
         <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">getRightTreeHeight</span>()<span style="color:#b8bfc6">-</span><span style="color:#b8bfc6">getLeftTreeHeight</span>() <span style="color:#b8bfc6">></span><span style="color:#64ab8f">1</span>) {
<span style="color:#da924a">//                判断是否需要进行双旋转</span>
<span style="color:#da924a">//                如果root右节点的左子树高度大于右子树,此时先以root右节点为根节点进行一次右旋转</span>
             <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getRight</span>()<span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span> <span style="color:#b8bfc6">&&</span> <span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getRight</span>().<span style="color:#b8bfc6">getLeftTreeHeight</span>()<span style="color:#b8bfc6">></span> <span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getRight</span>().<span style="color:#b8bfc6">getRightTreeHeight</span>()){
                 <span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getRight</span>().<span style="color:#b8bfc6">rightRotate</span>();
             }
             <span style="color:#b8bfc6">leftRotate</span>();
             <span style="color:#c88fd0">return</span>;
         }
         <span style="color:#da924a">//            添加后判断是否选哟进行右旋</span>
<span style="color:#da924a">//            判断双旋转</span>
<span style="color:#da924a">//            如果root左节点的右子树大于左子树。那么需要以root左节点为根进行一次左旋转</span>
         <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">getLeftTreeHeight</span>()<span style="color:#b8bfc6">-</span><span style="color:#b8bfc6">getRightTreeHeight</span>() <span style="color:#b8bfc6">></span><span style="color:#64ab8f">1</span>) {
             <span style="color:#c88fd0">if</span> (<span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getLeft</span>()<span style="color:#b8bfc6">!=</span><span style="color:#84b6cb">null</span> <span style="color:#b8bfc6">&&</span> <span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getLeft</span>().<span style="color:#b8bfc6">getRightTreeHeight</span>()<span style="color:#b8bfc6">></span> <span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getLeft</span>().<span style="color:#b8bfc6">getLeftTreeHeight</span>()){
                 <span style="color:#b8bfc6">root</span>.<span style="color:#b8bfc6">getLeft</span>().<span style="color:#b8bfc6">leftRotate</span>();
             }
             <span style="color:#b8bfc6">rightRotate</span>();
         }</span>

9.2 多路查找树

多路查找树是二叉树的演进,是为了弥补二叉树的不足,假设数据有海量,二叉树一个节点只能存放一个数据,数据读取每次都需要进行I/O操作,随着数据的增多,树的高度也会增加,查找效率并不高;;;;此时就出现了多路查找树,每个节点可以存多个数据,每个节点也可以有多个子节点;;;比如2-3树,2-3-4树,B树,B+树,B*树等

参考网址:

[多路查找树 | 数据结构与算法 系列教程(笔记) (zq99299.github.io)]:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值