數據結構-樹詳解

樹簡介

樹存儲和組織具有層級結構的數據(例:公司職級),就是一顆倒立生長的樹。
屬性:

  • 遞歸
  • n個節點有n-1個連接
  • 節點x的深度:節點x到根節點的最長路徑
  • 節點x的高度:節點x到葉子節點的最長路徑
    在這里插入圖片描述

二叉樹

完美、完全、平衡二叉樹

二叉樹:每個節點最多有兩個子節點(左孩子,有孩子)。在第i層最多有2i個節點。
完美二叉樹、完全二叉樹查看之前文章
平衡二叉樹:空樹或左子樹和右子樹高度差不超過1
請添加圖片描述
?
二叉樹在內存中的存儲方式:

  • 動態創建節點
  • 數組
    請添加圖片描述

二叉樹高度實現

求二叉樹高度的實現方式:計算左右子樹高度取較大者+1
在這里插入圖片描述

class TreeNode{int data;TreeNode left;TreeNode right;public TreeNode(int data){this.data = data;this.left = null;this.right = null;}
}
public class DataStruct {//高度public int findHight(TreeNode root){if (root == null){return -1;}return Math.max(findHight(root.left),findHight(root.right))+1;}//遍歷public static void main(String[] args) {DataStruct ds = new DataStruct();TreeNode root = new TreeNode(1);root.left = new TreeNode(2);root.left.left = new TreeNode(4);root.left.right = new TreeNode(5);root.left.right.left = new TreeNode(8);root.left.right.right = new TreeNode(9);root.right = new TreeNode(3);root.right.left = new TreeNode(6);root.right.right = new TreeNode(7);System.out.println(ds.findHight(root));}
}

二叉樹遍歷實現

樹的遍歷算法兩類:廣度優先(同一層級,下圖舉例即 F,D,J,B,E,G,K,A,C,I,H)、深度優先(左子樹、根節點、右子樹 三者順序可變)
深度優先:前序遍歷—根節點-左子樹-右子樹(F,D,B,A,C,E,J,G,I,H,K)
??????????????????中序遍歷—左子樹-根節點-右子樹(A,B,C,D,E,F,G,H,I,J,K)
??????????????????后續遍歷—左子樹-右子樹-根節點(A,C,B,E,D,H,I,G,K,J,F)

在這里插入圖片描述

廣度優先使用隊列來實現:取出節點的同時,讓他的孩子入隊。f(n)=O(n),S(n)=O(1)最好情況,S(n)=O(n)最壞情況。
在這里插入圖片描述

import java.util.LinkedList;
import java.util.Queue;
class TreeNode{char data;TreeNode left;TreeNode right;public TreeNode(char data){this.data = data;this.left = null;this.right = null;}
}
public class DataStruct {//廣度優先public void levelOrder(TreeNode root){if (root == null){return;}Queue<TreeNode> queue = new LinkedList<>();queue.add(root);while (!queue.isEmpty()){TreeNode poll = queue.poll();System.out.print(poll.data + " ");if (poll.left != null){queue.add(poll.left);}if (poll.right != null){queue.add(poll.right);}}return;}//深度優先public void preOrder(TreeNode root){if(root == null){return;}System.out.print(root.data + " ");preOrder(root.left);preOrder(root.right);}public void inOrder(TreeNode root){if(root == null){return;}inOrder(root.left);System.out.print(root.data + " ");inOrder(root.right);}public void postOrder(TreeNode root){if(root == null){return;}postOrder(root.left);postOrder(root.right);System.out.print(root.data + " ");}public static void main(String[] args) {DataStruct ds = new DataStruct();TreeNode root = new TreeNode('F');root.left = new TreeNode('D');root.left.left = new TreeNode('B');root.left.right = new TreeNode('E');root.left.left.left = new TreeNode('A');root.left.left.right = new TreeNode('C');root.right = new TreeNode('J');root.right.left = new TreeNode('G');root.right.right = new TreeNode('K');root.right.left.right= new TreeNode('I');root.right.left.right.left = new TreeNode('H');System.out.println("廣度優先:");ds.levelOrder(root);System.out.println();System.out.println("前序遍歷:");ds.preOrder(root);System.out.println();System.out.println("中序遍歷:");ds.inOrder(root);System.out.println();System.out.println("后序遍歷:");ds.postOrder(root);}
}

