數據結構與算法:二叉樹算法

內容銜接上一章 數據結構與算法:常見排序算法html

內容提要

  • 什麼是樹

  - 爲何使用樹前端

  • 二叉樹
  • 二叉查找樹
  • 紅黑樹
  • B、B+樹
  • 伸展樹

能夠點擊連接感覺下筆者用d3.js畫的treenode

https://codepen.io/AlexZ33/pe...面試

是計算機科學中常常用到的一種數據結構。算法

  • 樹是一種非線性的數據結構,以分層的方式存儲數據。
  • 樹被用來存儲具備層級關係的數據,好比文件系統中的文件
  • 數還被用來存儲有序列表

選擇樹而不是那些基本的數據結構,是由於:數據庫

  • 二叉樹上進行查找特別快(而在鏈表上查找每次基本就是遍歷,查找速度很慢)
  • 二叉樹添加或刪除元素也很快(而對數組執行添加或刪除操做則不是這樣)

樹的遍歷

樹的遍歷是樹的一種重要的運算。所謂遍歷是指對樹中全部結點的信息的訪問,即依次對樹中每一個結點訪問一次且僅訪問一次。樹的3種最重要的遍歷方式分別稱爲前序遍歷、中序遍歷和後序遍歷。以這3種方式遍歷一棵樹時,若按訪問結點的前後次序將結點排列起來,就可分別獲得樹中全部結點的前序列表、中序列表和後序列表。相應的結點次序分別稱爲結點的前序、中序和後序。

二叉樹

這裏咱們將研究一種特殊的樹:二叉樹(二叉樹,本質上,是對鏈表和數組的一個折中。)segmentfault

圖片描述

如上圖,樹是由一組以邊鏈接的節點組成。數組

二叉樹是一種特殊的樹,它的子節點個數不超過兩個數據結構

經過將子節點的個數限定爲2,能夠寫出高效的程序在樹中插入、查找和刪除數據。post

根節點:二叉樹中最高那個節點沒有父節點。
葉子節點: 最低下一層沒有孩子節點的節點
剩下的節點被成爲中間節點

二叉查找樹(排序二叉樹)Binary Search Tree

BST(Binary Search Tree)目的是爲了提升查找的性能,其查找在平均和最壞的狀況下都是logn級別,接近二分查找。

圖片描述
如上圖,相對較小的值保存在左節點中,較大的值保存在右節點中。這樣可以使查找效率變高。

  • 全部非葉子結點至多擁有兩個兒子(Left和Right);
  • 全部結點存儲一個關鍵字;
  • 非葉子結點的左指針指向小於其關鍵字的子樹,右指針指向大於其關鍵字的子樹;

有三種遍歷BST的方式:

  • 中序遍歷 (in-order)按照節點上的鍵值,以升序訪問BST上的全部節點
  • 先序遍歷 (pre-order)先訪問根節點,而後以一樣方式訪問左子樹和右子樹
  • 後序遍歷 (post-order)先訪問葉子節點,從左子樹到右子樹,再到根節點
  • 層次遍歷:只需按層次遍歷便可
function BinaryTree() {
            //二叉查找樹由節點組成,因此咱們先定義Node

            //Node
            var Node = function(data,left,right) {
                this.data = data;
                this.left = left;
                this.right = right;
               // this.show = show;
            };
                        
            // var show = function() {
            //         return = this.data;
            // };
            
            var root = null;//設置根節點
              
            //insert()方法,用來向樹中加入新節點
            this.insert = function(data) {
                var newNode = new Node(data,null,null);
                if(root ===null){
                    root = newNode;
                }
                else {
                    insertNode(root,newNode);    
                }
            };

            var insertNode = function(node,newNode) {
                     if(newNode.data < node.data){
                        if(node.left === null){
                          node.left = newNode;
                        }else{
                          insertNode(node.left,newNode);
                        }
                     }else{
                       if(node.right === null){
                         node.right = newNode;
                       }else{
                         insertNode(node.right,newNode);
                       }
                     }
                
            };

            
            

        }


        var nodes = [8,3,10,1,6,14,4,7,13];
        var binaryTree = new BinaryTree();
        nodes.forEach(function(data) {
            binaryTree.insert(data);
        });
     
     //中序遍歷

     //先序遍歷

     //後序遍歷

中序遍歷

function BinaryTree() {
            //二叉查找樹由節點組成,因此咱們先定義Node

            //Node
            var Node = function(data,left,right) {
                this.data = data;
                this.left = left;
                this.right = right;
               // this.show = show;
            };
                        
            // var show = function() {
            //         return = this.data;
            // };
            
            var root = null;//設置根節點
              
            //insert()方法,用來向樹中加入新節點
            this.insert = function(data) {
                var newNode = new Node(data,null,null);
                if(root ===null){
                    root = newNode;
                }
                else {
                    insertNode(root,newNode);    
                }
            };

            this.inOrderTraverse = function(callback) {
                inOrderTraverseNode(root,callback);
            }

            var insertNode = function(node,newNode) {
                     if(newNode.data < node.data){
                        if(node.left === null){
                          node.left = newNode;
                        }else{
                          insertNode(node.left,newNode);
                        }
                     }else{
                       if(node.right === null){
                         node.right = newNode;
                       }else{
                         insertNode(node.right,newNode);
                       }
                     }
                
            };

            var inOrderTraverseNode = function(node,callback) {
                if (node!==null) {
                    inOrderTraverseNode(node.left,callback);
                    callback(node.data);
                    inOrderTraverseNode(node.right,callback);
                }
            }

            
            

        }


        var nodes = [8,3,10,1,6,14,4,7,13];
        var binaryTree = new BinaryTree();
        nodes.forEach(function(data) {
            binaryTree.insert(data);
        });
     
     //中序遍歷
      var callback = function(data) {
          console.log(data);
      }
      binaryTree.inOrderTraverse(callback);

