日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

树一:邂逅入门篇

發(fā)布時間:2024/1/18 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 树一:邂逅入门篇 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、樹的概念

樹是一種典型的非線性結(jié)構(gòu),是表達有層次特性的圖結(jié)構(gòu)的一種方法。

1.1 基本術(shù)語

術(shù)語描述
空樹當(dāng)n=0 時稱為空樹。
根結(jié)點根結(jié)點是一個沒有雙親結(jié)點的結(jié)點。一棵樹最多一個。例如:A
結(jié)點之間的連線
葉子結(jié)點沒有孩子結(jié)點的結(jié)點。例如:N、O、P
兄弟結(jié)點同一雙親的孩子結(jié)點; 堂兄結(jié)點:同一層上結(jié)點
祖先結(jié)點從根到該結(jié)點的所經(jīng)分支上的所有結(jié)點
子孫結(jié)點以某結(jié)點為根的子樹中任一結(jié)點都稱為該結(jié)點的子孫
結(jié)點層根結(jié)點的層定義為1;根的孩子為第二層結(jié)點,依此類推;
樹的深度樹中最大的結(jié)點層
樹的高度跟樹的深度一個意思。樹中所有結(jié)點高度的最大值
結(jié)點的度結(jié)點子樹的個數(shù)
樹的度樹中最大的結(jié)點度。
分枝結(jié)點度不為0的結(jié)點;
有序樹子樹有序的樹,如:家族樹;
無序樹不考慮子樹的順序

注意有寫書定義書高和層是從0開始的。如:根結(jié)點在0層


  • 樹的度

  • 如果樹除了葉子結(jié)點外,其余每一個結(jié)點只有一個孩子結(jié)點,則這種樹稱為斜樹; 所有的結(jié)點都只有左子樹的二叉樹叫左斜樹。所有結(jié)點都是只有右子樹的二叉樹叫右斜樹。


1.2 二叉樹

如果一棵樹的每個結(jié)點有0 、1 后者 2個結(jié)點(最多兩個孩子結(jié)點),那么這棵樹稱為二叉樹??諛湟彩且豢糜行У亩鏄?。二叉樹的子樹還是二叉樹。實際上可以遞歸定義二叉樹。(因為這個特性,對二叉樹的操作常常使用遞歸算法)


  • 滿二叉樹/滿樹: 二叉樹中的每個結(jié)點恰好有兩個孩子結(jié)點且所有葉子結(jié)點都在同一層。


  • 完全二叉樹/完全樹:對一顆具有n個結(jié)點的二叉樹按層編號,如果編號為i(1<=i<=n) 的結(jié)點與同樣深度的滿二叉樹中編號為i的結(jié)點在二叉樹中位置完全相同,則這棵二叉樹稱為完全二叉樹

倒數(shù)第二層是滿的,且最后一層的葉子結(jié)點從左至右填充


  • 平衡二叉樹: 如果樹中的每個結(jié)點的子樹的高度差不大于1,則樹稱為高度平衡的或者平衡的。

  • 完全平衡樹: 若二叉樹中的每個結(jié)點有兩棵高度相等的子樹,則該樹稱為完全平衡樹。唯一的完全平衡二叉樹是滿樹。

  • 二叉搜索樹

