AVL Tree 平衡二叉树

使用例子:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <iostream.h>

#include "AVLTree.h"

using namespace std;

class CCity
{
public:
    CCity(const char* city = NULL);
    virtual ~CCity();

    virtual int Compare(const CCity& other) const;

    char szCity[32];
};

CCity::CCity(const char* city)
{
    sprintf(szCity,"%s",city);
}

CCity::~CCity()
{
    memset(szCity,0x00,sizeof(szCity));
}

int CCity::Compare(const CCity& other) const
{
    return strcmp(szCity,other.szCity);
}

int main()
{
    bool demo = true;

    if (demo)
    {
        cout << endl << endl << endl;
        cout << "Demo: AVL-Tree with user class" << endl;
        cout << "----------------------------------" << endl;
        CAVLTree<CCity> tree2;
        tree2.Insert(new CCity("London"));
        tree2.Insert(new CCity("Paris"));
        tree2.Insert(new CCity("Moskau"));
        tree2.Insert(new CCity("Helsinki"));
        tree2.Insert(new CCity("Canberra"));
        tree2.Insert(new CCity("Athen"));
        tree2.Insert(new CCity("Irkutsk"));
        tree2.Insert(new CCity("Paris"));
        tree2.Insert(new CCity("Berlin"));
        tree2.Insert(new CCity("Hamburg"));
        tree2.Insert(new CCity("Mexico"));
        tree2.Insert(new CCity("Aden"));
        tree2.Insert(new CCity("Rom"));
        // create an iterator and iterate throw all nodes in the tree
        //  for sorted output
        CAVLTreeIterator<CCity> iter2(tree2);
        for (iter2.MoveFirst(); iter2; iter2++)
        {
            // note: GetData() returns CCity*
            cout << iter2.GetData()->szCity << endl;
        }
        cout << "----------------------------------" << endl;

        CCity city1("Paris");
        CCity city2("Frankfurt");
        if (tree2.Search(city1))
            cout << "\"" << city1.szCity << "\" is in the tree." << endl;
        else
            cout << "\"" << city1.szCity << "\" is in not the tree." << endl;
        if (tree2.Search(city2))
            cout << "\"" << city2.szCity << "\" is in the tree." << endl;
        else
            cout << "\"" << city2.szCity << "\" is in not the tree." << endl;
        cout << "Press any key to continue" << endl;
        cout << "nodes:" << tree2.GetRoot()->NodesInTree()<<endl;
        cout << "depth:" << tree2.GetDepth()<<endl;
        cout << "NODES:" << tree2.NodesInTree() << endl;
    }

    return 0;
}


AVL Tree  代码:

// Creator: Andreas J?ger
//          Ortsstr. Nr. 2
//        D-07407 Geitersdorf
//
// Last updated: 17. April 1999
// e-mail: Jaeger-Geitersdorf@t-online.de
//
//
// Copyright and author:
// Andreas J?ger: Jaeger-Geitersdorf@t-online.de
//
// You may handle this code to others only when you do not delete these
// copyright-lines.
// These source files may not be copied except by permission of the author.
// These source files may not be included in source or compiled form as any
// part of a commercial distribution except by permission of the
// author.
// These files may be used freely for internal corporate use.
// These files may also may be used freely by students for
// educational purposes.
// No warranty or guarrantee of fitness can be made to these files.
//
//
// have fun!
//
// Updates:
//
// * 15.11.1998 - Some fixes in Delete()- and RestructureDelete()-
//                routines which could make the tree inconsistent
//                and result in a GPF (after lots of Insert- and
//                Delete-operations)
//              - Rename Level() -> GetLevel()
//              - new methods GetDepth() and NodesInTree() for
//                CAVLTree class
//              - new (debug) function CheckBalances()
//              - Draw() function only in Visual C++ environment
//                (not Borland) for portability
//              - updated sample project
//
// * 17.04.1999 - Enhancement of CAVLTreeIterator: delete current node
//

// Note:                                                      //
// there must be a function T::Compare(T&)                    //
// or the function Compare of teh Template-Klasse             //
// CAVLNode<T> has to be overridden.                          //



// Vorbemerkungen:                                            //
// Es mu? eine Funktion T::Compare(T&) definiert sein         //
// oder es mu? die Funktion Compare der Template-Klasse       //
// CAVLNode<T> ?berschrieben werden.                          //


// Forward-Deklarationen
//template <class T>
//class CAVLNode;

#ifndef __AVL_TREE_H__
#define __AVL_TREE_H__

template <class T>
class CAVLTree;

template <class T>
class CAVLTreeIterator;

/* siehe unter
template <class T>
class CAVLTreeDialog;
*/


// AVL-treenode (=subtree) (Template-Version)                 //



// AVL-Baumknoten (=Teilbaum) (Template-Variante)             //


template <class T>
class CAVLNode
{
public:
    // standard constructor, constructors, destructor
    // Standard-Konstruktor, Konstruktor(en) und Destruktor
    CAVLNode(
			T* data,
			int balance = 0,
			CAVLNode<T>* parent = NULL,
			CAVLNode<T>* left = NULL,
			CAVLNode<T>* right = NULL
	);
    virtual ~CAVLNode();

    // searching
    // Suchen
    CAVLNode<T>* Search(const T* data);

    // comparing
    // Vergleich
    static int Compare(const T& t1, const T& t2);

    // information about the position in the tree
    // Informationen ?ber die Position im Baum
    bool IsRoot() const;
    bool IsLeftSibling() const;
    bool IsRightSibling() const;
    bool HasLeftSibling() const;
    bool HasRightSibling() const;

    // further information
    // Weitere Informationen
    int GetDepth() const;
    int GetLevel() const;
    int NodesInTree() const;

    // navigation in the tree
    // Navigation im Baum
    CAVLNode<T>* GetRoot();

    CAVLNode<T>* GetLeftSibling();
    CAVLNode<T>* GetRightSibling();

    CAVLNode<T>* GetFirstNodeInOrder();
    CAVLNode<T>* GetLastNodeInOrder();

    CAVLNode<T>* GetPrevNodeInOrder();
    CAVLNode<T>* GetNextNodeInOrder();

    // restructuration
    // Restrukturierungs-Ma?nahmen
    bool LeftRotation();
    bool RightRotation();
    bool DoubleRotationLeft();
    bool DoubleRotationRight();


    // Diagnostics
    bool CheckBalances(const char * buffer = NULL, unsigned int buflen = 0) const;

    // drawing into a device context, not fully implemented
    // Visualisierung in einem Ger?tekontext
#ifdef _MSC_VER
    void Draw(CDC* dc, CRect& rect);
#endif

    // item-data
    // Datenelement
    T* Data;

    // informationen about the height of the subtrees
    // -1: left subtree is by 1 higher than the right one
    //  0: both subtrees have the same height
    //  1: right subtree is by 1 higher than the left one

    // Informationen ?ber die Tiefe der Teilb?ume
    // -1: linker Baum ist um 1 tiefer als rechter
    //  0: beide Teilb?ume haben die gleiche Tiefe
    //  1: rechter Baum ist um 1 tiefer als linker

    int Balance;

    // parent node
    // ?bergeordneter Knoten
    CAVLNode<T>* Parent;

    // left and right subtree
    // Linker und rechter Teilbaum
    CAVLNode<T>* Left;
    CAVLNode<T>* Right;
private:
    CAVLNode<T>* GetInsertPosition(const T* data);
    bool RestructureInsert();
    bool RestructureDelete();

    CAVLNode(const CAVLNode<T>& /*tree*/) {};
    CAVLNode& operator= (const CAVLNode<T>& /*tree*/) {return *this;};

    friend class CAVLTree<T>;
};

template <class T>
CAVLNode<T>::CAVLNode(T* data, int balance, CAVLNode<T>* parent, CAVLNode<T>* left, CAVLNode<T>* right)
    : Data(data),
      Balance(balance),
      Parent(parent),
      Left(left),
      Right(right)
{
};

template <class T>
CAVLNode<T>::~CAVLNode()
{
    delete Left;
    delete Right;
    delete Data;
};

template <class T>
bool CAVLNode<T>::RestructureInsert()
{
    CAVLNode<T>* item = this;
    while (!item->IsRoot())
    {
        // rule 1
        // Regel 1
        if (item->IsLeftSibling() && item->Parent->Balance == 0)
        {
            item->Parent->Balance = -1;
            item = item->Parent;
            continue;
        }
        if (item->IsRightSibling() && item->Parent->Balance == 0)
        {
            item->Parent->Balance = 1;
            item = item->Parent;
            continue;
        }
        // rule 2
        // Regel 2
        if (item->IsLeftSibling() && item->Parent->Balance == 1)
        {
            item->Parent->Balance = 0;
            break;
        }
        if (item->IsRightSibling() && item->Parent->Balance == -1)
        {
            item->Parent->Balance = 0;
            break;
        }
        // rule 3
        // Regel 3
        if (item->IsLeftSibling() && item->Parent->Balance == -1)
        {
            if (item->Balance == 1)
                item->Parent->DoubleRotationLeft();
            else
                item->Parent->RightRotation();
            break;
        }
        if (item->IsRightSibling() && item->Parent->Balance == 1)
        {
            if (item->Balance == -1)
                item->Parent->DoubleRotationRight();
            else
                item->Parent->LeftRotation();
            break;
        }
    }
    return true;
};

template <class T>
bool CAVLNode<T>::RestructureDelete()
{
    // Regeln f?r den Elternknoten des gerade gel?schten Blattes
    // anwenden, bevor mit dem eigentlichen Aufstieg begonnen
    // werden kann
    CAVLNode<T>* item = this;
    // Regel 1
    if (item->Balance == 0 && item->Left == NULL)
    {
        item->Balance = 1;
        return true;
    }
    if (item->Balance == 0 && item->Right == NULL)
    {
        item->Balance = -1;
        return true;
    }
    // Regel 2
    if (item->Balance == -1 && item->Left == NULL)
    {
        item->Balance = 0;
    }
    if (item->Balance == 1 && item->Right == NULL)
    {
        item->Balance = 0;
    }
    // Regel 3
    if (item->Balance == -1 && item->Right == NULL)
    {
        if (item->Left->Balance == 1)
        {
            item->DoubleRotationLeft();
            item = item->Parent; // Zeiger sind durch die Rotation etwas verrutscht
        }
        else
        {
            item->RightRotation();
            item = item->Parent; // Zeiger sind durch die Rotation etwas verrutscht
        }
        if (item->Balance == 1)
            return true;
    }
    if (item->Balance == 1 && item->Left == NULL)
    {
        if (item->Right->Balance == -1)
        {
            item->DoubleRotationRight();
            item = item->Parent; // Zeiger sind durch die Rotation etwas verrutscht
        }
        else
        {
            item->LeftRotation();
            item = item->Parent; // Zeiger sind durch die Rotation etwas verrutscht
        }
        if (item->Balance == -1)
            return true;
        //return true;
    }
    // Beginn des eigentlichen Aufstiegs
    while (!item->IsRoot())
    {
        // Regel 1
        if (item->IsLeftSibling() && item->Parent->Balance == 0)
        {
            item->Parent->Balance = 1;
            break;
        }
        if (item->IsRightSibling() && item->Parent->Balance == 0)
        {
            item->Parent->Balance = -1;
            break;
        }
        // Regel 2
        if (item->IsLeftSibling() && item->Parent->Balance == -1)
        {
            item->Parent->Balance = 0;
            item = item->Parent;
            continue;
        }
        if (item->IsRightSibling() && item->Parent->Balance == 1)
        {
            item->Parent->Balance = 0;
            item = item->Parent;
            continue;
        }
        // Regel 3
        if (item->IsRightSibling() && item->Parent->Balance == -1)
        {
            if (item->Parent->Left->Balance == 1)
            {
                item->Parent->DoubleRotationLeft();
                item = item->Parent->Parent; // Zeiger sind durch die Rotation etwas verrutscht
            }
            else
            {
                item->Parent->RightRotation();
                item = item->Parent->Parent; // Zeiger sind durch die Rotation etwas verrutscht
            }
            if (item->Balance == 1)
                return true;
            continue;
        }
        if (item->IsLeftSibling() && item->Parent->Balance == 1)
        {
            if (item->Parent->Right->Balance == -1)
            {
                item->Parent->DoubleRotationRight();
                item = item->Parent->Parent; // Zeiger sind durch die Rotation etwas verrutscht
            }
            else
            {
                item->Parent->LeftRotation();
                item = item->Parent->Parent; // Zeiger sind durch die Rotation etwas verrutscht
            }
            if (item->Balance == -1)
                return true;
            continue;
        }
        // Never appears...
        break;
    }
    return true;
};

template <class T>
CAVLNode<T>* CAVLNode<T>::Search(const T* data)
{
    switch (Compare(*Data, *data))
    {
    case -1:
        if (!Right) return NULL;
        return Right->Search(data);
    case  0: return this;
    case  1:
        if (!Left) return NULL;
        return Left->Search(data);
    }
    return NULL;
};

template <class T>
int CAVLNode<T>::Compare(const T& t1, const T& t2)
{
    return t1.Compare(t2);
};

template <class T>
bool CAVLNode<T>::IsRoot() const
{
    return Parent == NULL;
};

template <class T>
bool CAVLNode<T>::IsLeftSibling() const
{
    return !IsRoot() && Parent->Left == this;
};

template <class T>
bool CAVLNode<T>::IsRightSibling() const
{
    return !IsRoot() && Parent->Right == this;
};

template <class T>
bool CAVLNode<T>::HasLeftSibling() const
{
    return !IsRoot() && IsRightSibling() && Parent->Left != NULL;
};

template <class T>
bool CAVLNode<T>::HasRightSibling() const
{
    return !IsRoot() && IsLeftSibling() && Parent->Right != NULL;
};

