📜  splay tree java 实现 - Java (1)

📅  最后修改于: 2023-12-03 14:47:32.022000             🧑  作者: Mango

Splay Tree Java Implementation

Splay Tree is a self-adjusting binary search tree with the property that recently accessed elements are quick to access again. In this article, we will discuss the implementation of Splay Tree in Java.

Node Class

The first step is to define a Node class, which will represent the nodes of the Splay Tree. Each node will have a key, a left child, a right child, and a parent.

class Node {
    int key;
    Node left;
    Node right;
    Node parent;
 
    Node(int key) {
        this.key = key;
        this.left = null;
        this.right = null;
        this.parent = null;
    }
}
Splay Tree Class

The Splay Tree class will contain the root node of the tree and methods to insert, delete and search for a node. The constructor will initialize the root to null.

class SplayTree {
    Node root;
 
    SplayTree() {
        root = null;
    }
}
Rotations

The Splay Tree uses rotations to maintain the tree structure. There are three types of rotations - zig, zig-zig, and zig-zag. The zig rotation is a simple left or right rotation. The zig-zig rotation involves two consecutive left or right rotations, and the zig-zag rotation involves a left rotation followed by a right rotation or a right rotation followed by a left rotation.

class SplayTree {
    //...
 
    void zig(Node x) {
        Node y = x.parent;
        if (y.left == x) {
            Node b = x.right;
            x.right = y;
            y.left = b;
        } else {
            Node b = x.left;
            x.left = y;
            y.right = b;
        }
        x.parent = y.parent;
        y.parent = x;
        if (x.parent != null) {
            if (x.parent.left == y) {
                x.parent.left = x;
            } else {
                x.parent.right = x;
            }
        }
    }
 
    void zigZig(Node x) {
        Node y = x.parent;
        Node z = y.parent;
        if (y.left == x) {
            Node b = x.right;
            Node c = y.right;
            x.right = y;
            y.left = b;
            y.right = z;
            z.left = c;
        } else {
            Node b = x.left;
            Node c = y.left;
            x.left = y;
            y.right = b;
            y.left = z;
            z.right = c;
        }
        x.parent = z.parent;
        y.parent = x;
        z.parent = y;
        if (x.parent != null) {
            if (x.parent.left == z) {
                x.parent.left = x;
            } else {
                x.parent.right = x;
            }
        }
    }
 
    void zigZag(Node x) {
        Node y = x.parent;
        Node z = y.parent;
        if (y.left == x) {
            Node b = x.right;
            Node c = x.left;
            x.left = y;
            y.right = c;
            x.right = z;
            z.left = b;
        } else {
            Node b = x.left;
            Node c = x.right;
            x.right = y;
            y.left = c;
            x.left = z;
            z.right = b;
        }
        x.parent = z.parent;
        y.parent = x;
        z.parent = x;
        if (x.parent != null) {
            if (x.parent.left == z) {
                x.parent.left = x;
            } else {
                x.parent.right = x;
            }
        }
    }
}
Splay Operation

The Splay operation is the heart of the Splay Tree. It takes a node as input and brings it to the root of the tree by performing a series of rotations. The Splay operation has three main cases:

  1. Zig: The node is either the root of the tree or the child of the root. In this case, we perform a simple rotation to bring the node to the root.
  2. Zig-zig: The node and its parent are both either left or right children of their respective parents. In this case, we perform two consecutive rotations to bring the node to the root.
  3. Zig-zag: The node is either the left child of its parent and the parent is the right child of its grandparent or vice versa. In this case, we perform two rotations - one to bring the node to the root of its parent and another to bring it to the root of the tree.
class SplayTree {
    //...
 
    void splay(Node x) {
        while (x.parent != null) {
            Node y = x.parent;
            Node z = y.parent;
            if (z == null) {
                zig(x);
            } else if ((z.left == y && y.left == x) || (z.right == y && y.right == x)) {
                zigZig(x);
            } else {
                zigZag(x);
            }
        }
        root = x;
    }
}
Search Operation

The search operation in Splay Tree works by first performing a regular binary search for the key and then splaying the node to the root. If the key is not found, we splay the last accessed node to the root.

class SplayTree {
    //...
 
    Node search(int key) {
        Node x = root;
        Node y = null;
        while (x != null) {
            if (key < x.key) {
                y = x;
                x = x.left;
            } else if (key > x.key) {
                y = x;
                x = x.right;
            } else {
                splay(x);
                return x;
            }
        }
        if (y != null) {
            splay(y);
        }
        return null;
    }
}
Insert Operation

The insert operation in Splay Tree works by first performing a regular binary search for the key and then inserting the node in the appropriate position. After insertion, we splay the inserted node to the root.

class SplayTree {
    //...
 
    void insert(int key) {
        if (root == null) {
            root = new Node(key);
        } else {
            Node x = root;
            Node y = null;
            while (x != null) {
                y = x;
                if (key < x.key) {
                    x = x.left;
                } else if (key > x.key) {
                    x = x.right;
                } else {
                    return;
                }
            }
            Node z = new Node(key);
            z.parent = y;
            if (key < y.key) {
                y.left = z;
            } else {
                y.right = z;
            }
            splay(z);
        }
    }
}
Delete Operation

The delete operation in Splay Tree works by first performing a search for the key to be deleted and then deleting the node as we would in a regular binary search tree. After deletion, we splay the parent of the deleted node to the root.

class SplayTree {
    //...
 
    void delete(int key) {
        Node x = search(key);
        if (x == null) {
            return;
        }
        if (x.left != null && x.right != null) {
            Node y = x.right;
            while (y.left != null) {
                y = y.left;
            }
            x.key = y.key;
            x = y;
        }
        Node z;
        if (x.left != null) {
            z = x.left;
        } else {
            z = x.right;
        }
        if (z != null) {
            z.parent = x.parent;
        }
        if (x.parent == null) {
            root = z;
        } else if (x == x.parent.left) {
            x.parent.left = z;
            splay(x.parent.left);
        } else {
            x.parent.right = z;
            splay(x.parent.right);
        }
    }
}
Conclusion

In this article, we discussed the implementation of Splay Tree in Java. We defined a Node class to represent the nodes of the tree, and a SplayTree class to contain the root node and methods to perform operations on the tree. We also discussed the various rotations used in Splay Tree and the Splay operation, which brings a node to the root of the tree. Finally, we implemented the insert, search, and delete operations in the SplayTree class.