java學習之數據結構:四、樹(代碼補充)

這部分主要是用代碼實現有序二叉樹、樹遍歷、刪除節點

目錄

1.構建有序二叉樹

1.1原理

?1.2插入實現

2.廣度優先遍歷--隊列實現

3.深度優先遍歷--遞歸實現

3.1先序遍歷

3.2中序遍歷

3.3后序遍歷

4.刪除

4.1刪除葉子節點

4.2刪除有一棵子樹的節點

4.3刪除有兩棵子樹的節點

5.整體代碼


1.構建有序二叉樹

1.1原理

左邊節點值小于父節點,右邊節點值大于父節點,看下圖

?1.2插入實現

當傳入value值時,判斷root節點是否為空:空的話建立新節點做root;不空,建立一個中間節點index,然后循環按照插入原理判斷插到哪,代碼如下:

 public void insert(int value){Node node = new Node(value);if(root==null){root = node;return;}Node index = root;while(true) {if(index.value>value) {//要插入的節點值小if(index.left==null) {//插入index.left=node;return;}index=index.left;}else{//要插入的節點值大if(index.right==null){index.right=node;return;}index=index.right;}}

2.廣度優先遍歷--隊列實現

廣度優先遍歷就是層次遍歷,使用隊列實現。當隊列中進入一個新節點,輸出后就找這個節點的左右孩子入隊。

代碼如下:

    public void levelOrder() {Queue<Node> queue = new LinkedList<Node>();if(root!=null) {queue.add(root);}Node index;while (!queue.isEmpty()){index = queue.poll();System.out.print(index.value+Messages.getString("BinaryTree.0")); //$NON-NLS-1$if(index.left!=null){queue.add(index.left);}if(index.right!=null) {queue.add(index.right);}}System.out.println();}

3.深度優先遍歷--遞歸實現

3.1先序遍歷

就是根-左-右的順序,使用遞歸實現,代碼如下:

    /** 先序遍歷*/public void beforeOrder(Node node){if(node==null) {return;}System.out.print(node.value+Messages.getString("BinaryTree.1"));beforeOrder(node.left);beforeOrder(node.right);}

3.2中序遍歷

使用左-根-右順序

    /** 中序遍歷*/public void inOrder(Node node){if(node==null){return;}inOrder(node.left);System.out.print(node.value+Messages.getString("BinaryTree.2")); //$NON-NLS-1$inOrder(node.right);}

3.3后序遍歷

使用左-右-根順序,代碼如下:

    /** 后序遍歷*/public void afterOrder(Node node) {if(node==null) {return;}afterOrder(node.left);afterOrder(node.right);System.out.print(node.value+Messages.getString("BinaryTree.3")); }

4.刪除

刪除比較復雜,要分三種情況:

4.1刪除葉子節點

  1. 找到目標節點:在二叉搜索樹中定位要刪除的目標節點target?。
  2. 找到父節點:確定target節點的父節點parent?。
  3. 判斷父節點情況
    • 若無父節點,意味著target是根節點,直接將根節點置為null?。
    • 若有父節點,判斷targetparent的左子還是右子:是左子就執行parent.left = null?;是右子就執行parent.right = null?。

需要額外寫一個函數來尋找父節點,代碼如下:

    /*** 找目標值的父節點*/public Node searchParent(int value) {if(root==null) {return null;}Node index = root;while (index!=null) {if((index.left!=null&&index.left.value==value)||(index.right!=null&&index.right.value==value)) {return index;}else if (index.value>value) {index=index.left;}else {index = index.right;}}return null;}

這部分代碼如下:

		if(target.left==null&&target.right==null) {//葉子節點//沒有父節點if(parent==null) {root=null;return;}//有父節點if(parent.left!=null&&parent.left.value==value) {parent.left=null;}else {parent.right=null;}}

4.2刪除有一棵子樹的節點

  1. 找到目標節點:確定要刪除的節點target?。
  2. 找到父節點:找到target節點的父節點parent?。
  3. 判斷父節點和子樹情況
    • 若無父節點,即target是根節點,若target有左子樹,讓根節點指向其左子樹(root = root.left?);若有右子樹,讓根節點指向其右子樹(root = root.right?)。
    • 若有父節點,先確定targetparent的左子還是右子,再根據target自身有左子樹還是右子樹,調整parent相應子樹指針(如parent.left = target.left?或parent.right = target.right?)。

代碼如下:

			//有一棵子樹的節點//沒有父節點if(parent==null) {//目標節點有左子樹還是右子樹if(target.left!=null) {root = root.left;}else {root=root.right;}return;}//有父節點//判斷目標節點是父節點的左孩子還是右孩子if(parent.left!=null&&parent.left.value==value) {//左孩子//目標節點有左子樹還是右子樹if(target.left!=null) {parent.left = target.left;}else {parent.left = target.right;}}else {//右孩子//目標節點有左子樹還是右子樹if(target.left!=null) {parent.right = target.left;}else {parent.right = target.right;}}

4.3刪除有兩棵子樹的節點

  1. 找到目標節點:定位要刪除的節點target?。
  2. 替換節點選擇:獲取target左子樹的最大值節點或者右子樹的最小值節點作為替換節點。
  3. 刪除目標節點:用選定的替換節點替代target節點的位置 ,并處理好相關子樹連接關系(如parent.left = target.right?或parent.right = target.left?等)。

需要額外寫一個判斷最小值的函數:

	/*** 找樹當中的最小值*/public int min(Node node) {Node index = node;while(index.left!=null) {index=index.left;}return index.value;}

?

代碼如下:

 if(target.left!=null&&target.right!=null) {//有兩棵子樹的節點int minVal = min(target.right);delete(minVal);target.value = minVal;}

5.整體代碼

代碼如下:

package com.qcby.樹;import java.util.LinkedList;
import java.util.Queue;public class BinaryTree {Node root;/*** 插入*/public void insert(int value){Node node = new Node(value);if(root==null){root = node;return;}Node index = root;while(true) {if(index.value>value) {//要插入的節點值小if(index.left==null) {//插入index.left=node;return;}index=index.left;}else{//要插入的節點值大if(index.right==null){index.right=node;return;}index=index.right;}}}/** 廣度優先遍歷*/public void levelOrder() {Queue<Node> queue = new LinkedList<Node>();if(root!=null) {queue.add(root);}Node index;while (!queue.isEmpty()){index = queue.poll();System.out.print(index.value+Messages.getString("BinaryTree.0")); //$NON-NLS-1$if(index.left!=null){queue.add(index.left);}if(index.right!=null) {queue.add(index.right);}}System.out.println();}/** 先序遍歷*/public void beforeOrder(Node node){if(node==null) {return;}System.out.print(node.value+Messages.getString("BinaryTree.1")); //$NON-NLS-1$beforeOrder(node.left);beforeOrder(node.right);}/** 中序遍歷*/public void inOrder(Node node){if(node==null){return;}inOrder(node.left);System.out.print(node.value+Messages.getString("BinaryTree.2")); //$NON-NLS-1$inOrder(node.right);}/** 后序遍歷*/public void afterOrder(Node node) {if(node==null) {return;}afterOrder(node.left);afterOrder(node.right);System.out.print(node.value+Messages.getString("BinaryTree.3")); //$NON-NLS-1$}/** 查找*/public Node search(int value) {if(root==null) {return null;}Node index = root;while (index!=null) {if(index.value==value){return index;}else if(index.value>value) {index = index.left;}else {index=index.right;}}return null;}/*** 找目標值的父節點*/public Node searchParent(int value) {if(root==null) {return null;}Node index = root;while (index!=null) {if((index.left!=null&&index.left.value==value)||(index.right!=null&&index.right.value==value)) {return index;}else if (index.value>value) {index=index.left;}else {index = index.right;}}return null;}/*** 找樹當中的最小值*/public int min(Node node) {Node index = node;while(index.left!=null) {index=index.left;}return index.value;}/*** 刪除*/public void delete(int value){if(root==null) {System.out.println(Messages.getString("BinaryTree.4")); return;}//找目標節點Node target = search(value);if(target==null) {System.out.println(Messages.getString("BinaryTree.5")); return;}//找目標節點的父節點Node parent = searchParent(value);//三種情況,分情況討論if(target.left==null&&target.right==null) {//葉子節點//沒有父節點if(parent==null) {root=null;return;}//有父節點if(parent.left!=null&&parent.left.value==value) {parent.left=null;}else {parent.right=null;}}else if(target.left!=null&&target.right!=null) {//有兩棵子樹的節點int minVal = min(target.right);delete(minVal);target.value = minVal;}else {//有一棵子樹的節點//沒有父節點if(parent==null) {//目標節點有左子樹還是右子樹if(target.left!=null) {root = root.left;}else {root=root.right;}return;}//有父節點//判斷目標節點是父節點的左孩子還是右孩子if(parent.left!=null&&parent.left.value==value) {//左孩子//目標節點有左子樹還是右子樹if(target.left!=null) {parent.left = target.left;}else {parent.left = target.right;}}else {//右孩子//目標節點有左子樹還是右子樹if(target.left!=null) {parent.right = target.left;}else {parent.right = target.right;}}}}@Overridepublic String toString() {return "BinaryTree [root=" + root + "]";}}

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/904293.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/904293.shtml
英文地址,請注明出處:http://en.pswp.cn/news/904293.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

架構進階:什么是數據架構,如何理解數據架構?(華為)

數據架構是企業架構的重要組成部分,DAMA、IBM 及國內大廠對其定義各有側重。它包含數據資產目錄、數據標準、數據模型和數據分布四個組件。數據資產目錄可梳理企業數據資產,數據標準統一數據含義和規則,數據模型反映業務對象關聯關系,數據分布呈現數據流動情況。數據架構是…

Unity SpriteEditor(精靈圖片編輯器)

&#x1f3c6; 個人愚見&#xff0c;沒事寫寫筆記 &#x1f3c6;《博客內容》&#xff1a;Unity3D開發內容 &#x1f3c6;&#x1f389;歡迎 &#x1f44d;點贊?評論?收藏 &#x1f50e;SpriteEditor&#xff1a; 精靈圖片編輯器 &#x1f4cc;用于編輯2D游戲開發中使用的Sp…

【網絡原理】從零開始深入理解HTTP的報文格式(一)

本篇博客給大家帶來的是網絡HTTP協議的知識點, 重點介紹HTTP的報文格式. &#x1f40e;文章專欄: JavaEE初階 &#x1f680;若有問題 評論區見 ? 歡迎大家點贊 評論 收藏 分享 如果你不知道分享給誰,那就分享給薯條. 你們的支持是我不斷創作的動力 . 王子,公主請閱&#x1f68…

ElasticSearch深入解析(九):Object、Nested、Flattened類型

文章目錄 一、Object 類型&#xff1a;默認的嵌套對象處理方式核心原理典型場景關鍵限制 二、Nested 類型&#xff1a;解決嵌套數組的關聯查詢核心原理典型場景使用示例注意事項 三、Join 類型&#xff1a;跨文檔的父子關聯核心原理典型場景使用示例注意事項 四、Flattened 類型…

36、C#中的?法聲明參數關鍵字params,ref,out的意義及?法

在C#中&#xff0c;params、ref 和 out 是方法聲明中用于修飾參數的關鍵字&#xff0c;它們各自有不同的用途和語義。以下是它們的詳細說明和用法&#xff1a; 1、 params 關鍵字 意義 params 允許方法接受可變數量的參數&#xff0c;這些參數會被編譯為一個數組。適用于參數…

【大模型實戰篇】華為信創環境采用vllm部署QwQ-32B模型

1. 背景 本文分享在華為昇騰機器上部署QwQ-32B模型的實踐。 首先華為自己是提供了一套在信創機器&#xff08;NPU&#xff09;上部署模型的方案【1】&#xff0c;但是部署之后&#xff0c;測試發現會有輸出截斷的現象。QwQ-32B本身是支持128k的最大上下文長度&#xff0c;定位…

前端面經-VUE3篇(二)--vue3基礎知識(二)計算屬性(computed)、監聽屬性(Watch)

一、計算屬性(computed) 計算屬性&#xff08;Computed Properties&#xff09;是 Vue 中一種特殊的響應式數據&#xff0c;它能基于已有的響應式數據動態計算出新的數據。 計算屬性有以下特性&#xff1a; 自動緩存&#xff1a;只有當它依賴的響應式數據發生變化時&#xff…

[預備知識] 5. 優化理論(一)

優化理論 梯度下降&#xff08;Gradient Descent&#xff09; 數學原理與可視化 梯度下降是優化領域的基石算法&#xff0c;其核心思想是沿負梯度方向迭代更新參數。數學表達式為&#xff1a; θ t 1 θ t ? α ? θ J ( θ t ) \theta_{t1} \theta_t - \alpha \nabla…

大模型微調Fine-tuning:從概念到實踐的全面解析

目錄 引言 一、什么是大模型微調&#xff1f; 1.1 預訓練與微調的區別 1.2 微調的技術演進 二、為什么需要微調&#xff1f; 2.1 解決大模型的固有局限 2.2 微調的優勢 三、主流微調方法 3.1 全參數微調 3.2 參數高效微調&#xff08;PEFT&#xff09; 四、微調實踐指…

Docker 使用下 (二)

Docker 使用下 &#xff08;二&#xff09; 文章目錄 Docker 使用下 &#xff08;二&#xff09;前言一、初識Docker1.1 、Docker概述1.2 、Docker的歷史1.3 、Docker解決了什么問題1.4 、Docker 的優點1.5 、Docker的架構圖 二、鏡像三、容器四、數據卷4.1、數據卷的概念4.2 、…

洛谷P12238 [藍橋杯 2023 國 Java A] 單詞分類

[Problem Discription] \color{blue}{\texttt{[Problem Discription]}} [Problem Discription] Copy from luogu. [Analysis] \color{blue}{\texttt{[Analysis]}} [Analysis] 既然都是字符串前綴的問題了&#xff0c;那當然首先就應該想到 Trie \text{Trie} Trie 樹。 我們可…

pta作業中有啟發性的程序題

1 【知識點】&#xff1a;多態 函數接口定義&#xff1a; 以Student為基類&#xff0c;構建GroupA, GroupB和GroupC三個類 裁判測試程序樣例&#xff1a; #include<iostream> #include <string> using namespace std;/* 請在這里填寫答案 */int main() {const …

Scrapy框架之CrawlSpider爬蟲 實戰 詳解

CrawlSpider 是 Scrapy 框架中一個非常實用的爬蟲基類&#xff0c;它繼承自 Spider 類&#xff0c;主要用于實現基于規則的網頁爬取。相較于普通的 Spider 類&#xff0c;CrawlSpider 可以根據預定義的規則自動跟進頁面中的鏈接&#xff0c;從而實現更高效、更靈活的爬取。 Scr…

Glide 如何加載遠程 Base64 圖片

最近有個需求&#xff0c;后端給出的圖片地址并不是正常的 URL&#xff0c;而且需要一個接口去請求&#xff0c;但是返回的是 base64 數據流。這里不關心為啥要這么多&#xff0c;原因有很多&#xff0c;可能是系統的問題&#xff0c;也可能是能力問題。當然作為我們 Android 程…

004-nlohmann/json 快速認識-C++開源庫108杰

了解 nlohmann/json 的特點&#xff1b;理解編程中 “數據戰場”劃分的概念&#xff1b;迅速上手多種方式構建一個JSON對象&#xff1b; 1 特點與安裝 nlohmann/json 是一個在 github 長期霸占 “JSON” 熱搜版第1的CJSON處理庫。它的最大優點是與 C 標準庫的容器數據&#xf…

#基礎Machine Learning 算法(上)

機器學習算法的分類 機器學習算法大致可以分為三類&#xff1a; 監督學習算法 (Supervised Algorithms&#xff09;:在監督學習訓練過程中&#xff0c;可以由訓練數據集學到或建立一個模式&#xff08;函數 / learning model&#xff09;&#xff0c;并依此模式推測新的實例。…

正弦波、方波、三角波和鋸齒波信號發生器——Multisim電路仿真

目錄 Multisim使用教程說明鏈接 一、正弦波信號發生電路 1.1正弦波發生電路 電路組成 工作原理 振蕩頻率 1.2 正弦波發生電路仿真分析 工程文件鏈接 二、方波信號發生電路 2.1 方波發生電路可調頻率 工作原理 詳細過程 2.2 方波發生電路可調頻率/可調占空比 調節占空比 方波產生…

【AND-OR-~OR鎖存器設計】2022-8-31

緣由鎖存器11111111111-硬件開發-CSDN問答 重置1&#xff0c;不論輸入什么&#xff0c;輸出都為0&#xff1b; 重置0&#xff0c;輸入1就鎖住1 此時輸入再次變為0&#xff0c;輸出不變&#xff0c;為鎖住。

力扣-字符串-468 檢查ip

思路 考察字符串的使用&#xff0c;還有對所有邊界條件的檢查 spilt&#xff08;“\.”&#xff09;&#xff0c;toCharArray&#xff0c;Integer.parseInt() 代碼 class Solution {boolean checkIpv4Segment(String str){if(str.length() 0 || str.length() > 4) retur…

BC8 十六進制轉十進制

題目&#xff1a;BC8 十六進制轉十進制 描述 BoBo寫了一個十六進制整數ABCDEF&#xff0c;他問KiKi對應的十進制整數是多少。 輸入描述&#xff1a; 無 輸出描述&#xff1a; 十六進制整數ABCDEF對應的十進制整數&#xff0c;所占域寬為15。 備注&#xff1a; printf可以使用…