template <class T>
int CAVLNode<T>::GetDepth() const
{
    int i = 0;
    if (Left != NULL)
        i = Left->GetDepth();
    if (Right != NULL)
        i = max(i, Right->GetDepth());
    return i+1;
};

template <class T>
int CAVLNode<T>::GetLevel() const
{
    const CAVLNode<T>* item = this;
    int level = 0;
    while (item->Parent != NULL)
    {
        item = item->Parent;
        level++;
    }
    return level;
};

template <class T>
int CAVLNode<T>::NodesInTree() const
{
    int Nodes = 1;
    if (Left != NULL)
        Nodes += Left->NodesInTree();
    if (Right != NULL)
        Nodes += Right->NodesInTree();
    return Nodes;
};

template <class T>
CAVLNode<T>* CAVLNode<T>::GetRoot()
{
    CAVLNode<T>* item = this;
    while (item->Parent != NULL) item = item->Parent;
    return item;
};

template <class T>
CAVLNode<T>* CAVLNode<T>::GetLeftSibling()
{
    if (IsRoot() || IsLeftSibling()) return NULL;
    return Parent->Left;
};

template <class T>
CAVLNode<T>* CAVLNode<T>::GetRightSibling()
{
    if (IsRoot() || IsRightSibling()) return NULL;
    return Parent->Right;
};

template <class T>
CAVLNode<T>* CAVLNode<T>::GetFirstNodeInOrder()
{
    CAVLNode<T>* item = this;
    while (item->Left != NULL)
    {
        item = item->Left;
    }
    return item;
};

template <class T>
CAVLNode<T>* CAVLNode<T>::GetLastNodeInOrder()
{
    CAVLNode<T>* item = this;
    while (item->Right != NULL)
    {
        item = item->Right;
    }
    return item;
};

template <class T>
CAVLNode<T>* CAVLNode<T>::GetPrevNodeInOrder()
{
    if (Left != NULL)
    {
        return Left->GetLastNodeInOrder();
    }
    if (IsRightSibling()) return Parent;
    CAVLNode<T>* item = this;
    while (!item->IsRoot())
    {
        if (item->IsLeftSibling())
            item = item->Parent;
        else
            return item->Parent;
    }
    return NULL;
};

template <class T>
CAVLNode<T>* CAVLNode<T>::GetNextNodeInOrder()
{
    if (Right != NULL)
    {
        return Right->GetFirstNodeInOrder();
    }
    if (IsLeftSibling()) return Parent;
    CAVLNode<T>* item = this;
    while (!item->IsRoot())
    {
        if (item->IsRightSibling())
            item = item->Parent;
        else
            return item->Parent;
    }
    return NULL;
};

template <class T>
CAVLNode<T>* CAVLNode<T>::GetInsertPosition(const T* data)
{
    switch (Compare(*Data, *data))
    {
    case -1:
        if (!Right) return this;
        return Right->GetInsertPosition(data);
    case  0:
        return NULL; // Fehler, Objekt schon im Baum
        // error, object already in the tree (only inserted once!)
    case  1:
        if (!Left) return this;
        return Left->GetInsertPosition(data);
    }
    return NULL; // tritt nie auf
    // never happens
};

template <class T>
bool CAVLNode<T>::LeftRotation()
{
    assert(Right != NULL);

    if (Right == NULL) return false;

    CAVLNode<T>* b = Right;
    // Falls nicht die Wurzel: Knoten b wird Kind
    if (!IsRoot())
    {
        if (IsLeftSibling())
            Parent->Left = b;
        else
            Parent->Right = b;
        b->Parent = Parent;
    }
    else
    {
        b->Parent = NULL;
    }

    // Zeiger korrekt umsetzen
    Right = b->Left;
    b->Left = this;

    // Elternzeiger setzen
    Parent = b;
    if (Right != NULL) Right->Parent = this;

    // Balancen setzen
    if (b->Balance == 0)
    {
        Balance = 1;
        b->Balance = -1;
    }
    else
    {
        Balance = 0;
        b->Balance = 0;
    }

    return true;
};

template <class T>
bool CAVLNode<T>::RightRotation()
{
    assert(Left != NULL);

    if (Left == NULL) return false;

    CAVLNode<T>* b = Left;
    // Falls nicht die Wurzel: Knoten b wird Kind
    if (!IsRoot())
    {
        if (IsLeftSibling())
            Parent->Left = b;
        else
            Parent->Right = b;
        b->Parent = Parent;
    }
    else
    {
        b->Parent = NULL;
    }

    // Zeiger korrekt umsetzen
    Left = b->Right;
    b->Right = this;

    // Elternzeiger setzen
    Parent = b;
    if (Left != NULL) Left->Parent = this;

    // Balancen setzen
    if (b->Balance == 0)
    {
        Balance = -1;
        b->Balance = 1;
    }
    else
    {
        Balance = 0;
        b->Balance = 0;
    }

    return true;
};