圖片描述

前序遍歷(pre-order)

咱們看到中序遍歷能夠把二叉樹的節點按照從小到大的順序打印出來;
前序遍歷能夠在咱們已經擁有一顆二叉樹的時候,高效的複製這顆二叉樹。
經過其前序遍歷去複製一顆二叉樹比從新構造一顆二叉樹要高效得多

前(先)序遍歷:按照最優先順序沿必定路徑通過路徑上全部的站。在二叉樹中,先根後左再右。巧記:根左右。

圖片描述

clipboard.png

後序遍歷

紅黑樹

紅黑樹: 處於平衡狀態的特殊二叉查找樹
圖片描述

紅黑樹(Red-Black Tree,簡稱R-B Tree),它一種特殊的二叉查找樹。 紅黑樹是特殊的二叉查找樹,意味着它知足二叉查找樹的特徵:任意一個節點所包含的鍵值,大於等於左孩子的鍵值,小於等於右孩子的鍵值。 除了具有該特性以外,紅黑樹還包括許多額外的信息。

紅黑樹的每一個節點上都有存儲位表示節點的顏色,顏色是紅(Red)或黑(Black)。 紅黑樹的特性: (1) 每一個節點或者是黑色,或者是紅色。 (2) 根節點是黑色。 (3) 每一個葉子節點是黑色。 (4) 若是一個節點是紅色的,則它的子節點必須是黑色的。 (5) 從一個節點到該節點的子孫節點的全部路徑上包含相同數目的黑節點。

關於它的特性,須要注意的是: 第一,特性(3)中的葉子節點,是隻爲空(NIL或null)的節點。 第二,特性(5),確保沒有一條路徑會比其餘路徑長出倆倍。於是,紅黑樹是相對是接近平衡的二叉樹。

圖片描述

要實現起來,須要包含的基本操做是添加、刪除和旋轉。在對紅黑樹進行添加或刪除後,會用到旋轉方法。旋轉的目的是讓樹保持紅黑樹的特性。旋轉包括兩種:左旋 和 右旋。

紅黑樹的應用比較普遍,主要是用它來存儲有序的數據,它的查找、插入和刪除操做的時間複雜度是O(lgn)

B樹、B+樹

維基百科對B樹的定義爲「在計算機科學中,B樹(B-tree)是一種樹狀數據結構,它可以存儲數據、對其進行排序並容許以O(log n)的時間複雜度運行進行查找、順序讀取、插入和刪除的數據結構。B樹,歸納來講是一個節點能夠擁有多於2個子節點的二叉查找樹。與自平衡二叉查找樹不一樣,B-樹爲系統最優化大塊數據的讀和寫操做。B-tree算法減小定位記錄時所經歷的中間過程,從而加快存取速度。廣泛運用在數據庫和文件系統。

高級數據(樹、堆、圖)應該平時多積累,好好理解,好比理解了堆是什麼樣的數據結構,在面試中碰見的「查找最大的 K 個數」這類算法問題,就會迎刃而解。

伸展樹

常見面試題

一、已知一顆二叉樹,若是先序遍歷的節點順序是:ADCEFGHB, 中序遍歷是:CDFEGHAB,則後序遍歷結果是()
A. CFHGEBDA
B. CDFEGHBA
C. FGHCDEBA
D. CFHGEDBA

解答:

對於二叉樹的遍歷方式通常分爲三種先序、中序、後序三種方式:

先序遍歷(根左右)
若二叉樹爲空,則不進行任何操做:不然
一、訪問根結點。
二、先序方式遍歷左子樹。
三、先序遍歷右子樹。

中序遍歷 (左根右)
若二叉樹爲空,則不進行任何操做:不然
一、中序遍歷左子樹。
二、訪問根結點。
三、中序遍歷右子樹。

後序遍歷 (左右根)
若二叉樹爲空,則不進行任何操做:不然
一、後序遍歷左子樹。
二、後序遍歷右子樹。
三、放問根結點。

所以,根據題目給出的先序遍歷和中序遍歷,能夠畫出二叉樹: 
圖片描述
選 4

參考

《數據結構與算法Javascript描述》
Javascript實現二叉樹算法
淺談數據結構-二叉樹
慕課網 Javascript實現二叉樹算法
前端 樹控件
2016 騰訊軟件開發面試題
https://www.cnblogs.com/tangx...
https://jovial-snyder-8b8319....
Tree traversal
相關文章
相關標籤/搜索