二叉搜索樹

概述

搜索:用數組、鏈表進行搜索耗時O(n)。如果是已排序的數組,用二分查找(可查看之前算法文章)耗時O(logn)。

數據結構數組鏈表二分查找二叉搜索樹
搜索O(n)O(n)O(logn)O(logn)
插入O(1)O(1)O(n)O(logn)
刪除O(n)O(n)O(n)O(logn)

二叉搜索樹:對于任意節點,左子樹上的所有節點值都小于它,右子樹上的所有節點值都大于它,并且這種性質在每個子樹上都遞歸成立。
請添加圖片描述
二叉搜索樹搜索時間復雜度O(logn)原理:每次比較不是往左就是往右,每次數量都會減少一半,跟二分查找同理。但需要注意二叉搜索樹需要是平衡的,否則時間復雜度>O(logn),下圖最壞情況是O(n)
在這里插入圖片描述

查找最小值和最大值

根據二叉搜索樹的特性,最小值一定在左邊,最大值一定在右邊

class TreeNode{int data;TreeNode left;TreeNode right;public TreeNode(int data){this.data = data;this.left = null;this.right = null;}
}
public class DataStruct {//迭代寫法public int findMin(TreeNode root){TreeNode temp = root;while (temp!=null && temp.left!=null){temp=temp.left;}return temp.data;}//遞歸寫法public int findMin1(TreeNode root){TreeNode temp = root;if (temp==null){return -1;}if (temp.left==null){return temp.data;}return findMin1(temp.left);}public static void main(String[] args) {DataStruct ds = new DataStruct();TreeNode root = new TreeNode(15);root.left = new TreeNode(10);root.left.left = new TreeNode(8);root.left.right = new TreeNode(12);root.right = new TreeNode(20);root.right.left = new TreeNode(17);root.right.right = new TreeNode(25);System.out.print(ds.findMin(root));}
}

判斷是否是二叉搜索樹

對于isSubTreeGreater,isSubTreeLesser也可以換種思路,即尋找最大最小值與父節點比較。
進一步優化:舍去比較大小的遞歸函數,而采用傳入該節點的數據范圍的參數來進行比較。
另一種方法:二叉搜索樹的中序遍歷是排序好的,也可以檢查中序遍歷結果是否排序好了。

class TreeNode{int data;TreeNode left;TreeNode right;public TreeNode(int data){this.data = data;this.left = null;this.right = null;}
}
public class DataStruct {public boolean isSubTreeLesser(TreeNode root,int data){if (root == null){return true;}if (root.data <= data && isSubTreeLesser(root.left, data) && isSubTreeLesser(root.right, data)){return true;}return false;}public boolean isSubTreeGreater(TreeNode root,int data){if (root == null){return true;}if (root.data>=data && isSubTreeGreater(root.left, data) && isSubTreeGreater(root.right, data)){return true;}return false;}public boolean isBinaryTree(TreeNode root){if(root == null){return true;}if (isSubTreeLesser(root.left, root.data) && isSubTreeGreater(root.right, root.data)&& isBinaryTree(root.left) && isBinaryTree(root.right)){return true;}return false;}public boolean isBinaryTree1(TreeNode root,int min,int max){if(root == null){return true;}if (root.data < max && root.data > min && isBinaryTree1(root.left,min,root.data) && isBinaryTree1(root.right,root.data,max)){return true;}return false;}public static void main(String[] args) {DataStruct ds = new DataStruct();TreeNode root = new TreeNode(7);root.left = new TreeNode(4);root.left.left = new TreeNode(1);root.left.right = new TreeNode(6);root.right = new TreeNode(9);System.out.println(ds.isBinaryTree(root));System.out.println(ds.isBinaryTree1(root,Integer.MIN_VALUE,Integer.MAX_VALUE));}
}

