简体   繁体   English

是否可以优化此递归 function?

[英]Is it possible to optimize this recursive function?

I am trying to understand if this is the fastest way possible to delete a node in the Tree.我试图了解这是否是删除树中节点的最快方法。

struct node *deleteNode(struct node *root, char *key)
{
    // base case
    if (root == NULL)
        return root;

    // If the key to be deleted
    // is smaller than the root's
    // key, then it lies in left subtree
    if (strcmp(key, root->key) < 0)
        root->left = deleteNode(root->left, key);

    // If the key to be deleted
    // is greater than the root's
    // key, then it lies in right subtree
    else if (strcmp(key, root->key) > 0)
        root->right = deleteNode(root->right, key);

    // if key is same as root's key,
    // then This is the node
    // to be deleted
    else
    {
        // node with only one child or no child
        if (root->left == NULL)
        {
            struct node *temp = root->right;
            free(root);
            return temp;
        }
        else if (root->right == NULL)
        {
            struct node *temp = root->left;
            free(root);
            return temp;
        }

        // node with two children:
        // Get the inorder successor
        // (smallest in the right subtree)
        struct node *temp = minValueNode(root->right);

        // Copy the inorder
        // successor's content to this node
        root->key = temp->key;

        // Delete the inorder successor
        root->right = deleteNode(root->right, temp->key);
    }
    return root;
}

It takes a tree and a word and deletes the node from the tree.它需要一棵树和一个单词,然后从树中删除该节点。 The thing I want to understand is when do I reach a "perfect" optimization level?我想了解的是我什么时候达到“完美”的优化水平? I have worked a lot on this code and I think it is the best way possible.我在这段代码上做了很多工作,我认为这是最好的方法。 What can I look for more?我还能寻找什么?

First the initial parameter to deleteNode is the root, but you should actually name it just node or subtree .首先 deleteNode 的初始参数是根,但实际上您应该将其命名为nodesubtree

You should free the key, and strdup the key on node creation.您应该free密钥,并在创建节点时strdup密钥。

Finding the value at that node you cannot immediately delete that node.在该节点上查找值您不能立即删除该节点。 Either look at the left's max value (left - rights - rightnull node) or rights min value (right - lefts - leftnull node).要么查看左侧的最大值(左侧 - 右侧 - 右侧空节点),要么查看右侧最小值(右侧 - 左侧 - 左侧空节点)。

You have three pointers, root, xnull node, and the xnull node's other subtree.您有三个指针,根、xnull 节点和 xnull 节点的另一个子树。 One form of deleting is called rotating the pointers .一种删除形式称为旋转指针

Notice you do copy the key.请注意,您确实复制了密钥。 In C++ that could be more costly that a pointer copy.在 C++ 中,这可能比指针复制成本更高。 In C copying a pointer or at most a struct is similarly costly, though I would favor a pointer copy.在 C 中,复制一个指针或至多一个结构同样昂贵,尽管我更喜欢指针复制。

Then you descend the branch again, so there can be optimized a bit;然后你再次下降分支,所以可以稍微优化一下; at least more immediate.至少更直接。

struct node *deleteNode(struct node *tree, char *key)
{
    // base case
    if (tree == NULL)
        return tree;

    // If the key to be deleted
    // is smaller than the tree's
    // key, then it lies in left subtree
    int cmp = strcmp(key, tree->key); // Thanks to RachidK
    if (cmp < 0)
        tree->left = deleteNode(tree->left, key);

    // If the key to be deleted
    // is greater than the tree's
    // key, then it lies in right subtree
    else if (cmp > 0)
        tree->right = deleteNode(tree->right, key);

    // if key is same as tree's key,
    // then This is the node
    // to be deleted
    else
    {
        struct node *result;
        // node with only one child or no child
        if (tree->left == NULL)
        {
            result = tree->right;
        }
        else if (tree->right == NULL)
        {
            result = tree->left;
        }
        else
        {
            // node with two children:
            // Get the inorder successor
            // (smallest in the right subtree)
            struct node **successor = &(tree->right);
            while ((*successor)->left != NULL)
            {
                successor = &(*successor)->left;
            }
            // rotate pointers:
            result = *successor;
            result->left = tree->left;
            *successor = result->right;
            result->right = tree->right;
        }
        free(tree->key);
        free(tree);
        return result;
    }
    return tree;
}

I did not test it.我没有测试它。 Not successor being an alias of first a right and then of left fields.不是successor是第一个right字段的别名,然后是left字段的别名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM