摘要:自查找二叉樹起,可以說種族崛起了。編碼不善言辭,為敬首先代碼定義出查找二叉樹的結構結構,存儲業務數據左節點右節點注意查找二叉樹的結構可類比數據庫表結構理解。
載一棵小樹苗,精心培育,總有一天會長成參天大樹結構
????????????????比如查找二叉、AVL、B + *、紅黑……
繼線性結構之后,人們之所以又發明了樹形結構,是為了方便查找。普通樹隨便生長,看著就眼暈,除了和自然界的樹結構相似對得起Tree這名號,沒太大價值,更別提方便查找了。
自查找二叉樹起,可以說種族崛起了。結構上:從根節點起,小于父節點的在左,大于父節點的在右。如此結構,本身就是有序的,以中序遍歷(左->中->右)的方式走一遍,很方便把值從小到大排序。
以下給出這種樹的關鍵方法的邏輯,以及具體的編碼實現。
編碼(不善言辭,coding為敬……)
首先代碼定義出查找二叉樹的結構:
// 結構 public class BinaryNode{ // key private Integer id; // val,存儲業務數據 private V val; // 左節點 private BinaryNode leftNode; // 右節點 private BinaryNode rightNode; public BinaryNode(Integer id, V val, BinaryNode leftNode, BinaryNode rightNode) { this.id = id; this.val = val; this.leftNode = leftNode; this.rightNode = rightNode; } }
注意: 查找二叉樹的結構可類比數據庫表結構理解。 對于mysql中采用innodb引擎創建的表而言,以id為主鍵的表數據會自動加持索引。(實際上索引是B+ tree結構,可視作{{BANNED}}版的查找樹) 這也是上面的代碼結構定義中,key采用id命名的原因,val則可視為該數據庫表的其它字段。新增節點
每次新增節點,會從根節點開始,根據值的大小,尋找自己的位置。
舉個例子,上圖的樹再增加一個節點35,會經歷如下心路歷程:
與根節點50比較,新節點35較小,置左;很不幸,左邊已經有節點30雄踞。
新節點35繼續與節點30比較。其實此時可以忽略根節點50,把左子樹視作一顆新樹,節點30視作新的根節點……沒錯,就是遞歸,直到最終找到一個空位置,方安身立命。
代碼實現如下:
//新增,先不考慮id重復的問題 //@param id:新增節點的key //@param val:新增節點的值 BinaryNodeadd(Integer id,V val,BinaryNode tree){ //該位置無節點,安身立命 if(tree == null){ tree = new BinaryNode<>(id,val,null,null); } //遞歸:新節點id大于當前節點,新節點置右 if(id>tree.id){ tree.rightNode = add(id,val,tree.rightNode); } //遞歸:新節點id小于當前節點,新節點置左 if(id 范圍查找 正如之前提過的,查找二叉樹的優勢就在于范圍查找。
怎么在一顆查找二叉樹中找到min>=且<=max的全部值?具體步驟如下:
當前節點與min比較,如果大于min,則遞歸查看它的左節點;如果它沒有左節點,結束遞歸
當前節點在min和max范圍內,放入結果集
當前節點與max比較,如果小于max,則遞歸查看它的右節點;如果它沒有右節點,結束遞歸
CollectionsearchRange(Integer min, Integer max, Collection collection,BinaryNode tree){ //當前節點與min比較,如果大于min,遞歸查看當前節點的左節點(如果有左節點的話) if(min =tree.getId()){ collection.add(tree.getVal()); } //當前節點與max比較,如果小于max,遞歸查看當前節點的右節點(如果有右節點的話) if(tree.getId() 刪除節點 刪除節點相對比較復雜,涉及到子樹銜接問題,分幾種情況:
無子:被刪節點沒有子節點(葉子節點),直接移除就好。
單子:直接頂替被刪除節點的位置。
雙子
BinaryNoderemove(Integer id,BinaryNode tree){ if(tree==null){ return null; } if(id>tree.getId()){ tree.rightNode = remove(id,tree.rightNode); } if(id min = findMin(tree.rightNode); //找到最小節點 tree.id = min.id; tree.val = min.val; tree.rightNode = remove(tree.id,tree.rightNode); } //無子 else { tree = null; } } return tree; } 注意: 這里有個小訣竅。在做節點替換時(`32`替換`30`),可直接修改id和val,這樣就不需要修改引用了!不足試想一下這種情況,查找二叉樹在新增節點時,假如一直增加更小的節點,我們將得到一個只有左節點的查找二叉樹(雖然二叉不起來)。這樣的樹與鏈表又有什么區別呢?這種極端情況下,就失去了樹的優勢了。
也就是說,在新增或刪除操作過程中,樹越不均衡(左傾或右傾),越影響查找效率!如何彌補這種不足?需要保持樹的平衡,敬請期待AVL樹——平衡的查找二叉樹。
附錄完整代碼實現見我的git練習項目com.evolution.tree包下,地址:evolution 暗夜君王的各種demo練習
啰嗦幾句,demo項目中查找二叉樹的實現com.evolution.tree.BinaryNodeBak,模擬了數據庫表,會多一些id的唯一性驗證。另外,還增加了中序遍歷實現sort()方法。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/72476.html
摘要:因此,根據題目給出的先序遍歷和中序遍歷,可以畫出二叉樹選參考數據結構與算法描述實現二叉樹算法淺談數據結構二叉樹慕課網實現二叉樹算法前端樹控件騰訊軟件開發面試題 內容銜接上一章 數據結構與算法:常見排序算法 內容提要 什么是樹 - 為什么使用樹 二叉樹 二叉查找樹 紅黑樹 B、B+樹 堆 伸展樹 樹 可以點擊鏈接感受下筆者用d3.js畫的tree https://codepen...
摘要:同樣結點樹的二叉樹,完全二叉樹的深度最小。二叉樹每個結點最多有兩個孩子,所以為它設計一個數據域和兩個指針域是比較自然的想法,我們稱這樣的鏈表叫做二叉鏈表。 二叉樹的概念 二叉樹(Binary Tree)是n(n>=0)個結點的有限集合,該集合或者為空集(空二叉樹),或者由一個根結點和兩棵互不相交的、分別稱為根結點的左子樹和右子樹的二叉樹組成。 showImg(https://seg...
摘要:前言可能有一部分人沒有讀過我上一篇寫的二叉堆,所以這里把二叉樹的基本概念復制過來了,如果讀過的人可以忽略前面針對二叉樹基本概念的介紹,另外如果對鏈表數據結構不清楚的最好先看一下本人之前寫的數據結構鏈表二叉樹二叉樹是一種樹形結構,它的特點是 前言 可能有一部分人沒有讀過我上一篇寫的二叉堆,所以這里把二叉樹的基本概念復制過來了,如果讀過的人可以忽略前面針對二叉樹基本概念的介紹,另外如果對鏈...
摘要:是棧,它繼承于。滿二叉樹除了葉結點外每一個結點都有左右子葉且葉子結點都處在最底層的二叉樹。沒有鍵值相等的節點。這是數據庫選用樹的最主要原因。 在我們學習Java的時候,很多人會面臨我不知道繼續學什么或者面試會問什么的尷尬情況(我本人之前就很迷茫)。所以,我決定通過這個開源平臺來幫助一些有需要的人,通過下面的內容,你會掌握系統的Java學習以及面試的相關知識。本來是想通過Gitbook的...
摘要:所以,如果中序遍歷二叉搜索樹,會得到一個有序的數據,時間復雜度是,所以二叉搜索樹又叫做二叉排序樹。所以,我們需要一種方式來維持二叉樹的平衡,最好是將其維持為滿二叉樹或者完全二叉樹,這就是后面會說到的平衡二叉查找樹,常見的有樹,紅黑樹。 1. 概述 前面的文章說到了二叉樹,其實今天講的二叉搜索(查找)樹就是二叉樹最常用的一種形式,它支持高效的查找、插入、刪除操作,它的定義是這樣的:對于樹...
閱讀 908·2021-09-03 10:42
閱讀 1518·2019-08-30 15:56
閱讀 1453·2019-08-29 17:27
閱讀 879·2019-08-29 15:25
閱讀 3166·2019-08-26 18:27
閱讀 2487·2019-08-26 13:41
閱讀 1895·2019-08-26 10:39
閱讀 1585·2019-08-23 18:36