二叉搜索樹查詢、插入、刪除實現

在這里插入圖片描述

class TreeNode{int data;TreeNode left;TreeNode right;public TreeNode(int data){this.data = data;this.left = null;this.right = null;}
}
public class DataStruct {public TreeNode insert(TreeNode root, int data){if (root == null){return new TreeNode(data);}if (data<=root.data){root.left=insert(root.left,data);}else {root.right=insert(root.right,data);}return root;}public boolean search(TreeNode root, int data){if (root == null){return false;}if (data==root.data){return true;}if (data<root.data){return search(root.left,data);}else {return search(root.right,data);}}public TreeNode deleteNode(TreeNode root, int data){if (root == null){return null;}if (data<root.data){root.left=deleteNode(root.left,data);}else if (data>root.data){root.right=deleteNode(root.right,data);}else {//要刪除的節點是葉子節點if (root.left==null && root.right==null){return null;}//要刪除的節點只有一個子節點if (root.left==null){return root.right;//用右節點替代當前節點}if (root.right==null){return root.left;}//要刪除的節點有兩個節點,需要用子節點替換當前被刪除的節點,然后刪除子節點//此子節點要么是右子樹中的最小值,要么是左子樹中的最大值TreeNode minNode = root.right;while (minNode.left!=null){minNode = minNode.left;}root.data=minNode.data;root.right=deleteNode(root.right,minNode.data);}return root;}public void inOrder(TreeNode root){if(root == null){return;}inOrder(root.left);System.out.print(root.data + " ");inOrder(root.right);}   public static void main(String[] args) {DataStruct ds = new DataStruct();TreeNode root = null;root=ds.insert(root,15);root=ds.insert(root,10);root=ds.insert(root,20);root=ds.insert(root,8);root=ds.insert(root,12);root=ds.insert(root,17);root=ds.insert(root,25);ds.inOrder(root);System.out.print("\n");System.out.println(ds.search(root,12));System.out.println(ds.search(root,19));ds.deleteNode(root,15);ds.inOrder(root);}
}

尋找某個節點的中序后繼節點

二叉搜索樹的中序遍歷結果是已排序的。中序后繼節點就是排序好的數據中某個節點的下一個數據是什么。如果使用中序遍歷找后繼節點時間復雜度O(n)。

優化:

