2015-05-10 32 views
1

我正在創建一個二叉搜索樹,它需要能夠刪除節點,並在節點被正確刪除時返回true;如果該值不存在,則返回false那個樹。我這樣做是因爲我需要刪除多個數字,並且我想創建一個while循環來刪除它的所有內容,而這是真的。例如,一棵樹有以下整數:{79,83,147,71,95,49,15,191}。另一棵樹有以下整數{26,79,144,88,147,200,90}。我的任務是找到樹1中樹2中的任何元素,並從樹1中刪除它們(在這種情況下,爲79和147)。我想創建一個循環遍歷樹2中的所有數字,然後從樹中搜索並刪除它。以下是我迄今爲止的刪除節點功能(假設樹已經建成並填寫):從我的二叉搜索樹中刪除節點時遇到困難

Node.h:

template<class ItemType> 
class Node { 
public: 
    ItemType data; 
    Node * left; 
    Node * right; 

    //Constructors/Destructors 
    Node(); 
    Node (ItemType inData); 
    ~Node(); 
}; 

//--------------------------------------------------------------// 
//--    Constructor/Destructor     --// 
//--------------------------------------------------------------// 
/** Standard Constructor */ 
template<class ItemType> 
Node<ItemType>::Node() { 
    left = right = NULL; 
} 

/** Overload Constructor */ 
template<class ItemType> 
Node<ItemType>::Node (ItemType inData) { 
    data = inData; 
    left = right = NULL; 
} 

/** Standard Destructor */ 
template<class ItemType> 
Node<ItemType>::~Node() { 
    right = left = NULL; 
} 

從Source.cpp:

Tree2.postorder_print(); 

int ridOf = 79; 

if (Tree2.remove (ridOf)) { 
     Tree2.postorder_print(); 
     cout << endl << "Number of Nodes: " << Tree2.get_num_of_nodes() << endl; 
     cout << "Height:   " << Tree2.get_tree_height() << endl << endl; 
    } 

從Tree.h:

template<class ItemType> 
void BTree<ItemType>::postorder_print_helper (Node<ItemType> * inRoot, int & count) { 
    if (inRoot != NULL) { 
     postorder_print_helper (inRoot->left, count); 
     postorder_print_helper (inRoot->right, count); 
     count++; 
     std::cout << setw (4) << inRoot->data << " "; 
     if (count % 5 == 0) { std::cout << endl; } 
    } 
} // end of void BTree<ItemType>::postorder_print_helper (Node<ItemType> * inRoot) 




template<class ItemType> 
void BTree<ItemType>::postorder_print_helper (Node<ItemType> * inRoot, int & count) { 
    if (inRoot != NULL) { 
     postorder_print_helper (inRoot->left, count); 
     postorder_print_helper (inRoot->right, count); 
     count++; 
     std::cout << setw (4) << inRoot->data << " "; 
     if (count % 5 == 0) { std::cout << endl; } 
    } 
} // end of void BTree<ItemType>::postorder_print_helper (Node<ItemType> * inRoot) 




template<class ItemType> 
bool BTree<ItemType>::remove_helper (Node<ItemType> * inRoot, ItemType toRemove) { 
    //if this is the node with the data 
    if (inRoot->data == toRemove) { 
     //Create Null Node that points to NUll 
     Node<ItemType> * nullNode = new Node <ItemType> ; 
     //if inRoot has No Children 
     if (inRoot->left == NULL && inRoot->right == NULL) { 
      inRoot = nullNode; 
      return true; 
     } 
     //if inRoot has 2 Children 
     else if (inRoot->left != NULL && inRoot->right != NULL) { 
      Node<ItemType> * temp = new Node <ItemType>; 
      temp = return_max_value (inRoot->left); 
      Node<ItemType> * tempRight = new Node <ItemType>; 
      tempRight = inRoot->right; 
      Node<ItemType> * tempLeft = new Node <ItemType>; 
      tempLeft = inRoot->left; 
      inRoot = nullNode; 
      inRoot = temp; 
      temp->left = tempLeft; 
      temp->right = tempRight; 

      return true; 
     } 
     //if inRoot has 1 child 
     else { 
      //if inRoot has left child 
      if (inRoot->right == NULL) { 
       Node<ItemType> * temp = new Node <ItemType>; 
       temp = inRoot->left; 
       inRoot = nullNode; 
       inRoot = temp; 
       return true; 
      } 
      //if inRoot has right child 
      else { 
       Node<ItemType> * temp = new Node <ItemType>; 
       temp = inRoot->right; 
       inRoot = nullNode; 
       inRoot = temp; 
       return true; 
      } 
     } 
    } 
    //If not the node with the data See if toRemove is less than inRoot and perform recursive action 
    else if (toRemove < inRoot->data) { 
     remove_helper (inRoot->left, toRemove); 
    } //end if (toRemove < inRoot->data) 
    //See if toRemove is greater than inRoot and perform recursive action 
    else if (toRemove > inRoot->data) { 
     remove_helper (inRoot->right, toRemove); 
    }// end of else 

    //return false if data cannot be found 
    else return false; 
} 

我的一些結果是不同的,都是錯誤的。其中一個結果就是無限循環不斷打印樹。另一個結果是它會執行刪除操作並顯示成功,但如果您查看兩個打印輸出,它們是相同的,並且該節點不會被刪除(如果返回false,則不應再將其打印出來,但它會這樣做)。然後在第二個print_preorder期間發生第三個結果。它會中斷並停止在一個空節點上,但左側和右側的數據都會顯示「無法讀取內存」。我做錯了什麼?我無法弄清楚。我試圖刪除一個節點之前,我所有的其他樹功能(包括前序打印)。

