1. 程式人生 > >二叉樹系列5:建立二叉搜尋樹

二叉樹系列5:建立二叉搜尋樹

二叉查詢樹(Binary Search Tree),(又:二叉搜尋樹,二叉排序樹)它或者是一棵空樹,或者是具有下列性質的二叉樹: 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值; 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值; 它的左、右子樹也分別為二叉排序樹。

二叉排序樹的查詢過程和次優二叉樹類似,通常採取二叉連結串列作為二叉排序樹的儲存結構。中序遍歷二叉排序樹可得到一個關鍵字的有序序列,一個無序序列可以通過構造一棵二叉排序樹變成一個有序序列,構造樹的過程即為對無序序列進行排序的過程。每次插入的新的結點都是二叉排序樹上新的葉子結點,在進行插入操作時,不必移動其它結點,只需改動某個結點的指標,由空變為非空即可。搜尋,插入,刪除的複雜度等於樹高,O(log(n))。

1 插入

    /**
     * 二叉樹的插入操作
     */
    public boolean add(TreeNode t, int val) {
        if (t == null) {
            t = new TreeNode(val);
            return true;
        }

        // 如果父節點等於要插入的值,則說明該值已存在,所以不新建任何節點,返回false
        if (t.val == val) {
            return false;
        }
        // 如果val 小於 父節點的值,則新節點應該為其左子樹中
else if (val < t.val) { // 如果左子樹為空,則新建節點, 並將這個節點設為左孩子 if (t.left == null) { t.left = new TreeNode(val); return true; } else { return add(t.left, val); } } else { if (t.right == null
) { t.right = new TreeNode(val); return true; } else { return add(t.right, val); } } } /** 非遞迴中序遍歷二叉樹 */ public ArrayList<TreeNode> inorderTraversal(TreeNode t) { if (t == null) { return null; } Stack<TreeNode> stack = new Stack<>(); ArrayList<TreeNode> aList = new ArrayList<>(); TreeNode p = t; while (p != null || !stack.isEmpty()) { // 如果目前訪問的節點不為空,則嘗試先訪問它的左子樹 if (p != null) { stack.push(p); // 開始訪問左子樹 p = p.left; } // 如果 p為null說明訪問的左節點為空,將先前壓入棧的父節點pop,列印,並且開始訪問右子樹 else { p = stack.pop(); // 列印父節點 aList.add(p); // 開始訪問右子樹 p = p.right; } } return aList; }

2 刪除

  • 首先,找到這個要刪除的節點
  • 如果它是葉子節點就可以直接刪除
  • 如果它只有一個子節點,則讓它的子節點代替它的位置就好了
  • 如果它有兩個子節點,則找到右子樹的最小值,這個值一定是一個葉子,所以先將這個最小值復值給要刪除的節點的值域,然後刪除這個最小值節點,由於是葉子節點,所以很容易刪除
    private TreeNode remove(TreeNode t, int val) {
        if (t == null) {
            return null;
        }

        // 第一步是,找到要刪除的節點
        // 小於0,說明該節點在左子樹中
        if (val - t.val < 0) {
            t.left = remove(t.left, val);
        }
        // 大於0,說明該節點在右子樹中
        else if (val - t.val > 0) {
            t.right = remove(t.right, val);
        }
        // 等於0,說明找到了
        else {
            // 如果這是一個葉子,則直接刪除這個節點
            if (t.left == null && t.right == null) {
                t = null;
            }
            // 如果該節點有一個兒子
            else if (t.left == null ^ t.right == null) {
                return t = (t.left != null ? t.left : t.right);
            }
            // 如果有兩個兒子
            else if (t.left != null && t.right != null) {
                TreeNode minNode = findMin(t.right);
                t.val = minNode.val;
                t.right = remove(t.right, minNode.val);
            }
        }

        return t;
    }
    private TreeNode findMin(TreeNode t) {
        if (t == null) {
            return null;
        } else if (t.left == null) {
            return t;
        } else {
            return findMin(t.left);
        }
    }

3 測試

public class Main {

    public static void main(String[] args) {
        TreeNode binarySearchTree = new TreeNode(8);
        BinaryTreeTest testTree = new BinaryTreeTest();
        testTree.add(binarySearchTree, 22);
        testTree.add(binarySearchTree, 3);
        testTree.add(binarySearchTree, 13);
        testTree.add(binarySearchTree, 5);
        testTree.add(binarySearchTree, 7);
        testTree.add(binarySearchTree, 27);
        System.out.println("\n通過插入新建了一個二叉搜尋樹,然後輸出其中序遍歷的結果");
        ArrayList<TreeNode> aList = testTree.inorderTraversal(binarySearchTree);
        for (TreeNode treeNode : aList) {
            System.out.printf("%-5d", treeNode.val);
        }

        testTree.remove(binarySearchTree, 7);
        System.out.println("\n刪除已經存在的 7");
        aList = testTree.inorderTraversal(binarySearchTree);
        for (TreeNode treeNode : aList) {
            System.out.printf("%-5d", treeNode.val);
        }

    }

}

輸出:


通過插入新建了一個二叉搜尋樹,然後輸出其中序遍歷的結果
3    5    7    8    13   22   27   
刪除已經存在的 7
3    5    8    13   22   27   

相關推薦

系列5建立搜尋

二叉查詢樹(Binary Search Tree),(又:二叉搜尋樹,二叉排序樹)它或者是一棵空樹,或者是具有下列性質的二叉樹: 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值; 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值; 它的

劍指offer第55.5平衡

題目描述 輸入一棵二叉樹,判斷該二叉樹是否是平衡二叉樹。 class Solution: def IsBalanced_Solution(self, pRoot): # write code here if not pRoot:

系列3 的路徑問題

1 輸出根節點到葉子節點的路徑 TreeNode.java package BinaryTree; public class TreeNode { int val; TreeNode left; TreeNode right

java由先根中根遍歷序列建立,由標明空子建立,有完全順序儲存結構建立鏈式儲存結構

    //由先根和中根遍歷建立二叉樹 public class bitree{     public bitree(String preorder,String inorder,int preindex,int in

【LeetCode & 劍指offer刷題】題934 中和為某一值的路徑(112. Path Sum)

【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...) 112. Path Sum Given a binary tree and a sum, determine if the tree has a root-to-leaf path suc

【LeetCode & 劍指offer刷題】題727 的映象

【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...) 27 二叉樹的映象   題目描述 操作給定的二叉樹,將其變換為源二叉樹的映象。 輸入描述: 二叉樹的映象

遍歷的應用輸出所有葉結點和求高度

利用二叉樹的遍歷方法,我們可以求得一棵二叉樹的很多東西,例如我們可以遍歷求得一棵二叉樹的所有葉結點,到我們找到一個結點的左右子樹都為空了,它就是其中一個葉結點,我們把它儲存起來,在遍歷完一棵二叉樹後,我們就可以找到所有的葉結點。同理,我們也可以通過遍歷一棵二叉樹的所有節點後,

CentOS 基本指令()——Linux 使用者管理建立使用者與變更使用者組

首先我們使用 useradd 使用者名稱 命令建立一個新使用者: 然後需要繼續為新使用者建立密碼和主目錄: useradd -d "/home/username" -m passwd username 使用如下命令可以將使用者新增到不同的使用者組: usermod -

C++遊戲系列5不止有一件武器

location ref 初始 .text isalive urn lan dead then 很多其它見:C++遊戲系列文件夾 知識點:對象數組作為數據成員 改進:每一個角色所持有的武器不僅僅一件,故持有的武器,用了對象數組來表示,當然,也能

Azure手把手系列5Azure帳戶和訂閱

雲計算 雲服務 對於Azure來說,帳戶和訂閱是非常重要的。很多朋友都不明白Azure的帳戶和訂閱的關系,今天我們就通過簡單通俗易懂的方式來介紹一下Azure的帳戶和訂閱。 ? ?要使用Azure服務,必須擁有一個Azure 的帳戶,還必須擁有Azure訂閱。這裏我們以身份證和手機SIM卡來介紹Az

go基礎系列(5)陣列

瞭解Python、Perl、JavaScript的人想必都知道它們的陣列是動態的,可以隨需求自動增大陣列長度。但Go中的陣列是固定長度的,陣列一經宣告,就無法擴大、縮減陣列的長度。但Go中也有類似的動態"陣列",稱為slice資料結構,在下一篇文章會詳細解釋它。 Go中的陣列是slice和map兩種資料型別的

強化學習系列5有模型的策略迭代方法

1. 策略迭代演算法 這裡策略迭代使用的是表格法,基本步驟是: 用字典儲存每個s的v值 根據v值來選骰子 策略迭代的步驟為: 初始化 V

【LeetCode & 劍指offer刷題】5110 Balanced Binary Tree

【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...) 110. Balanced Binary Tree Given a binary tree, determine if it is height-balanced.

windows bat系列5檢視監聽埠&終止程序

1.    netstat說明:顯示協議統計和當前 TCP/IP 網路連線。其相關命令列引數如下: -a 顯示所有連線和偵聽埠。 -b 顯示在建立每個連線或偵聽埠時涉及的可執行程式。 在某些情況下,已

爬蟲系列5scrapy動態頁面爬取的另一種思路

前面有篇文章給出了爬取動態頁面的一種思路,即應用Selenium+Firefox(參考《scrapy動態頁面爬取》)。但是selenium需要執行本地瀏覽器,比較耗時,不太適合大規模網頁抓取。 事實上,還有一種執行效率更高的方法。就是事先分析js發出的GET或者POST請求

VSTO之旅系列(四)建立Word解決方案

本專題概要 引言 Word物件模型 建立Word外接程式 小結 一、引言 在上一個專題中主要為大家介紹如何自定義我們的Excel 介面的,然而在這個專題中,我將為大家介紹如何用VSTO來建立Word專案,對於Word的VSTO開發和Excel的開發很類似,你同樣也可以為Word自定義

SSO單點登入系列5cas單點登入增加驗證碼功能完整步驟

本篇教程cas-server端下載地址:解壓後,直接放到tomcat的webapp目錄下就能用了,不過你需要登入的話,要修改資料來源,C:\tomcat7\webapps\casServer\WEB-INF\deployerConfigContext.xml,嗯。地址

SQL Server溫故系列(5)SQL 查詢之分組查詢 GROUP BY

1、GROUP BY 與聚合函式 2、GROUP BY 與 HAVING 3、GROUP BY 擴充套件分組 3.1、GROUP BY ROLLUP 3.2、GROUP BY CUBE 3.3、GROUP BY GROUPING SETS 4、GROUP BY 擴充套件函式 4.1、GROUPING

HelloDjango 系列教程建立 Django 部落格的資料庫模型

文中涉及的示例程式碼,已同步更新到 HelloGitHub-Team 倉庫 設計部落格的資料庫表結構 部落格最主要的功能就是展示我們寫的文章,它需要從某個地方獲取部落格文章資料才能把文章展示出來,通常來說這個地方就是資料庫。我們把寫好的文章永久地儲存在資料庫裡,當用戶訪問我們的部落格時,django

夯實Java基礎系列5Java檔案和Java包結構

目錄 Java中的包概念 包的作用 package 的目錄結構 設定 CLASSPATH 系統變數 常用jar包 java軟體包的型別 dt.jar rt.jar *.java檔案的奧祕 *.Java檔案簡介 為什麼一個java原始檔中只能有一個public類? Main方法 外部類的訪問許可權