二叉查找樹是一棵二叉樹、其結(jié)點含有comparable類型的對象,并遵循以下規(guī)則:

  • 結(jié)點中的數(shù)據(jù)大于結(jié)點左子樹中的所有數(shù)據(jù)。
  • 結(jié)點中的數(shù)據(jù)小于結(jié)點的右子樹中的所有數(shù)據(jù)。
  • 左子樹和右子樹也都必須是二叉查找樹

    • 平衡二叉查找樹(AVL 樹)

    是平衡樹和二叉搜索樹的結(jié)合

    HB(k)中,如果k=1,那么這樣的二叉搜索叫做AVL樹。即一棵AVL樹是帶有平衡條件的二叉搜索樹。 左子樹和右子樹的高度最多不能超過1


    • 紅黑色
      在紅黑樹中,每個結(jié)點關(guān)聯(lián)一個額外的屬性:紅色或者黑色中的一種顏色。
      定義:紅黑樹是一棵滿足以下性質(zhì)的二叉搜索樹:
  • 根結(jié)點是黑色
  • 每個葉子結(jié)點是黑色
  • 紅色結(jié)點的孩子結(jié)點是黑色

  • 1.3 滿樹(滿二叉樹)或完全樹(完全二叉樹)的高度

    其中h是樹的高度,如果滿樹的結(jié)點樹為n,則有

    即含有n個結(jié)點的滿樹的高度是 log2(n+1)。含n個結(jié)點的完全樹的高度是對 log2(n+1)向上取整。

    含有n個結(jié)點的完全二叉樹或滿二叉樹的高度是對log2(n+1)向上取整


    1.4 其他、 二叉樹的應(yīng)用

    • 編譯器中的表達式
    • 用于數(shù)據(jù)壓縮算法中哈弗曼編碼樹
    • 二叉搜索樹(查找樹)BST
    • 優(yōu)先隊列(PQ)
      ……

    1.5 二叉樹的結(jié)構(gòu)

    為了簡單起見,數(shù)據(jù)設(shè)定為整數(shù)

    //java語言描述 public class BinaryTreeNode {private int data;private BinaryTreeNode leftTree;private BinaryTreeNode rightTree;…… }

    1.6 二叉樹的操作

    • 基本操作
      • 插入
      • 刪除
      • 查找
      • 遍歷
    • 輔助操作
      • 樹大小
      • 樹高
      • 樹最大層
      • 給定兩個或多個節(jié)點,找最近公共祖先

    ……


    二 、樹的遍歷

    2.1 二叉樹的遍歷

    為了對樹結(jié)構(gòu)進行處理,需要一種機制來遍歷樹中的結(jié)點。在遍歷過程中,每個結(jié)點只能被處理一次,但可以被訪問多次。

    • 前序遍歷/先序遍歷
      在訪問根的子樹之前訪問根。然后訪問根的左子樹中所有的結(jié)點,再訪問根的右子樹中的所有結(jié)點。

    遞歸方式

    public static void preOrder(BinaryTreeNode root) {if(null != root) {System.out.print(root.getData() + " ");preOrder(root.getLeftTree());preOrder(root.getRightTree());}}

    非遞歸方式

    為了模擬遞歸:首先處理當(dāng)前結(jié)點,在遍歷左子樹之前,把當(dāng)前結(jié)點保留到棧中,當(dāng)遍歷完左子樹后,將該元素出棧,然后找打其右子樹進行遍歷。直到棧為空為止。

    public static void preOrderNonRecursive(BinaryTreeNode root) {if(null == root) {return;}Stack<BinaryTreeNode> s = new Stack<BinaryTreeNode>(); // FILOwhile (true) {while (null != root) {System.out.print(root.getData() + " ");s.push(root);root = root.getLeftTree();}if(s.isEmpty()) {break;}root = s.pop();root = root.getRightTree();}}
    • 中序遍歷
      在中序遍歷中,根結(jié)點的訪問在兩棵子樹的遍歷中間完成。

    遞歸方式:

    public static void inOrder(BinaryTreeNode root) {if(null != root) {inOrder(root.getLeftTree());System.out.print(root.getData() + " ");inOrder(root.getRightTree());} }

    非遞歸方式:

    非遞歸中序遍歷類似前序遍歷。唯一區(qū)別是,首先要移動到結(jié)點的左子樹,完成左子樹的遍歷后,再將結(jié)點出棧進行處理。

    public static void inOrderNonRecursive(BinaryTreeNode root) {if(null == root) return;Stack<BinaryTreeNode> stack = new Stack<BinaryTreeNode>();while (true) {while (null != root) {stack.push(root);root = root.getLeftTree();}if(stack.isEmpty()) return;BinaryTreeNode node = stack.pop();System.out.print(node.getData() + " ");root = node.getRightTree();}}
    • 后序遍歷
      訪問二叉樹的根的子樹中的結(jié)點之后訪問樹的根

    遞歸方式:

    public static void postorder(BinaryTreeNode root) {if(null != root) {postorder(root.getLeftTree());postorder(root.getRightTree());System.out.print(root.getData() + " ");}}

    非遞歸方式:

    ①:前序、中序遍歷中,當(dāng)元素出棧后就不需要再次訪問該結(jié)點了,但是后序遍歷中,每個結(jié)點需要訪問兩次。
    ②:當(dāng)從棧中出棧一個元素時,檢查這個元素與棧頂元素的右子樹是否相同。如果相同,則說明已經(jīng)完成了左、右子樹的遍歷。此時,只需要再將棧頂元素出棧一次病輸出該結(jié)點數(shù)據(jù)即可。

    public static void postOrderNonRecursive(BinaryTreeNode root) {if(null == root) return;Stack<BinaryTreeNode> stack = new Stack<>();while (true) {if (null != root) {stack.push(root);root = root.getLeftTree();} else {if(stack.isEmpty()) {return;}else {if(null == stack.peek().getRightTree()) {root = stack.pop();System.out.print(root.getData() + " ");if(!stack.isEmpty() && root == stack.peek().getRightTree()) {//左右子樹遍歷完成System.out.println(stack.peek().getData() + " ");stack.pop();if(stack.isEmpty()) {break;}}root = null;} else {//exists the right subtreeroot = stack.peek().getRightTree();stack.peek().setRightTree(null);}}}}}
    • 層序遍歷
      從根開始,每次訪問一層中的結(jié)點。在同一層中,從左至右訪問。

    層序遍歷需要借助隊列來完成

    public static void levelOrder(BinaryTreeNode root) {if(null == root) return;Queue<BinaryTreeNode> queue = new ArrayDeque<>();queue.add(root);BinaryTreeNode temp = null;while (!queue.isEmpty()) {temp = queue.poll();//處理當(dāng)前結(jié)點System.out.print(temp.getData() + " ");if(null != temp.getLeftTree()) {queue.add(temp.getLeftTree());}if(null != temp.getRightTree()) {queue.add(temp.getRightTree());}}}

    廣度優(yōu)先遍歷:層序遍歷是廣度優(yōu)先遍歷的示例
    深度優(yōu)先遍歷:前序遍歷是深度優(yōu)先遍歷的示例

    2.2一般樹的遍歷

    一般樹的遍歷有層序、前序和后序、對一般樹而言,中序遍歷不好定義。


    三、樹的示例

    一些使用樹來組織數(shù)據(jù)的示例。

    3.1 表達式樹

    可以用二叉樹來表示其運算符為二元運算符的代數(shù)表達式。孩子的次序要與操作樹的次序想匹配。這樣的二叉樹稱為表達式樹。

    事實上,不需要括號,樹也能得到表示中的運算符的次序。代數(shù)表達式有不同的寫法。正常書寫的表達式,即每個二元運算符出現(xiàn)在兩個操作數(shù)的中間,稱為中綴表達式。前綴表達式將每個運算符都放在其兩個操作的前面,后綴表達式將每個運算符都放在其兩個操作數(shù)的后面。


    3.2 二叉查找樹 / 二叉搜索樹

    二叉查找樹是一棵二叉樹、其結(jié)點含有comparable類型的對象,并遵循以下規(guī)則:

    • 結(jié)點中的數(shù)據(jù)大于結(jié)點左子樹中的所有數(shù)據(jù)。
    • 結(jié)點中的數(shù)據(jù)小于結(jié)點的右子樹中的所有數(shù)據(jù)。
    • 左子樹和右子樹也都必須是二叉查找樹

    例如:字符串二叉查找樹、Jared大于Jared的左子樹中的所有名字,但小于Jared的右子樹中的所有名字。


    下面是也是一棵二叉查找樹


    注意: 上面二叉查找樹的定義,隱含表明樹中的所有項都是不同的。但允許樹中有重復(fù)的值


    二叉查找樹的形態(tài)是不唯一的。即對同樣的一組數(shù)據(jù),可以組成幾棵不同的二叉查找樹。例如:


    3.3 堆

    堆(heap) 是其結(jié)點含有 Comparable對象的一棵完全二叉樹,且滿足以下條件:每個結(jié)點的對象不小于(或不大于)其后代的對象。 在最大堆中,結(jié)點中的對象大于或等于其后代的對象。 在最小堆中,關(guān)系是小于或等于。
    最大/小堆的任何結(jié)點的子樹仍然是最大/小堆。

    可以用堆實現(xiàn)優(yōu)先隊列


    小結(jié)

    本篇是對樹的一個入門,講解了樹的一些基本概念、并對二叉樹的三種遍歷做了全面的介紹,給出了java描述。后面講解了一些其他平衡樹的知識,也給出了一些樹的示例。


    參考

    • 《數(shù)據(jù)結(jié)構(gòu)與算法經(jīng)典問題解析-Java語言描述》
    • 《數(shù)據(jù)結(jié)構(gòu)與抽象Java語言描述第4版》
    • 參考 【https://xiaozhuanlan.com/topic/7189032546】

    總結(jié)

    以上是生活随笔為你收集整理的树一:邂逅入门篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。