二叉尋找樹(5),二叉尋找樹

來源:互聯網
上載者:User

二叉尋找樹(5),二叉尋找樹
在本系列的第一篇文章中,已經介紹過了二叉尋找樹的一些性質:

  • 節點的左子樹中任意節點值小於根節點
  • 節點的右子樹中任意節點值大於根節點
  • 左右子樹都必須是二叉尋找樹,不允許存在重複節點。

基於上面的這些性質,自然的就得到了這種判斷方式:樹中的每個節點都有一個特定的值。

假設樹的節點定義為:
struct Node{        int key;        Node *left;        Node *right;};

方法1 (實現簡單,但卻是錯誤的)對於每個節點,檢測它的左孩子節點是否小於它,且右孩子節點是否大於它。
bool isBST(Node* node){  if (node == NULL)    return true;       //如果左孩子大於根節點,則不是BST  if (node->left != NULL && node->left->key> node->key)    return false;       //如果右孩子節點小於根節點,則不是BST  if (node->right != NULL && node->right->key < node->key)    return false;     //遞迴的判斷  if (!isBST(node->left) || !isBST(node->right))    return false;       //檢測完畢,所有條件通過,則是BST  return true;}
但是,這種判斷方法是錯誤的,如下面例子所示,節點4處於根節點3的左子樹中,但是函數檢測到這棵樹是BST.
        3
      /   \
    2     5
  /  \
1    4

方法2 (結果正確,但是效率比較低)對於每個節點,檢測左子樹中的最大值是否比它小,而右子樹的最小值比它大。
//如果是BST,則返回truebool isBST(Node * node ){        if ( node == NULL)               return true;        //如果左子樹最大值大於根節點,則返回false        if ( node->left != NULL && maxValue( node->left) > node->key)               return false;        //如果右子樹最小值小於根節點,則返回false        if ( node->right != NULL && minValue( node->right) < node->key)               return false;        //遞迴判斷        if (!isBST( node->left) || !isBST( node->right))               return( false);        //所有檢測都通過,是BST        return true;}
其中,maxValue以及minValue函數,分別返回一顆非空樹中的最大值和最小值。

方法3 (正確並且有效)方法2因為要重複的遍曆樹中的部分資料,效率比較低。更好的方案是每個節點只遍曆一次。 方法3的巧妙之處在於限定了子樹中節點值的範圍,從而每個節點只需訪問一次。節點值的初始範圍可限定為INT_MIN以及INT_MAX。
//判斷是否為BST
bool isBST(Node* node)
{
    return(isBSTUtil(node, INT_MIN, INT_MAX));
}
//如果是一顆二叉尋找樹,且值範圍在[min,max],則返回true
bool isBSTUtil(Node* node, int min, int max)

代碼實現:
#include <iostream>struct Node{        int key;        Node *left;        Node *right;};bool isBSTUtil(Node * node, int min, int max);//判斷是否為BSTbool isBST(Node * node ){        return(isBSTUtil( node, INT_MIN, INT_MAX));}//如果是一顆二叉尋找樹,且值範圍在[min, max],則返回truebool isBSTUtil(Node * node , int min , int max ){        //空樹也是BST        if ( node == NULL)               return true;        //如果節點值違反了最大/最小約束條件,則不是BST        if ( node->key < min || node->key > max)               return false;        //遞迴檢查子樹        return  isBSTUtil( node->left, min, node->key - 1) &&              isBSTUtil( node->right, node->key + 1, max);}// 建立一個新的BST節點Node *createNewNode(int item ){        Node *temp = new Node;       temp->key = item;       temp->left = temp->right = NULL;        return temp;}int main(){    /* tree1的定義            4          /   \         2     5        / \       1   3     */       Node *root = createNewNode(4);       root->left = createNewNode(2);       root->right = createNewNode(5);       root->left->left = createNewNode(1);       root->left->right = createNewNode(3);        if (isBST(root))              std::cout << "tree1 is BST\n";        else              std::cout << "tree1 is not BST\n";        /* tree2的定義            4          /   \         2     5        /     /       1     3       */       root = createNewNode(4);       root->left = createNewNode(2);       root->left->left = createNewNode(1);       root->right = createNewNode(5);       root->right->left = createNewNode(3);        if (isBST(root))              std::cout << "tree2 is BST\n";        else              std::cout << "tree2 is not BST\n";        return 0;}
輸出:
tree1 is BST
tree2 is not BST

時間複雜度: O(n)
輔助空間 : 如果不考慮函數調用棧的大小,則為O(1), 否則為O(n)

方法4(使用中序遍曆)1) 對樹進行中序遍曆,將結果儲存在temp數組中。
3) 檢測temp數組中元素是否為升序排列。如果是,則這棵樹為BST.
時間複雜度: O(n)
方法4還可以進一步的最佳化,我們可以避免使用這個額外的數組。在中序遍曆時,可以儲存前驅節點,如果當前節點小於前驅節點,則這棵樹不是BST.
//判斷是否為BSTbool isBST(Node* root){     static Node *prev = NULL;     // 中序遍曆這棵樹,並儲存前驅節點至prev中     if (root)     {          if (!isBST(root->left))               return false;          // 檢測節點值的合法性          if (prev != NULL && root->key <= prev->key)               return false;          prev = root;          //右子樹          return isBST(root->right);     }     return true;}

更多參考:
http://en.wikipedia.org/wiki/Binary_search_tree
http://cslibrary.stanford.edu/110/BinaryTrees.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.