错误的avltree实现c ++

时间:2017-12-04 14:35:38

标签: c++ visual-c++

这是我目前的avltree实现,avltree.h:

#pragma once
#include <math.h>
#include <algorithm>
#include <iostream>
namespace avltree {

    template <class T>
    struct node {
        static node * null_node;
        node *left = null_node;
        node *right = null_node;
        node *parent = null_node;
        int height = 0;
        T value;
        node(T value) :value(value) {}
        node(T value, int height) :height(height), value(value) {}
    };
    template <class T>
    node<T>* node<T>::null_node = new node(0, -1);

    template <class T>
    struct avltree {
    public:
        node<T> *root;
        avltree(T value);
        node<T> *insert(T value);
        void print(void);
        void print_with_height(void);
    private:
        node<T> *insert(T value, node<T> *x);
        node<T> *left_rotate(node<T> *x);
        node<T> *right_rotate(node<T> *x);
        void retrace(node<T> *n);
        void update_root();
        void print(node<T> *n);
        void print(node<T> *n, int depth);
        void update_height(node<T> *n);
    };
    template <class T>
    avltree<T>::avltree(T value) :root(new node<T>(value)) { }

    template <class T>
    node<T> *avltree<T>::insert(T value) {
        auto n = insert(value, root);
        update_root();
        return n;
    }
    template <class T>
    void avltree<T>::retrace(node<T> *n) {
        while (n != node<T>::null_node) {
            update_height(n);
            if (n->left->height - n->right->height > 1) {
                if (n->left->left->height >= n->left->right->height) {
                    right_rotate(n);
                }
                else {
                    left_rotate(n);
                    right_rotate(n);
                }
            }
            else
                if (n->right->height - n->left->height > 1) {
                    if (n->right->right->height >= n->right->left->height) {
                        left_rotate(n);
                    }
                    else {
                        right_rotate(n);
                        left_rotate(n);
                    }
            }
            n = n->parent;
        }
    }
    template <class T>
    node<T> *avltree<T>::insert(T value, node<T> *n) {
        if (n->value > value) {
            if (n->left != node<T>::null_node) {
                n->left->height++;
                insert(value, n->left);
            }
            else {
                auto new_node = new node<T>(value);
                n->left = new_node;
                new_node->parent = n;
                retrace(n);
                return new_node;
            }
        }
        if (n->value < value) {
            if (n->right != node<T>::null_node) {
                n->right->height++;
                insert(value, n->right);
            }
            else {
                auto new_node = new node<T>(value);
                n->right = new_node;
                new_node->parent = n;
                retrace(n);
                return new_node;
            }
        }
        update_height(n);
        return n;
    }
    template <class T>
    node<T> *avltree<T>::left_rotate(node<T> *x) {
        node<T> *y = x->right;
        if (y == node<T>::null_node) {
            return node<T>::null_node;
        }
        y->parent = x->parent;
        if (x->parent->right == x) {
            x->parent->right = y;
        }
        else {
            x->parent->left = y;
        }

        y->left = x;
        x->parent = y;

        x->right = y->left;
        x->right->parent = x;

        update_height(x);
        update_height(y);

        return x;
    }
    template <class T>
    node<T> *avltree<T>::right_rotate(node<T> *x) {
        node<T> *y = x->left;
        if (y == node<T>::null_node) {
            return node<T>::null_node;
        }
        y->parent = x->parent;
        if (x->parent->right == x) {
            x->parent->right = y;
        }
        else {
            x->parent->left = y;
        }

        y->right = x;
        x->parent = y;

        x->left = y->right;
        x->left->parent = x;

        update_height(x);
        update_height(y);

        return x;
    }
    template <class T>
    void avltree<T>::update_root() {
        auto n = root, last = root;
        while (n != node<T>::null_node) {
            last = n;
            n = n->parent;
        }
        root = last;
    }
    template <class T>
    void avltree<T>::print(void) {
        print(root);
        cout << endl;
    }
    template <class T>
    void avltree<T>::print(node<T> *n) {
        if (n->left != node<T>::null_node) {
            print(n->left);
        }
        cout << n->value << " ";
        if (n->right != node<T>::null_node) {
            print(n->right);
        }
    }
    template <class T>
    void avltree<T>::print(node<T> *n, int height) {
        if (n->left != node<T>::null_node) {
            print(n->left, height);
        }
        if (n->height == height) {
            std::cout << n->value << ", ";
        }
        if (n->right != node<T>::null_node) {
            print(n->right, height);
        }
    }
    template <class T>
    void avltree<T>::print_with_height(void) {
        int height = root->height;
        for (int height = root->height; height >= 0; height--) {
            std::cout << "height = " << height << "\t:";
            print(root, height);
            std::cout << std::endl;
        }
        std::cout << std::endl;
    }
    template <class T>
    void avltree<T>::update_height(node<T> *n) {
        n->height = std::max(n->left->height, n->right->height) + 1;
    }
}

以下是主要文件:

#include "stdafx.h"
#include "avltree.h"

int main()
{
    avltree::avltree<int> tree(1);
    for (int i = 2; i < 128; i++) {
        tree.insert(i);
    }
    tree.print_with_height();

    return 0;
}

上面代码的问题是,在迭代124,它将在插入中的回扫调用内生成无限循环。基本上,节点将以不能到达根节点的方式继续旋转(导致无限循环)。我已经检查了一些简单的例子(对于一些节点)并且它们有效。提供跑步的所有内容,如果有经验的人可以花时间运行这个程序,我会很感激,也许会发现回溯/轮换中出现了什么问题。

1 个答案:

答案 0 :(得分:1)

获得类似的无限循环表示旋转功能可能存在问题。快速查看left_rotate节目

    y->left = x;
    x->parent = y;

    x->right = y->left;

最后一次作业中y->left是什么? x,所以你真正的x->right = x。这显然是一个需要解决的问题。

right_rotate中存在类似的问题。