Balansering String basert binært søketre (For Stavekontroll)

stemmer
1

Oppdatering: Jeg kan ikke få Balancing for å fungere, fordi jeg ikke kan få doAVLBalance for å gjenkjenne medlem funksjoner isBalanced (), isRightHeavy (), isLeftHeavy. Og jeg vet ikke hvorfor! Jeg prøvde Sash 'eksempel (tredje svar) nøyaktig, men jeg får retardasjon er uforenlig, og jeg kunne ikke fikse det ... så jeg prøvde å gjøre det på min måte ... og det forteller meg de medlemsfunksjoner ikke eksisterer, når de tydelig gjør.

Feil: class 'IntBinaryTree:.. TreeNode' har ingen medlem 'isRightHeavy' Jeg står fast etter å ha prøvd for de siste 4 timer :( Oppdatert koden under, hjelpe ville være mye verdsatt !!

Jeg oppretter en streng basert binært søketre og trenger å gjøre det til en balansert treet. Hvordan gjør jeg dette? * Hjelp please !! Takk på forhånd!

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
};
Publisert på 02/08/2011 klokken 04:00
kilden bruker
På andre språk...                            


3 svar

stemmer
1

Det er mange måter å gjøre dette, men jeg vil foreslå at du faktisk ikke gjør dette som alt. Hvis du ønsker å lagre en BST av strenger, er det mye bedre alternativer:

  1. Bruk en forhåndsskrevet binært søketre klasse. C ++ std :: satt klassen tilbyr de samme tidsgarantier som et balansert binært søketre og er ofte implementert som sådan. Det er vesentlig enklere å bruke enn å rulle du eier BST.

  2. Bruk en trie stedet. Den trie datastruktur er enklere og mer effektiv enn en BST av strenger, krever ingen balansering i det hele tatt, og er raskere enn en BST.

Hvis du virkelig må skrive din egen balansert BST, har du mange alternativer. De fleste BST implementeringer som bruker balansering er svært komplekse og er ikke for svak til hjertet. Jeg vil foreslå å gjennomføre enten en treap eller spriker tre, som er to balanserte BST strukturer som er ganske enkel å gjennomføre. De er både mer komplisert enn den koden du har ovenfor, og jeg kan ikke i denne korte gi en implementering, men en Wikipedia søk etter disse strukturene bør gi deg masse råd om hvordan du går frem.

Håper dette hjelper!

Svarte 02/08/2011 kl. 05:21
kilden bruker

stemmer
1

Dessverre, vi programmerere er bokstavelig dyr.

gjøre det til en "balansert" treet.

"Balansert" er kontekstavhengig. Den innledende datastrukturer klassene vanligvis referere til et tre som "balansert" når forskjellen mellom noden av største dybde og noden av minst dybde blir minimalisert. Men som nevnt av Sir Templatetypedef er en spriker tre regnes som en balansering tre. Dette er fordi det kan balansere trær i stedet for brønnen i tilfelle at noen noder vist sammen på en gang ofte. Dette er fordi det tar mindre node gjennomløping for å få på dataene i en spriker tre enn en vanlig binært tre i disse tilfellene . På den annen side kan det worst-case ytelse på en access-by-tilgang basis være like ille som en lenket liste.

Snakker av lenkede lister ...

Fordi ellers uten "Balancing" det er det samme som en lenket-liste jeg leste og nederlagene formålet.

Det kan være like ille, men for randomiserte innsatser er det ikke. Hvis du setter inn allerede sorterte data, vil de fleste binært søketre implementeringer lagre data som en oppsvulmet og bestilt lenket liste. Men det er bare fordi du bygger den ene siden av treet kontinuerlig. (Tenk å sette inn 1, 2, 3, 4, 5, 6, 7, osv ... inn i et binært tre. Prøv den på papir og se hva som skjer.)

Hvis du må balansere på en teoretisk worst-case-må-garantert forstand, anbefaler jeg å se opp rød-svart trær. (Google det, er andre linken ganske bra.)

Hvis du må balansere det på en fornuftig måte for dette scenariet, vil jeg gå med heltall indekser og en anstendig hash-funksjon - på den måten balansering vil skje sannsynlighets uten ekstra kode. Det vil si, gjøre sammenligning funksjonen ser ut hash (strA) <hash (STRB) i stedet for hva du har nå. (For en rask, men effektiv hash for denne saken, se opp FNV hashing. Første treff på Google. Gå ned til du ser nyttig kode.) Du kan bekymre seg om detaljene i gjennomføringen effektivitet hvis du vil. (For eksempel, trenger du ikke å utføre både hashes hver eneste gang du sammenligne siden en av strengene aldri endres.)

Hvis du kan komme unna med det, jeg sterkt anbefale sistnevnte hvis du er i en knase for tid og ønsker noe raskt. Ellers rød-svart trær er verdt siden de er svært nyttig i praksis når du trenger å rulle dine egne høyde balanserte binære trær.

Til slutt, adressering koden ovenfor, se kommentarer i koden under:

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;
}
Svarte 02/08/2011 kl. 07:10
kilden bruker

stemmer
1

Programmerere bruker AVL Tre konsepter for å balansere binære trær. Det er ganske enkelt. Mer informasjon finner du på nettet. Hurtig wiki lenke

Nedenfor er eksempelkode som gjør treet balansen ved hjelp AVL algoritme.

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;
}

klasse Definisjon

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);
    }
};
Svarte 02/08/2011 kl. 16:45
kilden bruker

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