1. 程式人生 > >java資料結構之二叉排序樹

java資料結構之二叉排序樹

binary sort tree / binary search tree

性質:

1.若左子樹不為空,則左子樹上所有節點的值均小於它的根節點的值。

2.若右子樹不為空,則右子樹上所有節點的值均大於它的根節點的值。

3.左右子樹也是二叉排序樹。

4.沒有值相同的節點。

查詢步驟:

若根結點的值等於查詢的關鍵字的值,成功。

否則,若小於根結點的關鍵字值,遞迴查詢左子樹。

若大於根結點的關鍵字值,遞迴查詢右子樹。

若子樹為空,則查詢不成功。

設 P(n,i)為它的左子樹的結點個數為 i 時的平均查詢長度。P(n):具有N個節點的平均查詢長度。

則上圖的  P(6, 3) = [ 1+ ( P(3) + 1) * 3 + ( P(2) + 1) * 2 ] / 6= [ 1+ ( 5/3 + 1) * 3 + ( 3/2 + 1) * 2 ] / 6

平均查詢長度= 每個結點的深度的總和 / 總結點數

P(3) = (1+2+2)/ 3 = 5/3

P(2) = (1+2)/ 2 = 3/2

∴ P(n,i)= [ 1+ ( P(i) + 1) * i + ( P(n-i-1) + 1) * (n-i-1) ] / n

∴ P(n)=  P(n,i)/ n <= 2(1+I/n)lnn = O(logn)

插入節點:

public BinaryNode insert(int value, BinaryNode node) {
    if (node == null) {
        return new BinaryNode(value, null, null);
    }
    int result = node.getNodeValue().compareTo(value);
    if (result < 0) {
        node.rightNode = insert(value, node.getRightNode());
    } else if (result > 0) {
        node.leftNode = insert(value, node.getLeftNode());
    } else {
        System.out.println("duplicate value , fail to insert");
    }
    return node;
}

刪除節點:

// 查詢value最小的節點
public BinaryNode findMin(BinaryNode node) {
  if (node == null) {
      return node;
  } else if (node.getLeftNode() != null) {
      // 從左節點開始查詢
      node = findMin(node.getLeftNode());
  }
  return node;
}

public BinaryNode delete(Integer value, BinaryNode node) {
    if (node == null) {
        return node;
    }
    // 將要刪除的value值與二叉樹的節點值比較
    int result = value.compareTo(node.getNodeValue());
    if (result < 0) {
        // 從左子樹查詢符合刪除條件的節點,設定新的左子樹
        node.setLeftNode(delete(value, node.getLeftNode()));
    } else if (result > 0) {
        // 從右子樹查詢符合條件的節點進行刪除。設定新的右子樹。
        node.setRightNode(delete(value, node.getRightNode()));
    } else if (node.getLeftNode() != null && node.getRightNode() != null) {
        // 左右子樹同時不為空,從右子樹查詢值最小的節點,將它的值與當前父節點的值交換
        int minValue = findMin(node.getRightNode()).getNodeValue();
        node.setNodeValue(minValue);
        // 刪除上述從右子樹查詢值最小的節點,設定新的右子樹
        node.setRightNode(delete(node.getNodeValue(), node.getRightNode()));
    } else {
        // 左右子樹有一個為空,該節點的子節點替代該節點。
        return node = (node.getLeftNode() != null) ? node.getLeftNode() : node.getRightNode();
    }
    return node;
}