只是澄清一點,我有我的remove_helper函數的問題。所以我可以移動到從Tree1中刪除Tree2中存在的節點。

+0

剛剛爲結果構建一棵新樹如何?它看起來像集合差異。 –

+0

我不確定你的意思。我的實際代碼有用獨特的隨機數創建的樹。 – kingcobra1986

+0

我的意思是代替修改一棵樹,如果這是困難的地方,只需要在結果中創建一個新的樹。 –

回答

2

remove_helper正在嘗試更改inRoot參數的值。但inRoot是按值傳遞的,因此在函數中所做的任何更改都不會反映在調用函數中。

更改remove_helper功能採取參照inRoot,然後就可以修改調用函數中使用的參數的值:

template<class ItemType> 
bool BTree<ItemType>::remove_helper (Node<ItemType> * &inRoot, ItemType toRemove) { 

而且這個代碼看起來不正確:

//Create Null Node that points to NUll 
    Node<ItemType> * nullNode = new Node <ItemType> ; 

該節點不指向NULL,它指向一個空節點。進一步在代碼中,您正在檢查inRoot->left == NULL,所以您應該將指針設置爲NULL,而不是指向空節點。

您也有很多內存泄漏,請記住 - 如果您使用new創建某個內容,那麼在某處也應該有相應的delete

編輯:還有一兩件事 - 你永遠要做到這一點:

Node<ItemType> * tempRight = new Node <ItemType>; 
tempRight = inRoot->right; 

你分配一些內存,並指向它在tempRight,然後立即設置tempRight到別的東西。這是內存泄漏,是不必要的 - 你不需要爲每個指針分配內存。 將其更改爲:

Node<ItemType> * tempRight = inRoot->right; 
+0

全部是通過參考。哈哈我知道這就像1個字符的變化。我在那裏刪除了它,但由於某種原因它阻止了它的編譯,於是我將它們取出。我想當你刪除一個節點時,應該是這樣的:delete node;節點= NULL;?或者我可以將最後一部分退出?另外,如果我想要一個節點變爲空,我應該只是把Node = NULL?我應該這樣做:Node = Node-> left = Node-> right = NULL? – kingcobra1986

+0

'delete node'將釋放節點中使用的內存。除非您稍後要使用它,否則不必將指針設置爲NULL。是的,設置'Node = NULL'會將節點設置爲NULL,你只需要確保你先通過調用delete來釋放內存,或者在其他地方有一個指向內存的指針(例如在Node-> Left指針)。 –

+0

所以我做了這些改變,但它仍然有問題。我把一個孩子部分下的「一個」,兩個孩子部分下的「兩個」和無孩子部分下的「零」放在一起。我注意到這個問題沒有發生在兩個孩子身上。它會有一個無限循環或只是崩潰。仍然無法讀取內存。 – kingcobra1986

0

你要做的是兩棵樹之間的倒置交叉點。你可以通過創建一個帶有兩個參數的函數來實現。一個參數是你想要從樹中刪除東西的樹(tree1),另一個是你想要檢查的樹(tree2)。

在函數中,然後使用遞歸檢查樹2。對於每個取出的元素,使用該元素來搜索它是否存在於tree1中(並且在這種情況下也將其刪除)。然後你繼續搜索tree1中的每個節點,直到你遍歷了樹2中的每個元素。

+0

對不起,我沒有澄清,我還沒有進入這一步。我想確保我的remove_helper函數在我完成該功能之前完全正常工作。 – kingcobra1986

0

有很多來自@TheDark幫助確定這是我的remove_helper功能:

template<class ItemType> 
bool BTree<ItemType>::remove_helper (Node<ItemType> * &inRoot, ItemType toRemove) { 
    //if this is the node with the data 
    if (inRoot->data == toRemove) { 
     //if inRoot has No Children 
     if (inRoot->left == NULL && inRoot->right == NULL) { 
      inRoot = NULL; 
      std::cout << "one" << std::endl; 
      return true; 
     } 
     //if inRoot has 2 Children 
     else if (inRoot->left != NULL && inRoot->right != NULL) { 
      inRoot->data = return_max_value (inRoot->left)->data; 
      remove_helper (inRoot->left,inRoot->data); 
      std::cout << "two" << std::endl; 
      return true; 
     } 
     //if inRoot has 1 child 
     else { 
      std::cout << "zero" << std::endl; 
      //if inRoot has left child 
      if (inRoot->right == NULL) { 
       Node<ItemType> * temp = new Node <ItemType>; 
       temp = inRoot->left; 
       inRoot = NULL; 
       inRoot = temp; 
       return true; 
      } 
      //if inRoot has right child 
      else { 
       Node<ItemType> * temp = new Node <ItemType>; 
       temp = inRoot->right; 
       inRoot = NULL; 
       inRoot = temp; 
       return true; 
      } 
     } 
    } 
    //If not the node with the data See if toRemove is less than inRoot and perform recursive action 
    else if (toRemove < inRoot->data) { 
     remove_helper (inRoot->left, toRemove); 
    } //end if (toRemove < inRoot->data) 
    //See if toRemove is greater than inRoot and perform recursive action 
    else if (toRemove > inRoot->data) { 
     remove_helper (inRoot->right, toRemove); 
    }// end of else 

    //return false if data cannot be found 
    else return false; 
} 

參照使參數通過後,我固定節點的缺失與2個孩子。我只是從左邊的最大值複製數據,然後從遞歸刪除節點。現在完成了,我可以繼續下一步!感謝大家。