Árbol Negro Rojo lento que regulares de búsqueda binaria en mis pruebas

Higigig:

He implementado un árbol Negro Rojo, y quería comparar el tiempo a un árbol de búsqueda binaria regular. Sin embargo, en mis pruebas, he encontrado que la mayoría de las veces, de búsqueda binaria árbol son realmente más rápido. ¿Hay algo malo en mi aplicación, o se supone que esto suceda? Este es mi árbol Negro Rojo:

public class RedBlackTree {

    public class RedBlackNode {
        Integer val;
        RedBlackNode left, right, parent;
        boolean color;

        public RedBlackNode() {

        }

        public RedBlackNode(Integer val) {
            this.val = val;
        }

        @Override
        public String toString() {
            return val + "";
        }

    }

    public static final boolean red = false, black = true;

    public RedBlackNode root;
    public final RedBlackNode nil;
    public int size;

    public RedBlackTree() {
        nil = new RedBlackNode();
        nil.color = black;
        root = nil;
    }

    public void insert(int val) {
        size ++;

        if(root == nil) {
            root = new RedBlackNode(val);
            root.parent = nil;
            root.left = nil;
            root.right = nil;
            root.color = black;
            return;
        }

        RedBlackNode dummy = root;

        while(true) {
            if(val < dummy.val) {
                if(dummy.left == nil) {
                    dummy.left = new RedBlackNode(val);
                    dummy.left.parent = dummy;
                    dummy.left.left = nil;
                    dummy.left.right = nil;
                    dummy.left.color = red;
                    dummy = dummy.left;
                    break;
                }

                dummy = dummy.left;
            } else {
                if(dummy.right == nil) {
                    dummy.right = new RedBlackNode(val);
                    dummy.right.parent = dummy;
                    dummy.right.left = nil;
                    dummy.right.right = nil;
                    dummy.right.color = red;
                    dummy = dummy.right;
                    break;
                }

                dummy = dummy.right;
            }
        }

        balance(dummy);
    }

    private void balance(RedBlackNode node) {
        while(node.parent.color == red) {
            if(node.parent == node.parent.parent.left) {
                if(node.parent.parent.right.color == red) {
                    node.parent.color = black;
                    node.parent.parent.color = red;
                    node.parent.parent.right.color = black;
                    node = node.parent.parent;
                } else {
                    if(node == node.parent.right) {
                        node = node.parent;
                        rotateLeft(node);
                    }

                    node.parent.color = black;
                    node.parent.parent.color = red;
                    rotateRight(node.parent.parent);
                }
            } else {
                if(node.parent.parent.left.color == red) {
                    node.parent.color = black;
                    node.parent.parent.color = red;
                    node.parent.parent.left.color = black;
                    node = node.parent.parent;
                } else {
                    if(node == node.parent.left) {
                        node = node.parent;
                        rotateRight(node);
                    }

                    node.parent.color = black;
                    node.parent.parent.color = red;
                    rotateLeft(node.parent.parent);
                }
            }
        }

        root.color = black;
    }

    private void rotateLeft(RedBlackNode node) {
        RedBlackNode temp = node.right;
        node.right = temp.left;
        temp.left.parent = node;
        temp.parent = node.parent;
        if(node.parent == nil) {
            root = temp;
        } else if(node == node.parent.left) {
            node.parent.left = temp;
        } else {
            node.parent.right = temp;
        }
        temp.left = node;
        node.parent = temp;
    }

    private void rotateRight(RedBlackNode node) {
        RedBlackNode temp = node.left;
        node.left = temp.right;
        temp.right.parent = node;
        temp.parent = node.parent;
        if(node.parent == nil) {
            root = temp;
        } else if(node == node.parent.right) {
            node.parent.right = temp;
        } else {
            node.parent.left = temp;
        }
        temp.right = node;
        node.parent = temp;
    }

    public void printInSorted() {
        printInSorted(root);
    }

    private void printInSorted(RedBlackNode root) {
        if(root == nil) {
            return;
        }

        printInSorted(root.left);
        System.out.print(root.val + " ");
        printInSorted(root.right);
    }

}

Mi árbol de búsqueda binaria:

public class BinarySearchTree {

    public class BinarySearchTreeNode {
        int val;
        BinarySearchTreeNode left, right;

        public BinarySearchTreeNode(int val) {
            this.val = val;
        }
    }

    private BinarySearchTreeNode root;
    private int size;

    public void insert(int val) {
        size ++;

        if(root == null) {
            root = new BinarySearchTreeNode(val);
            return;
        }

        BinarySearchTreeNode dummy = root;

        while(true) {
            if(val < dummy.val) {
                if(dummy.left == null) {
                    dummy.left = new BinarySearchTreeNode(val);
                    break;
                }

                dummy = dummy.left;
            } else {
                if(dummy.right == null) {
                    dummy.right = new BinarySearchTreeNode(val);
                    break;
                }

                dummy = dummy.right;
            }
        }
    }

    public boolean search(int val) {
        return search(root, val);
    }

    private boolean search(BinarySearchTreeNode root, int val) {
        if(root == null) {
            return false;
        }

        if(root.val == val) {
            return true;
        }

        return search(root.left, val) || search(root.right, val);
    }

    public void printInSorted() {
        printInSorted(root);
    }

    private void printInSorted(BinarySearchTreeNode root) {
        if(root == null) {
            return;
        }

        printInSorted(root.left);
        System.out.print(root.val + " ");
        printInSorted(root.right);
    }

    public int[] inSorted() {
        int[] ans = new int[size];
        int count = 0;
        Stack<BinarySearchTreeNode> stack = new Stack<>();
        stack.push(root);

        while(!stack.isEmpty()) {
            BinarySearchTreeNode curr = stack.pop();

            if(curr.left != null || curr.right != null) {
                if(curr.right != null) {
                    stack.push(curr.right);
                    curr.right = null;
                }

                stack.push(curr);

                if(curr.left != null) {
                    stack.push(curr.left);
                    curr.left = null;
                }
            } else {
                ans[count ++] = curr.val;
            }
        }

        return ans;
    }

}

Aquí está mi prueba:

    int better = 0;
    for(int i = 0; i < 30; i ++) {
        RedBlackTree redBlackTree = new RedBlackTree();
        BinarySearchTree binarySearchTree = new BinarySearchTree();
        int[] rand = Utility.createArray(100, 100);

        long start1 = System.currentTimeMillis();
        for(int j : rand) {
            redBlackTree.insert(j);
        }
        long end1 = System.currentTimeMillis();

        long start2 = System.currentTimeMillis();
        for(int j : rand) {
            binarySearchTree.insert(j);
        }
        long end2 = System.currentTimeMillis();

        long total1 = end1 - start1;
        long total2 = end2 - start2;

        if(total1 < total2) {
            better ++;
        }
    }

    System.out.println((double) (better) / 100 + "%");

Esto debe imprimir el porcentaje de la cantidad de veces Árbol Negro Rojo fue más rápido. Utility.createArray(int size, int max)simplemente crea una matriz de tamaño sizey un máximo de maxde números aleatorios. Lo que estoy recibiendo la mayor parte de las veces es porcentajes gusta 0.02%o 0.03%.

Joni:

Este no es un buen punto de referencia. Ver ¿Cómo escribo un micro-punto de referencia correcto en Java?

Para enumerar algunos puntos débiles: System.currentTimeMillisno da suficiente tiempo de resolución, su código no hace "calentar" iteraciones para asegurar el código se compila, no hace nada para garantizar el compilador no lanza el código de distancia, ya que doesn 't tiene efectos secundarios, etc Si usted está interesado en hacer mejores puntos de referencia, sugeriría aprender a usar JMH .

Dicho esto, el hecho de que se va a insertar medios de números aleatorios es muy probable que para evitar los casos patológicos que hacen desequilibradas árboles binarios de búsqueda funcionan mal. Usted está en efecto el uso de un "Treap" (aleatorios árbol binario de búsqueda) . La sobrecarga es menor que en un árbol rojo-negro, así que no es demasiado sorprendente, es posible que vea un mejor rendimiento.

Supongo que te gusta

Origin http://10.200.1.11:23101/article/api/json?id=408487&siteId=1
Recomendado
Clasificación