簡體   English   中英

二進制搜索樹刪除

[英]Binary Search Tree Remove

目前,我正在使用C ++在二叉搜索樹上工作,已經達到必須編寫remove / delete函數的階段(使用遞歸方法, x = change(x) )。 我有兩個選擇:

  • 在要刪除的節點的父節點處停止;

  • 到達要刪除的節點,然后調用一個函數
    返回父母

方法1:價格便宜,代碼更多

方法2:更少的代碼,更昂貴

您認為哪種方法更好,為什么?

我不同意這些是您僅有的兩個選擇。

我認為一個更簡單的解決方案是要求每個節點都應刪除它。 如果確定是,則將其刪除並返回應替換它的新節點。 如果決定不,則返回自身。

// pseudo code.
deleteNode(Node* node, int value)
{
    if (node == NULL) return node;

    if (node->value == value)
    {
        // This is the node I want to delete.
        // So delete it and return the value of the node I want to replace it with.
        // Which may involve some shifting of things around.
        return doDelete(node);
    }
    else if (value < node->value)
    {
        // Not node. But try deleting the node on the left.
        // whatever happens a value will be returned that
        // is assigned to left and the tree will be correct.
        node->left = deleteNode(node->left, value);
    }
    else
    {
        // Not node. But try deleting the node on the right.
        // whatever happens a value will be returned that
        // is assigned to right and the tree will be correct.
        node->right = deleteNode(node->right, value);
    }
    // since this node is not being deleted return it.
    // so it can be assigned back into the correct place.
    return node;
}

最好的方法是遍歷要刪除的節點的父節點,然后刪除該子節點。 最終,您將始終訪問子節點,因為您始終必須確認子節點是您要刪除的節點。

我發現一般而言,編寫樹數據結構函數的最有效形式是以下偽代碼格式。

    function someActionOnTree() {
         return someActionOnTree(root)
    }

    function someActionOnTree (Node current) {
         if (current is null) {
              return null
         }
         if (current is not the node I seek) {
              //logic for picking the next node to move to
              next node = ...

              next node = someActionOnTree(next node)
         }
         else {
              // do whatever you need to do with current
              // i.e. give it a child, delete its memory, etc
              current = ...
         }
         return current;
    }

此遞歸函數在數據結構的頂點集上遞歸。 對於算法的每次迭代,它要么尋找要在其上遞歸函數的節點,然后用該節點上算法迭代的值覆蓋對該節點的數據結構引用。 否則,它將覆蓋節點的值(並可能執行不同的邏輯集)。 最后,該函數返回對參數節點的引用,這對於覆蓋步驟至關重要。

這是我在C ++中為樹數據結構找到的通常最有效的代碼形式。 這些概念也適用於其他結構-您可以使用這種形式的遞歸,其中返回值始終是對數據結構的平面表示形式中的固定點的引用(基本上,總是返回您應該在現場找到的任何東西在看)。

這是對二進制搜索樹刪除功能的這種應用,以修飾我的觀點。

function deleteNodeFromTreeWithValue( value ) {
     return deleteNodeFromTree(root, value)
}

function deleteNodeFromTree(Node current, value) {
     if (current is null) return null
     if (current does not represent value) {
          if (current is greater than my value) {
               leftNode = deleteNodeFromTree(leftNode, value)
          } else {
                rightNode = deleteNodeFromTree(rightNode, value)
          }
      }
      else {
           free current's memory
           current = null
      }
      return current
}

顯然,還有許多其他方式可以編寫此代碼,但是根據我的經驗,這是最有效的方法。 注意,由於硬件已經緩存了節點,因此覆蓋指針實際上並不會影響性能。 如果您想提高搜索樹的性能,我建議您研究專門的樹,例如自平衡樹(AVL樹),B樹,紅黑樹等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM