Балансировка Строка на основе двоичного поиска дерева (для проверки орфографии)

голоса
1

Обновление: Я не могу получить «Балансировка» работать, потому что я не могу получить «doAVLBalance» распознавать функции - члены «isBalanced ()», «isRightHeavy ()», «isLeftHeavy». И я не знаю , почему! Я попытался пример для Sash (третий ответ) точно , но я получаю «замедление несовместима» , и я не мог исправить это ... так что я пытался делать это мой путь ... и он говорит мне , эти функции - члены не существуют, когда они явно делают.

«Ошибка: класс„IntBinaryTree:.. TreeNode“не имеет ни одного члена„isRightHeavy“Я застрял после попытки в течение последних 4 часов :( Обновленный код ниже, помощь была бы оценена !!

Я создаю строку на основе двоичного поиска дерева и нужно сделать его «Сбалансированный» дерево. Как мне это сделать? * Помогите пожалуйста !! Заранее спасибо!

BinarySearchTree.cpp:

    bool IntBinaryTree::leftRotation(TreeNode *root)
    {
        //TreeNode *nodePtr = root;  // Can use nodePtr instead of root, better?
        // root, nodePtr, this->?

        if(NULL == root)
        {return NULL;}

        TreeNode *rightOfTheRoot = root->right;
        root->right = rightOfTheRoot->left;
        rightOfTheRoot->left = root;

        return rightOfTheRoot;
    }

    bool IntBinaryTree::rightRotation(TreeNode *root)
    {
        if(NULL == root)
        {return NULL;}
        TreeNode *leftOfTheRoot = root->left;
        root->left = leftOfTheRoot->right;
        leftOfTheRoot->right = root;

        return leftOfTheRoot;
    }

    bool IntBinaryTree::doAVLBalance(TreeNode *root)
    {


        if(NULL==root)
            {return NULL;}
        else if(root->isBalanced()) // Don't have isBalanced
            {return root;}

        root->left = doAVLBalance(root->left);
        root->right = doAVLBalance(root->right);

        getDepth(root); //Don't have this function yet

        if(root->isRightHeavy()) // Don't have isRightHeavey
        {
            if(root->right->isLeftheavey())
            {
                root->right = rightRotation(root->right);
            }
            root = leftRotation(root);
        }
        else if(root->isLeftheavey()) // Don't have isLeftHeavey
        {
            if(root->left->isRightHeavey())
            {
                root->left = leftRotation(root->left);
            }
            root = rightRotation(root);
        }
        return root;
    }

    void IntBinaryTree::insert(TreeNode *&nodePtr, TreeNode *&newNode)
    {
        if(nodePtr == NULL)
            nodePtr = newNode;                  //Insert node
        else if(newNode->value < nodePtr->value)
            insert(nodePtr->left, newNode);     //Search left branch
        else
            insert(nodePtr->right, newNode);    //search right branch
    }

//
// Displays the number of nodes in the Tree


int IntBinaryTree::numberNodes(TreeNode *root)
{
    TreeNode *nodePtr = root;

    if(root == NULL)
        return 0;

    int count = 1; // our actual node
    if(nodePtr->left !=NULL)
    { count += numberNodes(nodePtr->left);
    }
    if(nodePtr->right != NULL)
    {
        count += numberNodes(nodePtr->right);
    }
    return count;
} 

    // Insert member function

    void IntBinaryTree::insertNode(string num)
    {
        TreeNode *newNode; // Poitner to a new node.

        // Create a new node and store num in it.
        newNode = new TreeNode;
        newNode->value = num;
        newNode->left = newNode->right = NULL;

        //Insert the node.
        insert(root, newNode);
    }

    // More member functions, etc.

BinarySearchTree.h:

class IntBinaryTree
{
private:
    struct TreeNode
    {
        string value; // Value in the node
        TreeNode *left; // Pointer to left child node
        TreeNode *right; // Pointer to right child node
    };

    //Private Members Functions
    // Removed for shortness
    void displayInOrder(TreeNode *) const;


public:
    TreeNode *root;
    //Constructor
    IntBinaryTree()
        { root = NULL; }
    //Destructor
    ~IntBinaryTree()
        { destroySubTree(root); }

    // Binary tree Operations
    void insertNode(string);
    // Removed for shortness

    int numberNodes(TreeNode *root);
    //int balancedTree(string, int, int); // TreeBalanced

    bool leftRotation(TreeNode *root);
    bool rightRotation(TreeNode *root);
    bool doAVLBalance(TreeNode *root); // void doAVLBalance();
    bool isAVLBalanced();

    int calculateAndGetAVLBalanceFactor(TreeNode *root);

    int getAVLBalanceFactor()
    {
        TreeNode *nodePtr = root; // Okay to do this? instead of just
        // left->mDepth
        // right->mDepth

        int leftTreeDepth = (left !=NULL) ? nodePtr->left->Depth : -1;
        int rightTreeDepth = (right != NULL) ? nodePtr->right->Depth : -1;
        return(leftTreeDepth - rightTreeDepth);
    }

    bool isRightheavey() { return (getAVLBalanceFactor() <= -2); }

    bool isLeftheavey() { return (getAVLBalanceFactor() >= 2); }


    bool isBalanced()
    {
        int balanceFactor = getAVLBalanceFactor();
        return (balanceFactor >= -1 && balanceFactor <= 1);
    }


    int getDepth(TreeNode *root); // getDepth

    void displayInOrder() const
        { displayInOrder(root); }
    // Removed for shortness
};
Задан 02/08/2011 в 05:00
источник пользователем
На других языках...                            


3 ответов

голоса
1

Есть много способов сделать это, но я полагаю, что вы на самом деле не делать это, как и все. Если вы хотите сохранить BST строк, есть гораздо лучшие варианты:

  1. Используйте предварительно составленный двоичный класс дерева поиска. ++ станд :: установлен класс C предлагает те же временные гарантии как сбалансированное бинарное дерево поиска и часто реализуется как таковой. Это значительно проще в использовании, чем качению у вас есть BST.

  2. Вместо этого используйте синтаксическое дерево. Структура Trie данных проще и эффективнее, чем BST строк, не требует балансировки на всех, и быстрее, чем BST.

Если вы действительно должны написать свой собственный сбалансированный BST, у вас есть много вариантов. Большинство реализации BST, которые используют балансировку, чрезвычайно сложны и не для слабонервных. Я хотел бы предложить реализацию либо декартово дерева или скошенное дерево, которые являются два сбалансированной BST структуры, которые достаточно просты в реализацию. Они оба более сложны, чем код, который вы имеете выше, и я не могу в этом коротком пространстве обеспечить реализацию, но поиск Wikipedia для этих структур должно дать вам много советов о том, как продолжить.

Надеюсь это поможет!

Ответил 02/08/2011 в 06:21
источник пользователем

голоса
1

К сожалению, мы программисты буквальные звери.

сделать это «Сбалансированный» дерево.

«Сбалансированный» является контекстно - зависимой. Классы вводных структур данных , как правило , относятся к дереву быть «сбалансированным» , когда разница между узлом наибольшей глубины и узлом наималейшей глубины сведена к минимуму. Однако, как уже упоминались сэр Templatetypedef, расставленное дерево считается балансированием дерева. Это происходит потому , что он может уравновесить деревья , а также в тех случаях, несколько узлов доступ вместе в одно время часто. Это происходит потому , что она занимает меньше узлов обходов для получения данных в скошенном дереве , чем обычное бинарное дерево в этих случаях . С другой стороны, его производительность в худшем случае на основе доступа по доступу может быть так плохо , как связанный список.

Говоря о связанных списках ...

Потому что в противном случае без «Балансировка» это то же самое, как связанный список, я прочитал и поражения цели.

Это может быть плохо, но для рандомизированных вставок это не так . Если вставить уже отсортированные данные, большинство бинарных реализаций дерева поиска будут хранить данные , как раздутые и упорядоченные связанные список. Тем не менее, это только потому , что вы создаете одну сторону дерева постоянно. (Представьте себе , вставляя 1, 2, 3, 4, 5, 6, 7, и т.д ... в бинарном дереве. Попробуйте это на бумаге и посмотреть , что происходит.)

Если у вас есть баланс в теоретическом наихудший-должен-гарантированном смысле, я рекомендую смотреть на красно-черные деревья. (Google это, вторая ссылка очень хорошо.)

Если у вас есть, чтобы сбалансировать его разумным способом для этого конкретного сценария, я бы с целыми индексами и достойной хэш-функции - таким образом балансировку будет происходить вероятностным без какого-либо дополнительного кода. То есть, сделать функцию сравнения выглядит как хэш (Стр) <хэш (STRB) вместо того, что у вас есть в настоящее время. (Для быстрого, но эффективного хэша для этого случая, посмотреть FNV хэширование. Первый удар по Google. Спуститесь вниз, пока не увидите полезный код). Вы можете не беспокоиться о деталях эффективности реализации, если вы хотите. (Например, вы не должны выполнять как хэши каждый раз, когда вы сравниваете, так как одна из строк не меняется.)

Если вы можете уйти с ним, я настоятельно рекомендую последний, если вы находитесь в хруст на время и хотят что-то быстро. В противном случае, красно-черные деревья имеют смысл, так как они чрезвычайно полезны на практике, когда вам нужно свернуть свои собственные высоты уравновешенный бинарных деревьев.

Наконец, обращаясь код выше, см комментарии в коде ниже:

int IntBinaryTree::numberNodes(TreeNode *root)
{
    if(root = NULL) // You're using '=' where you want '==' -- common mistake.
                    // Consider getting used to putting the value first -- that is,
                    // "NULL == root". That way if you make that mistake again, the
                    // compiler will error in many cases.
        return 0;
    /*
    if(TreeNode.left=null && TreeNode.right==null)  // Meant to use '==' again.
    { return 1; }

    return numberNodes(node.left) + numberNodes(node.right);
    */

    int count = 1; // our actual node
    if (left != NULL)
    {
        // You likely meant 'root.left' on the next line, not 'TreeNode.left'.
        count += numberNodes(TreeNode.left);
        // That's probably the line that's giving you the error.
    }
    if (right != NULL)
    {
        count += numberNodes(root.right);
    }
    return count;
}
Ответил 02/08/2011 в 08:10
источник пользователем

голоса
1

Программисты используют понятие AVL дерева , чтобы сбалансировать бинарные дерева. Это довольно просто. Более подробную информацию можно найти в Интернете. Быстрая вики ссылка

Ниже приведен пример кода, который делает баланс дерева, используя алгоритм AVL.

Node *BinarySearchTree::leftRotation(Node *root)
{
    if(NULL == root)
    {
        return NULL;
    }
    Node *rightOfTheRoot = root->mRight;
    root->mRight = rightOfTheRoot->mLeft;
    rightOfTheRoot->mLeft = root;

    return rightOfTheRoot;
}

Node *BinarySearchTree::rightRotation(Node *root)
{
    if(NULL == root)
    {
        return NULL;
    }
    Node *leftOfTheRoot = root->mLeft;
    root->mLeft = leftOfTheRoot->mRight;
    leftOfTheRoot->mRight = root;

    return leftOfTheRoot;
}

Node *BinarySearchTree::doAVLBalance(Node *root)
{
    if(NULL == root)
    {
        return NULL;
    }
    else if(root->isBalanced())
    {
        return root;
    }

    root->mLeft  = doAVLBalance(root->mLeft);
    root->mRight = doAVLBalance(root->mRight);

    getDepth(root);

    if(root->isRightHeavy())
    {
        if(root->mRight->isLeftHeavy())
        {
            root->mRight = rightRotation(root->mRight);
        }
        root = leftRotation(root);
    }
    else if(root->isLeftHeavy())
    {
        if(root->mLeft->isRightHeavy())
        {
            root->mLeft = leftRotation(root->mLeft);
        }
        root = rightRotation(root);
    }

    return root;
}

Определение класса

class BinarySearchTree
{
public:
    // .. lots of methods 
    Node *getRoot();
    int getDepth(Node *root);

    bool isAVLBalanced();
    int calculateAndGetAVLBalanceFactor(Node *root);
    void doAVLBalance();

private:
     Node *mRoot;
};

class Node
{
public:
    int  mData;
    Node *mLeft;
    Node *mRight;
    bool mHasVisited;
    int mDepth;
public:

    Node(int data)
    : mData(data),
      mLeft(NULL),
      mRight(NULL),
      mHasVisited(false),
      mDepth(0)
    {
    }

    int getData()              { return mData; }

    void setData(int data)     { mData = data;  }

    void setRight(Node *right) { mRight = right;}

    void setLeft(Node *left)   { mLeft = left; }

    Node * getRight()          { return mRight; }

    Node * getLeft()           { return mLeft; }

    bool hasLeft()             { return (mLeft != NULL);  }

    bool hasRight()            { return (mRight != NULL); }

    bool isVisited()           { return (mHasVisited == true); }

    int getAVLBalanceFactor()
    {
        int leftTreeDepth = (mLeft != NULL) ? mLeft->mDepth : -1;
        int rightTreeDepth = (mRight != NULL) ? mRight->mDepth : -1;
        return(leftTreeDepth - rightTreeDepth);
    }

    bool isRightHeavy() { return (getAVLBalanceFactor() <= -2); }

    bool isLeftHeavy()  { return (getAVLBalanceFactor() >= 2);  }

    bool isBalanced()
    {
        int balanceFactor = getAVLBalanceFactor();
        return (balanceFactor >= -1 && balanceFactor <= 1);
    }
};
Ответил 02/08/2011 в 17:45
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more