【问题标题】:Deleting a node from a binary search tree without recursion不递归地从二叉搜索树中删除节点
【发布时间】:2017-07-15 20:00:53
【问题描述】:

我有一个二叉搜索树。我想从中删除一个节点:

void deleteANode(struct node *head, int value) {
    //let us find the node
    struct node *temp = head;
    struct node *parent = NULL;

    //let us find the node
    while (temp != NULL) {
        if (value > temp->data) {
            parent = temp;
            temp = temp->right;
        } else
        if (value < temp->data) {
            parent = temp;
            temp = temp->left;
        } else {
            //let us check for child nodes
            //
            if (temp->left == NULL && temp->right == NULL) {
                printf("Deleting a leaf.\n");

                temp = NULL;
                printf("Set temp null.\n");
                free(temp);
                break;
            } else
            if (temp->left == NULL || temp->right == NULL) {
                printf("Deleting a one child.\n");
                //one of the child is null
                if (temp->left != NULL) {
                    parent->left = temp->left;
                } else {
                    parent->right = temp->right;
                }
                free(temp);
            } else {
                printf("Deleting two child parent.\n");
                //both of them are not NULL
                //need to find the pre-order successor
                struct node *temp2 = temp->right;

                while (temp2->left != NULL) {
                    temp2 = temp2->left;
                }
                //found the successor.
                temp->data = temp2->data;
                free(temp);
            }
            break;
        }
    }
}

我正在尝试删除此块中的叶节点:

if (temp->left == NULL && temp->right == NULL) {
    printf("Deleting a leaf.\n");

    temp->data = NULL;
    printf("Set temp null.\n");
    free(temp);
    break;
}

但是上面的代码不起作用。

我在调用上面的方法:

deleteANode(head, 3);

前序遍历前后一致:

5 4 3 10 7 20 删除叶子。将临时设置为空。 =============== 5 4 3 10 7 20

我做错了什么。

根据@pstrjds cmets 更新:

if (temp->left == NULL && temp->right == NULL ) {
    printf("Deleting a leaf.\n");
    parent->left = NULL;
    parent->right = NULL;
    free(temp);
    temp = NULL;
    printf("Set temp null.\n");
    break;
}

叶子节点工作正常。需要为有两个孩子的节点工作。

【问题讨论】:

  • 好吧,一方面,您在调用 free 之前将 temp 设置为 NULL。您可能应该首先释放它(这是在检查叶子的 if 块中)
  • You should probably free it first.?应该还是必须?我认为免费首先意味着它不再存在。虽然这样做并不能解决我的问题,但它会为已删除的密钥提供 0 而不是 3
  • 我应该更清楚,抱歉,您应该在将 temp 设置为 null 之前调用 free(temp),否则您不会释放节点,只是在 null 上调用 free。您还需要确保父节点不再指向它。
  • 做了同样的事情,但得到了输出:5 4 3 10 7 20 Deleting a leaf. Set temp null. =============== 5 4 0 10 7 20。好的,我需要另一个节点作为父节点才能使其工作吗?
  • 你能用你更新的代码更新问题吗 - 从新的输出来看,在我看来你没有修复叶节点的父节点,所以父节点指向一个空节点或那种性质的东西。

标签: c data-structures tree


【解决方案1】:

在删除叶子的代码块中,您实际上并没有释放节点,也没有更新父节点以不再指向它。

if ( temp -> left == NULL && temp -> right == NULL )
{
    printf("Deleting a leaf.\n");
    if (parent->left == temp)
    {
        parent->left = NULL;
    }
    else
    {
        parent->right = NULL;
    }

    free(temp);
    temp = NULL;
    printf("Set temp null.\n");
    break;
 }

您实际上可以删除temp = NULL 行并将break; 更改为return 语句。

【讨论】:

  • 感谢您的帮助。您的代码工作正常。 temp = NULL 在这里没用。但是change the break; to a return statement. 是什么意思?我应该从这一点回来。我在 while 循环中使用了所有这些逻辑。我认为打破也会做同样的事情。
  • @learner - 它确实完成了同样的事情,但不同之处在于可读性。如果我在代码中看到 break 语句,我必须查看循环在哪里,然后在循环之后搜索以查看可能发生的其他情况。如果我看到一个 return 语句,我知道该方法将在 return 语句处完成执行。在我看来,return 语句会更好地表达意图,并清楚地表明该方法在此时完成。
【解决方案2】:

您的代码真的有效吗? 应该是这样的:

printf("Deleting two child parent.\n");
Node* temp2 = temp->right;
while(temp2->left != NULL)
{
    parent = temp2;
    temp2 = temp2->left;
}

temp->data = temp2->data;
parent->left = NULL;
delete temp2;

return;

【讨论】:

  • 在我之前的回复中更正: parent->left = temp2->right;删除 temp2 之前
【解决方案3】:

Java 解决方案

// Java program to demonstrate delete operation in binary search tree 
class BinarySearchTree 
{ 
  /* Class containing left and right child of current node and key value*/
  class Node 
  { 
    int key; 
    Node left, right; 

    public Node(int item) 
    { 
        key = item; 
        left = right = null; 
    } 
} 

// Root of BST 
Node root; 

// Constructor 
BinarySearchTree() 
{ 
    root = null; 
} 

// This method mainly calls deleteRec() 
void deleteKey(int key) 
{ 
    root = deleteRec(root, key); 
} 

/* A recursive function to insert a new key in BST */
Node deleteRec(Node root, int key) 
{  Node x=root;
 Node parent =null;
    /* Base Case: If the tree is empty */
    while(x!=null)
    {
      if(x.key>key)
      { parent=x;
        x=x.left;
      }
      else if(x.key<key)
      {parent=x;
        x=x.right;
      }
      else
      {
        if(x.left==null&&x.right==null)
        {
         System.out.println(x.key+"y1");
          if(parent.left==x)
          parent.left=null;
          else if(parent.right==x)
          parent.right=null;

          x=null;

          break;
        }
        else
        {
          System.out.println(x.key+"y2");
          if(x.left==null)
          { 
            if(parent.right==x)
            parent.right=x.right;
            else if(parent.left==x)
             parent.left=x.right;
            System.out.println(x.key+"yes");
            x=null;
            break;
          }
          else if(x.right==null)
          {
            if(parent.left==x)
            parent.left=x.left;
            else if(parent.right==x)
            parent.right=x.left;
            x=null;
            break;
          }
          else
          {
            Node temp=x;
            Node px=null;
            temp=temp.right;
            while(temp.left!=null)
            { px=temp;
              temp=temp.left;
            }
            x.key=temp.key;
            if(px.left==temp)
            px.left=null;
            else if(px.left==temp)
            px.right=null;
            temp=null;
            break;
          }
        }
      }
    }
  return root;
} 

int minValue(Node root) 
{ 
    int minv = root.key; 
    while (root.left != null) 
    { 
        minv = root.left.key; 
        root = root.left; 
    } 
    return minv; 
} 

// This method mainly calls insertRec() 
void insert(int key) 
{ 
    root = insertRec(root, key); 
} 

/* A recursive function to insert a new key in BST */
Node insertRec(Node root, int key) 
{ 

    /* If the tree is empty, return a new node */
    if (root == null) 
    { 
        root = new Node(key); 
        return root; 
    } 

    /* Otherwise, recur down the tree */
    if (key < root.key) 
        root.left = insertRec(root.left, key); 
    else if (key > root.key) 
        root.right = insertRec(root.right, key); 

    /* return the (unchanged) node pointer */
    return root; 
} 

// This method mainly calls InorderRec() 
void inorder() 
{ 
    inorderRec(root); 
} 

// A utility function to do inorder traversal of BST 
void inorderRec(Node root) 
{ 
    if (root != null) 
    { 
        inorderRec(root.left); 
        System.out.print(root.key + " "); 
        inorderRec(root.right); 
    } 
} 

// Driver Program to test above functions 
public static void main(String[] args) 
{ 
    BinarySearchTree tree = new BinarySearchTree(); 

    /* Let us create following BST 
        50 
    /    \ 
    30   70 
    / \ / \ 
    20 40 60 80 */
    tree.insert(50); 
    tree.insert(30); 
    tree.insert(20); 
    tree.insert(40); 
    tree.insert(70); 
    tree.insert(60); 
    tree.insert(80); 

    System.out.println("Inorder traversal of the given tree"); 
    tree.inorder(); 

    System.out.println("\nDelete 20"); 
    tree.deleteKey(20); 
    System.out.println("Inorder traversal of the modified tree"); 
    tree.inorder(); 

    System.out.println("\nDelete 30"); 
    tree.deleteKey(30); 
    System.out.println("Inorder traversal of the modified tree"); 
    tree.inorder(); 

    System.out.println("\nDelete 50"); 
    tree.deleteKey(50); 
    System.out.println("Inorder traversal of the modified tree"); 
    tree.inorder(); 
  } 
} 

【讨论】:

    猜你喜欢
    • 2015-04-08
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    相关资源
    最近更新 更多