template <class T>
bool CAVLNode<T>::DoubleRotationLeft()
{
    assert(Left != NULL && Left->Right != NULL);

    if (Left == NULL || Left->Right == NULL) return false;

    CAVLNode<T>* b = Left;
    CAVLNode<T>* c = Left->Right;

    // Falls nicht die Wurzel: Knoten c wird Kind
    if (!IsRoot())
    {
        if (IsLeftSibling())
            Parent->Left = c;
        else
            Parent->Right = c;
    }

    // Zeiger korrekt umsetzen
    b->Right = c->Left;
    Left = c->Right;
    c->Left = b;
    c->Right = this;

    // Elternzeiger setzen
    c->Parent = Parent;
    Parent = c;
    b->Parent = c;
    if (b->Right != NULL) b->Right->Parent = b;
    if (Left != NULL) Left->Parent = this;

    // Balancen setzen
    switch (c->Balance)
    {
    case -1:
        Balance = 1;
        b->Balance = 0;
        break;
    case 0:
        Balance = 0;
        b->Balance = 0;
        break;
    case 1:
        Balance = 0;
        b->Balance = -1;
        break;
    }
    c->Balance = 0;

    return true;
};

template <class T>
bool CAVLNode<T>::DoubleRotationRight()
{
    assert(Right != NULL && Right->Left != NULL);

    if (Right == NULL || Right->Left == NULL) return false;

    CAVLNode<T>* b = Right;
    CAVLNode<T>* c = Right->Left;

    // Falls nicht die Wurzel: Knoten c wird Kind
    if (!IsRoot())
    {
        if (IsLeftSibling())
            Parent->Left = c;
        else
            Parent->Right = c;
    }

    // Zeiger korrekt umsetzen
    Right = c->Left;
    b->Left = c->Right;
    c->Left = this;
    c->Right = b;

    // Elternzeiger setzen
    c->Parent = Parent;
    Parent = c;
    b->Parent = c;
    if (Right != NULL) Right->Parent = this;
    if (b->Left != NULL) b->Left->Parent = b;

    // Balancen setzen
    switch (c->Balance)
    {
    case -1:
        Balance = 0;
        b->Balance = 1;
        break;
    case 0:
        Balance = 0;
        b->Balance = 0;
        break;
    case 1:
        Balance = -1;
        b->Balance = 0;
        break;
    }
    c->Balance = 0;

    return true;
};

#ifdef _MSC_VER
template <class T>
void CAVLNode<T>::Draw(CDC* dc, CRect& rect)
{
    int depth = GetDepth();
    CSize Size = dc->GetTextExtent(*Data);
    dc->TextOut((rect.left+rect.right)/2-Size.cx/2, rect.top, *Data);

    if (Left != NULL)
    {
        CRect rect1 = rect;
        rect1.top += 2*Size.cy;
        rect1.right = (rect.right+rect.left)/2;
        dc->MoveTo((rect.left+rect.right)/2, rect.top+Size.cy);
        dc->LineTo((rect1.left+rect1.right)/2, rect1.top);
        Left->Draw(dc, rect1);
    }
    if (Right != NULL)
    {
        CRect rect2 = rect;
        rect2.top += 2*Size.cy;
        rect2.left = (rect.right+rect.left)/2;
        dc->MoveTo((rect.left+rect.right)/2, rect.top+Size.cy);
        dc->LineTo((rect2.left+rect2.right)/2, rect2.top);
        Right->Draw(dc, rect2);
    }
};
#endif


// AVL-Tree (Template-Version)                                //


// AVL-Baum (Template-Variante)                               //


// Requirements for the class T:
// Objects of class T must be comparable.
// A function
// int T::Compare(const T& t) const
// must be implemented.
// Return values:
//    -1, if *this <  t
//     0, if *this == t
//     1, if *this >  t

// Anforderungen an die Klasse T:
// Objekte der Klasse T m?ssen vergleichbar sein.
// Der Vergleich erfolgt ?ber eine Funktion
// int T::Compare(const T& t) const
// R?ckgabewerte:
//    -1, falls *this <  t
//     0, falls *this == t
//     1, falls *this >  t

template <class T>
class CAVLTree
{
public:
    // construction and destruction
    // Standard-Konstruktor, Konstruktor und Destruktor
    CAVLTree();
    virtual ~CAVLTree();

    // information
    // Informationen
    bool IsEmpty() const;
    int GetDepth() const;
    long NodesInTree() const;

    // access to the root of the tree
    // Zugriff auf die Wurzel
    CAVLNode<T>* GetRoot();

    // insert and delete
    // Insert und Delete
    CAVLNode<T>* Insert(T* data, bool autodelete = true);
    bool Delete(T* data);

    bool DeleteAll();

    // delete current node of an iterator
    // Aktuellen Knoten eines Iterators l?schen
    bool Delete(CAVLTreeIterator<T>& iter, bool movenext = true);

    // search
    // Suchen
    virtual CAVLNode<T>* Search(const T* data);
    virtual CAVLNode<T>* Search(T& data);

#ifdef _MSC_VER
//    void Draw(CDC* dc, CRect& rect);
#endif

private:
    CAVLNode<T>* Tree;

    friend class CAVLTreeIterator<T>;
    /* siehe unten
    friend class CAVLTreeDialog<T>;
    */
};

template <class T>
CAVLTree<T>::CAVLTree() : Tree(NULL)
{
};

template <class T>
CAVLTree<T>::~CAVLTree()
{
    delete Tree;
};

template <class T>
bool CAVLTree<T>::IsEmpty() const
{
    return Tree == NULL;
};

template <class T>
int CAVLTree<T>::GetDepth() const
{
    if (Tree == NULL) return 0;
    return Tree->GetDepth();
};

template <class T>
CAVLNode<T>* CAVLTree<T>::Insert(T* data, bool autodelete)
{
    // if the tree is empty, the root is used to store the entry

    // Wenn der Baum noch leer ist, kann (und mu?) die Wurzel
    // selbst dazu benutzt werden, um den Eintrag aufzunehmen
    if (IsEmpty())
    {
        Tree = new CAVLNode<T>(data, 0, NULL, NULL, NULL);
        return Tree;
    }
    // detect insert position
    // Einf?geposition ermitteln
    CAVLNode<T>* item = Tree->GetInsertPosition(data);
    if (item == NULL)
    {
        if (autodelete)
            delete data;
        return NULL;
    }
    // create a new node
    // Neuen Knoten erzeugen
    CAVLNode<T>* newitem = new CAVLNode<T>(data, 0, item, NULL, NULL);
    // link with parents
    // Mit Eltern verkn?pfen
    if (CAVLNode<T>::Compare(*(item->Data), *data) == -1)
        item->Right = newitem;
    else
        item->Left = newitem;
    // restructuration
    //Restrukturierungs-Ma?nahmen
    newitem->RestructureInsert();
    Tree = Tree->GetRoot();
    // return the new inserted node
    // R?ckgabe des neu eingef?gten Knotens
    return newitem;
};

template <class T>
bool CAVLTree<T>::Delete(T* data)
{
    // if the tree is empty there is nothing to delete
    // Wenn der Baum leer ist, gibt es auch nichts zu l?schen
    if (IsEmpty()) return false;
    CAVLNode<T>* item = Tree->Search(data);
    if (item == NULL) return false; // Element nicht im Baum
    // element not in the tree

    // if we want to delete the root item, we have to do some extra
    // operation the preserve some pointers...
    // Wenn die Wurzel gel?scht werden soll, m?ssen entsprechende
    // Vorkehrungen getroffen werden, um den Zeiger nicht zu
    // verlieren
    if (item == Tree)
    {
        // the root is the only one node in the tree
        // Die Wurzel ist der einzige Knoten im Baum
        if (item->Left == NULL && item->Right == NULL)
        {
            delete Tree;
            Tree = NULL;
            return true;
        }
    }
    // start node for restructuration
    // Startknoten f?r Restrukturierung
    CAVLNode<T>* startitem = NULL;
    // node to delete has no children
    // Zu l?schender Knoten hat keine S?hne
    if (item->Left == NULL && item->Right == NULL)
    {
        if (item->IsLeftSibling())
            item->Parent->Left = NULL;
        else
            item->Parent->Right = NULL;
        startitem = item->Parent;
        delete item;
        item = NULL;
    }
    // node to delete has only right son
    // Zu l?schender Knoten hat nur rechten Sohn
    if (item != NULL && item->Left == NULL && item->Right != NULL)
    {
        delete item->Data;
        item->Data = item->Right->Data;
        item->Right->Data = NULL;
        delete item->Right;
        item->Right = NULL;
        startitem = item;
    }
    // node to delete has only left son
    // Zu l?schender Knoten hat nur linken Sohn
    if (item != NULL && item->Left != NULL && item->Right == NULL)
    {
        delete item->Data;
        item->Data = item->Left->Data;
        item->Left->Data = NULL;
        delete item->Left;
        item->Left = NULL;
        startitem = item;
    }
    // node to delete has both sons
    // Zu l?schender Knoten hat beide S?hne
    if (item != NULL && item->Left != NULL && item->Right != NULL)
    {
        CAVLNode<T>* y = item->Left->GetLastNodeInOrder();
        CAVLNode<T>* z = y->Left;
        delete item->Data;
        item->Data = y->Data;
        y->Data = NULL;
        /*
        if (y->IsLeftSibling())
            y->Parent->Left = z;
        else
            y->Parent->Right = z;
        */
        if (z != NULL)
        {
            y->Data = z->Data;
            z->Data = NULL;
            y->Left = NULL;
            delete z;
            startitem = y;
        }
        else
        {
            if (y->IsLeftSibling())
                y->Parent->Left = NULL;
            else
                y->Parent->Right = NULL;
            startitem = y->Parent;
            delete y;
        }
    }
    startitem->RestructureDelete();
    Tree = Tree->GetRoot();
    return true;
};

template <class T>
CAVLNode<T>* CAVLTree<T>::Search(const T* data)
{
    CAVLNode<T>* root = GetRoot();
    if (root==NULL)
        return NULL;
    return root->Search(data);
};

template <class T>
CAVLNode<T>* CAVLTree<T>::Search(T& data)
{
    CAVLNode<T>* root = GetRoot();
    if (root==NULL)
        return NULL;
    return root->Search(&data);
};

template <class T>
CAVLNode<T>* CAVLTree<T>::GetRoot()
{
    return Tree;
};

template <class T>
long CAVLTree<T>::NodesInTree() const
{
    if (Tree)
        return Tree->NodesInTree();
    return 0;
};

template <class T>
bool CAVLNode<T>::CheckBalances(const char * buffer, unsigned int buflen) const
{
    int d1 = 0;
    int d2 = 0;
    if (Left)
    {
        d1 = Left->GetDepth();
        if (!Left->CheckBalances(buffer, buflen)) return false;
    }
    if (Right)
    {
        d2 = Right->GetDepth();
        if (!Right->CheckBalances(buffer, buflen)) return false;
    }
    if (abs(d1-d2)>1)
    {
        if (buffer)
            sprintf(buffer, "Depths are incorrect for AVL-Tree (Left %d, Right %d), level: %d", d1, d2, GetLevel());
        return false;
    }
    if (Balance == -1 && d1 >  d2) return true;
    if (Balance ==  0 && d1 == d2) return true;
    if (Balance ==  1 && d1 <  d2) return true;
    if (buffer)
        sprintf(buffer, "Balance does not match depths: (Left %d, Right %d, Balance %d), level: %d", d1, d2, Balance, GetLevel());
    return false;
};

template <class T>
bool CAVLTree<T>::DeleteAll()
{
    delete Tree;
    Tree = NULL;
    return true;
};

template <class T>
bool CAVLTree<T>::Delete(CAVLTreeIterator<T>& iter, bool movenext)
{
    if (!iter)
        return false;
    CAVLNode<T>* item = iter.Current;
    CAVLNode<T>* item1 = NULL;
    if (movenext)
    {
        item1 = item->GetPrevNodeInOrder();
        iter.MoveNext();
    }
    else
    {
        item1 = item->GetNextNodeInOrder();
        iter.MovePrev();
    }
    T* t = (iter ? iter.Current->Data : NULL);
    bool ret = Delete(item->Data);
    if (t)
    {
        iter.Current = Search(t);
    }
    iter.Tree = NULL;
    if (iter.Current != NULL)
        iter.Tree = iter.Current->GetRoot();
    if (iter.Current == NULL && item1 != NULL)
        iter.Tree = item1->GetRoot();
    return ret;
};

#ifdef _MSC_VER
template <class T>
void CAVLTree<T>::Draw(CDC* dc, CRect& rect)
{
    if (IsEmpty()) return;
    Tree->Draw(dc, rect);
};
#endif


// Iterator durch einen AVL-Baum                              //

template <class T>
class CAVLTreeIterator
{
public:
    // construction and destruction
    // Konstruktor und Destruktor
    CAVLTreeIterator(CAVLNode<T>* tree);
    CAVLTreeIterator(CAVLTree<T>& tree);
    virtual ~CAVLTreeIterator();

    // validity
    // G?ltigkeitspr?fung
    operator bool();

    // navigation
    // Navigation
    void operator ++();
    void operator --();
    void operator ++(int);
    void operator --(int);
    void Reset();
    void MoveFirst();
    void MoveLast();
    void MoveNext();
    void MovePrev();

    // access to current node
    // Zugriff auf aktuellen Knoten
    T* GetData();
    CAVLNode<T>* Current;
private:
    CAVLNode<T>* Tree;
    CAVLTreeIterator(const CAVLTreeIterator<T>& /*treeiterator*/) {};
    CAVLTreeIterator& operator= (const CAVLTreeIterator<T>& /*treeiterator*/) {return *this;};

    friend class CAVLTree<T>;
};

template <class T>
CAVLTreeIterator<T>::CAVLTreeIterator(CAVLNode<T>* tree)
    : Tree(tree)
{
    if (Tree != NULL)
        Current = Tree->GetFirstNodeInOrder();
    else
        Current = NULL;
};

template <class T>
CAVLTreeIterator<T>::CAVLTreeIterator(CAVLTree<T>& tree)
    : Tree(tree.Tree)
{
    if (Tree != NULL)
        Current = Tree->GetFirstNodeInOrder();
    else
        Current = NULL;
};

template <class T>
CAVLTreeIterator<T>::~CAVLTreeIterator()
{
};

template <class T>
void CAVLTreeIterator<T>::Reset()
{
    if (Tree)
        Current = Tree->GetFirstNodeInOrder();
    else
        Current = NULL;
};

template <class T>
void CAVLTreeIterator<T>::MoveFirst()
{
    if (Tree)
        Current = Tree->GetFirstNodeInOrder();
    else
        Current = NULL;
};

template <class T>
void CAVLTreeIterator<T>::MoveLast()
{
    if (Tree)
        Current = Tree->GetLastNodeInOrder();
    else
        Current = NULL;
};

template <class T>
CAVLTreeIterator<T>::operator bool()
{
    return Current != NULL;
};

template <class T>
void CAVLTreeIterator<T>::operator ++()
{
    if (Current == NULL) return;
    Current = Current->GetNextNodeInOrder();
};

template <class T>
void CAVLTreeIterator<T>::operator --()
{
    if (Current == NULL) return;
    Current = Current->GetPrevNodeInOrder();
};

template <class T>
void CAVLTreeIterator<T>::operator ++(int)
{
    if (Current == NULL) return;
    Current = Current->GetNextNodeInOrder();
};

template <class T>
void CAVLTreeIterator<T>::operator --(int)
{
    if (Current == NULL) return;
    Current = Current->GetPrevNodeInOrder();
};

template <class T>
void CAVLTreeIterator<T>::MoveNext()
{
    if (Current == NULL) return;
    Current = Current->GetNextNodeInOrder();
};

template <class T>
void CAVLTreeIterator<T>::MovePrev()
{
    if (Current == NULL) return;
    Current = Current->GetPrevNodeInOrder();
};

template <class T>
T* CAVLTreeIterator<T>::GetData()
{
    if (Current)
        return Current->Data;
    else
        return NULL;
};

/* Code kann bei entsprechender Resourcen-Definition wieder eingesetzt
   werden, siehe Projekt ?????
template <class T>
class CAVLTreeDialog : public CDialog
{
public:
    CAVLTreeDialog(CAVLTree<T>& tree, CWnd* pParent = NULL);   // standard constructor

// Dialog Data
    enum { IDD = IDD_VEKTORTREEDIALOG1 };
    CTreeCtrl   m_Tree;


// Overrides
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
    CAVLTree<T>& Tree;
    CImageList  m_ctlImage;

    virtual BOOL OnInitDialog();
    virtual void Insert(CAVLNode<T>* item, HTREEITEM pos);
};

template <class T>
CAVLTreeDialog<T>::CAVLTreeDialog(CAVLTree<T>& tree, CWnd* pParent)
    : CDialog(CTreeDialog::IDD, pParent), Tree(tree)
{
};

template <class T>
void CAVLTreeDialog<T>::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_TREE1, m_Tree);
};

template <class T>
BOOL CAVLTreeDialog<T>::OnInitDialog()
{
    bool ret = CDialog::OnInitDialog();
    m_ctlImage.Create(IDB_BITMAP1,16,0,RGB(255,0,255));
    m_ctlImage.SetBkColor(GetSysColor(COLOR_WINDOW));
    m_Tree.SetImageList(&m_ctlImage, TVSIL_NORMAL);

    Insert(Tree.Tree, TVI_ROOT);
    return ret;
};

template <class T>
void CAVLTreeDialog<T>::Insert(CAVLNode<T>* tree, HTREEITEM pos)
{
    if (tree == NULL)
    {
        m_Tree.InsertItem(_T("NULL"), 3, 3, pos);
        return;
    }
    int image = 1 + tree->Balance;
    HTREEITEM newpos = m_Tree.InsertItem(*(tree->Data), image, image, pos);
    Insert(tree->Left, newpos);
    Insert(tree->Right, newpos);
};
*/
#endif // __AVL_TREE_H__


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值