  • 某節點有右子樹,后繼節點=右子樹的最小值。
  • 某節點無右子樹,后繼節點=最近祖先節點(前提:某節點一定位于祖先節點的左子樹上)。(為了存儲父祖先,需要從跟節點走到指定節點)

10后繼=11,6后繼=8,12后繼=15
在這里插入圖片描述

class TreeNode{int data;TreeNode left;TreeNode right;public TreeNode(int data){this.data = data;this.left = null;this.right = null;}
}
public class DataStruct {public TreeNode getSuccessor(TreeNode root, TreeNode p){if (root == null){return null;}if (p.right != null){return findMin(p.right);}else {TreeNode successor = null;TreeNode temp = root;while (temp != p){if (p.data<temp.data){successor = temp;temp = temp.left;}else {temp=temp.right;}}return successor;}}public TreeNode findMin(TreeNode root){TreeNode temp = root;while (temp!=null && temp.left!=null){temp=temp.left;}return temp;}public static void main(String[] args) {DataStruct ds = new DataStruct();TreeNode root = new TreeNode(15);root.left = new TreeNode(10);root.left.left = new TreeNode(8);root.left.right = new TreeNode(12);root.left.left.left = new TreeNode(6);root.left.right.left = new TreeNode(11);root.right = new TreeNode(20);root.right.left = new TreeNode(17);root.right.right = new TreeNode(25);root.right.left.left = new TreeNode(16);root.right.right.right = new TreeNode(27);System.out.println(ds.getSuccessor(root,root.left.right).data);}
}

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

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

相關文章

【安卓Sensor框架-2】應用注冊Sensor 流程

注冊傳感器的核心流程為如下&#xff1a;應用層調用 SensorManager注冊傳感器&#xff0c;framework層創建SensorEventQueue對象&#xff08;事件隊列&#xff09;&#xff0c;通過JNI調用Native方法nativeEnableSensor()&#xff1b;SensorService服務端createEventQueue()創建…

新版本沒有docker-desktop-data分發 | docker desktop 鏡像遷移

在新版本的docker desktop中&#xff08;如4.42版本&#xff09;&#xff0c;鏡像遷移只需要更改路徑即可。如下&#xff1a; 打開docker desktop的設置&#xff08;圖1&#xff09;&#xff0c;將圖2的原來的地址C:\Users\用戶\AppData\Local\Docker\wsl修改為你想要的空文件…

EtherCAT SOEM源碼分析 - ec_init

ec_init SOEM主站一切開始的地方始于ec_init, 它是EtherCAT主站初始化的入口。初始化SOEM 主站&#xff0c;并綁定到socket到ifname。 /** Initialise lib in single NIC mode* param[in] ifname Dev name, f.e. "eth0"* return >0 if OK* see ecx_init*/ in…

84、原理解析-SpringApplication創建初始化流程

84、原理解析-SpringApplication初始化流程 # SpringApplication創建初始化流程原理解析 SpringApplication的創建和初始化是Spring Boot應用啟動的關鍵步驟&#xff0c;主要包括以下過程&#xff1a; ## 1. 創建SpringApplication實例 ### 1.1 調用構造函數 - 當調用SpringApp…

【數理邏輯】 選擇公理與集值映射

目錄 選擇公理1. 有限指標集 I I I2. 可數無限指標集 I I I &#xff08;簡稱為 ACC 或 ACω&#xff09;3. 不可數無限指標集 I I I4. 選擇公理的層級與數學應用5. 選擇公理的深層意義 集值映射的選擇函數1. 選擇公理的核心作用2. 不同情況下的依賴性分析3. AC 的必要性證明…

微信小程序使用wx.chooseImage上傳圖片時進行壓縮,并添加時間水印

在微信小程序的開發過程&#xff0c;經常會使用自帶的api(wx.chooseImage)進行圖片拍照或選擇圖片進行上傳&#xff0c;有時圖片太大&#xff0c;造成上傳和下載時過慢&#xff0c;現對圖片進行壓縮后上傳&#xff0c;以下是流程和代碼 一、小程序的版本選擇了3.2.5&#xff0…

RAII簡介

&#x1f4e6; 一、技術原理簡介&#xff1a;RAII是個“托管狂魔” 想象你有個健忘的朋友&#xff0c;每次借東西都會忘記歸還。RAII&#xff08;Resource Acquisition Is Initialization&#xff0c;資源獲取即初始化&#xff09;就是C派來的“超級管家”&#xff1a; “你負…

微信小程序入門實例_____打造你的專屬單詞速記小程序

上次通過天氣查詢小程序&#xff0c;我們初探了微信小程序開發的世界。這次&#xff0c;咱們再挑戰一個有趣又實用的項目 ——“單詞速記小程序”。無論是學生黨備考&#xff0c;還是上班族提升英語&#xff0c;都能用得上&#xff01;接下來就跟著我&#xff0c;一步一步把它做…

gateway白名單存儲nacos,改成存儲數據庫

前言 很久沒寫博客了&#xff0c;csdn都開始ai潤色了&#xff0c;之前都是看相應框架的源碼看了個遍&#xff0c;感覺底層原理都差不多&#xff0c;這陣子著手改造了下gateway中的白名單&#xff0c;之前白名單存儲到nacos&#xff0c;要改成存到數據庫。里面涉及到淺淺的源碼…

ubentu服務器版本安裝Dify

Docker 中安裝Dify 首先安裝Docker 1. 克隆Dify代碼倉庫 從github克隆 Dify 源代碼至要本地環境。 我的ubentu服務器版本&#xff0c;我把源代碼下載到 /var/下 在var文件夾下執行 git clone https://github.com/langgenius/dify.git執行成功后&#xff0c;進入Dify源代碼的…

Redis分布式鎖實戰:從入門到生產級方案

目錄 一、為什么需要分布式鎖&#xff1f; 二、Redis分布式鎖核心特性 三、實現方案與代碼詳解 方案1&#xff1a;基礎版 SETNX EXPIRE 原理 代碼示例 問題 方案2&#xff1a;Redisson框架&#xff08;生產推薦&#xff09; 核心特性 代碼示例 優勢 方案3&#xff…

【Redis】StringRedisTemplate 和 RedisTemplate 的區別

StringRedisTemplate 和 RedisTemplate 是 Spring Data Redis 提供的兩種用于操作 Redis 的模板類&#xff0c;它們的核心區別在于 序列化方式 和 操作的數據類型。以下是兩者的主要區別和使用建議&#xff1a; ? 1. 數據類型支持 類名支持的數據類型說明RedisTemplate支持所…

docker-compose快速搭建redis集群

目錄結構 redis-cluster/ ├── config/ │ ├── master.conf │ ├── slave1.conf │ └── slave2.conf └── docker-compose.yml配置文件內容 1. config/master.conf # Redis主節點配置 port 6379 bind 0.0.0.0 protected-mode no logfile "redis-mas…

SpringCloud系列(39)--SpringCloud Gateway常用的Route Predicate

前言&#xff1a;在上一節中我們實現了SpringCloud Gateway的動態路由 &#xff0c;而在本節中我們將著重介紹各種Route Predicate的作用。 1、可以到官方文檔里查看常用的Route Predicate的種類 https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.REL…

漸變色的進度條控件

近日&#xff0c;用VB.net2003重寫了一個漸變色的進度條控件。主要有以下功能&#xff1a; 支持自定義進度條分段數量&#xff0c;可拆分為多個步驟&#xff1b;每個步驟可獨立顯示完成百分比及漸變色效果。 每個步驟均可配置任務名稱和描述&#xff1b;運行時能實時顯示當前執…

【DICOM后處理】qt+vs 實現DICOM數據四視圖顯示

目錄 1、DICOM四視圖2、vtkImageViewer2 實現二維平面圖顯示3、vtkVolume實現三維體數據顯示4、實現界面圖 1、DICOM四視圖 DICOM四視圖通常指同時顯示醫學影像的四個不同平面或視角&#xff0c;用于全面分析三維數據&#xff08;如CT、MRI等&#xff09;。 標準四視圖布局&a…

Google Maps 安裝使用教程

一、Google Maps 簡介 Google Maps 是谷歌提供的地圖服務&#xff0c;通過其 JavaScript API&#xff0c;開發者可以在網頁中嵌入地圖&#xff0c;添加標記、路徑、地理編碼、路線導航等功能&#xff0c;適用于位置展示、物流追蹤、LBS 應用等場景。 二、獲取 Google Maps API…

Nginx+Keepalived實現前臺服務高可用

現階段項目開發往往采用前后臺分離&#xff0c;前臺常用的技術有vue、react等&#xff0c;前臺代碼部署在nginx中&#xff0c;代碼中配置了后臺服務的網關地址&#xff0c;由網關向后臺分發服務請求&#xff0c;架構示意圖如下&#xff1a; 在上述架構圖中&#xff0c;如果Ngin…

Gradio全解13——MCP協議詳解(5)——Python包命令:uv與uvx實戰

Gradio全解13——MCP協議詳解&#xff08;5&#xff09;——Python包命令&#xff1a;uv與uvx實戰 第13章 MCP協議詳解13.5 Python包命令&#xff1a;uv與uvx實戰13.5.1 uv核心亮點與常用命令1. uv介紹2. 安裝與項目管理3. 腳本與工具4. Python版本與pip接口 13.5.2 uv核心指令…

OD 算法題 B卷【求最小步數】

文章目錄 求最小步數 求最小步數 求從坐標零點到坐標點n的最小步數&#xff0c;一次只能沿著橫坐標軸向左或向右移動2或3&#xff1b;途經的坐標點可以為負數&#xff1b; 輸入描述: 坐標點n 輸出描述: 從坐標零點移動到坐標點n的最小步數 n在【1,10^9】 示例1 輸入&#xf…