实现Splay树

扩展树是一种自平衡二进制搜索树,具有最近访问的元素可以快速再次访问的附加属性。它以O(log n)摊销时间执行基本操作,例如插入,查找和删除。对于许多非随机操作序列,即使序列的具体模式未知,八叉树的性能也比其他搜索树好。

我在splay树中的remove方法有一些问题。谁能帮我吗?

struct Node {
    int key;
    string value;
    Node* parent;
    Node* left;
    Node* right;

    Node(int key,const string& value) {
        this->key = key;
        this->parent = nullptr;
        this->left = nullptr;
        this->right = nullptr;
        this->value = value;
    }
};

void SplayTree::zig(Node *node) {
    Node *p = node->parent;
    node->parent = nullptr;
    p->parent = node;
    Node *c = nullptr;

    if (p->left == node) {
        c = node->right;
        node->right = p;
        p->left = c;
    } else {
        c = node->left;
        node->left = p;
        p->right = c;
    }

    if (c != nullptr) {
        c->parent = p;
    }
}

void SplayTree::zigZig(Node *node) {
    Node *p = node->parent;
    Node *pp = p->parent;
    node->parent = pp->parent;
    p->parent = node;

    if (p->left == node) {
        Node *c = node->right;
        Node *pc = p->right;

        node->right = p;

        p->left = c;
        p->right = pp;

        pp->parent = p;
        pp->left = pc;

        if (node->parent != nullptr) {
            if (node->parent->left == pp)
                node->parent->left = node;
            else
                node->parent->right = node;
        }

        if (c != nullptr)
            c->parent = p;

        if (pc != nullptr)
            pc->parent = pp;
    }
    else {
        Node *c = p->left;
        Node *pc = node->left;

        node->left = p;

        p->left = pp;
        p->right = pc;

        pp->parent = p;
        pp->right = c;

        if (node->parent != nullptr) {
            if (node->parent->left == pp)
                node->parent->left = node;
            else
                node->parent->right = node;
        }

        if (c != nullptr)
            c->parent = pp;

        if (pc != nullptr)
            pc->parent = p;
    }
}

void SplayTree::zigZag(Node *node) {
    Node *p = node->parent;
    Node *pp = p->parent;
    Node *cl = node->left;
    Node *cr = node->right;
    node->parent = pp->parent;
    p->parent = node;
    pp->parent = node;

    if (p->right == node) {
        node->left = p;
        node->right = pp;
        p->right = cl;
        pp->left = cr;

        if (cl != nullptr)
            cl->parent = p;

        if (cr != nullptr)
            cr->parent = pp;
    } else {
        node->left = pp;
        node->right = p;
        p->left = cr;
        pp->right = cl;

        if (cl != nullptr)
            cl->parent = pp;

        if (cr != nullptr)
            cr->parent = p;
    }
    if (node->parent != nullptr) {
        if (node->parent->left == pp)
            node->parent->left = node;
        else
            node->parent->right = node;
    }
}

void SplayTree::splay(Node *node) {
    while (node->parent != nullptr) {
        Node *p = node->parent;
        Node *pp = p->parent;
        if (pp == nullptr)
            zig(node);
        else if ((pp->left == p && p->left == node) || (pp->right == p && p->right == node))
            zigZig(node);
        else
            zigZag(node);
    }
    this->root = node;
}

SplayTree::SplayTree() {
    this->root = nullptr;
}

Node* SplayTree::find(int key) {
    Node *res = nullptr;
    Node *cur = this->root;
    Node *prev = nullptr;
    while (cur != nullptr) {
        prev = cur;
        if (key < cur->key)
            cur = cur->left;
        else if (key > cur->key)
            cur = cur->right;
        else {
            res = cur;
            break;
        }
    }
    if (res != nullptr)
        splay(res);
    else if (prev != nullptr)
        splay(prev);
    return res;
}

void SplayTree::insert(int key,const string& value) {
    if (root == nullptr) {
        root = new Node(key,value);
        return;
    }
    Node *cur = this->root;
    while (cur != nullptr) {
        if (key < cur->key) {
            if (cur->left == nullptr) {
                Node *node = new Node(key,value);
                cur->left = node;
                node->parent = cur;
                splay(node);
                return;
            }
            else
                cur = cur->left;
        }
        else if (key > cur->key) {
            if (cur->right == nullptr) {
                Node *node = new Node(key,value);
                cur->right = node;
                node->parent = cur;
                splay(node);
                return;
            }
            else
                cur = cur->right;
        } else {
            splay(cur);
            return;
        }
    }
}

void SplayTree::remove(int key) {
    Node *n = find(key);
    if (n == nullptr) {
        return;
    }
    Node *l = n->left;
    Node *r = n->right;
    if (l == nullptr && r == nullptr) {
        this->root = nullptr;
    } else if (l == nullptr) {
        Node *k = r;
        while (k->left != nullptr)
            k = k->left;
        splay(k);
    } else {
        Node *k = l;
        while (k->right != nullptr)
            k = k->right;
        splay(k);
        if (r != nullptr) {
            k->right = r;
            r->parent = k;
        }
    }
    delete n;
}

当我添加键1和2时,我正在尝试删除带有1的节点。代码无法正常工作,因为带有键1的节点没有删除;

cywmm 回答:实现Splay树

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3106769.html

大家都在问