Avatar billede martinskou Nybegynder
19. marts 2002 - 21:52 Der er 9 kommentarer og
1 løsning

Template og pointere

Jeg har en

template <class Comparable>
class SplayTree

men når jeg laver en instance fx:

SplayTree<int *> t;
t.insert(new int(5));
...

virker template klassen ikke efter hensigten fordi den benytter > og < på pointeren i stedet for indholdet af pointeren.

Kan jeg tage højde for dette uden at skulle rette på indholdet i min template??





Avatar billede alvion Nybegynder
20. marts 2002 - 06:27 #1
Har du prøvet:

SplayTree<(int *)> t;
Avatar billede martinskou Nybegynder
20. marts 2002 - 07:28 #2
Compileren vil ikke have det.
Avatar billede alvion Nybegynder
20. marts 2002 - 08:37 #3
Må jeg se koden for din template klasse? Der må være en fejl der, for man burde sagtens kunne lave en

SplayTree<int *> t;
Avatar billede martinskou Nybegynder
20. marts 2002 - 10:23 #4
Koden som volder problemer ligger her:

http://www.prerelease.dk/pqueue.cpp

Den kompilere på Microsoft Visual C++ 7 , men sikkert også på alt muligt andet.
Avatar billede alvion Nybegynder
20. marts 2002 - 16:39 #5
Hmm... Det er et stykke tid siden jeg har rodet med templates...

Kan du give et linienummer på den linie, hvor compileren giver fejl?
Avatar billede greybeard Nybegynder
21. marts 2002 - 23:11 #6
Hvis du vil bruge pointere i din template, kan du f.eks sende en compareTo() metode med som parameter, og bruge den i stedet for > <.
For at få > < til at virke efter hensigten, ville det være nødvendigt at overloade dem, og det kan man ikke med pointere.

Hvis det kun er primitiver du vil bruge, kan du lave et typecheck, og hvis parameteret er en pointer, kan du dereferentiere den, før du sammenligner.

Du kan også bare bruge et referenceparameter.
Avatar billede greybeard Nybegynder
22. marts 2002 - 00:35 #7
// pqueue.cpp : Defines the entry point for the console application.
//

#include <iostream.h>      // For NULL
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <limits.h>


class tri {

public:

    char name[20];
    float error;

    tri() {
    }

   
    tri(char *n, float e) {
        strcpy(name,n);
        error=e;
    }

    bool operator==( const tri & t )
    {
        return error == t.error;
    }

    bool operator!=( const tri & t )
    {
        return error != t.error;
    }

    bool operator<( const tri & t )
    {
        return error < t.error;
    }

    bool operator<=( const tri & t )
    {
        return error <= t.error ;
    }

    bool operator>( const tri & t )
    {
        return error > t.error;
    }

    bool operator>=( const tri & t )
    {
        return error >= t.error;
    }

};




template <class Comparable>
class SplayTree;

template <class Comparable>
class BinaryNode
{
    Comparable  element;
    BinaryNode *left;
    BinaryNode *right;

    BinaryNode( ) : left( NULL ), right( NULL ) { }
    BinaryNode(  Comparable & theElement, BinaryNode *lt, BinaryNode *rt )
      : element( theElement ), left( lt ), right( rt ) { }

    friend class SplayTree<Comparable>;
};


template <class Comparable>
class SplayTree
{
  public:
    explicit SplayTree( const Comparable & notFound );
    SplayTree( const SplayTree & rhs );
    ~SplayTree( );

    const Comparable & findMin( );
    const Comparable & findMax( );
    const Comparable & find(  Comparable & x );
    bool isEmpty( ) const;
    void printTree( ) const;

    void makeEmpty( );
    void insert(  Comparable & x );
    void remove(  Comparable & x );

    const SplayTree & operator=( const SplayTree & rhs );


    BinaryNode<Comparable> *root;
    void splay(  Comparable & x, BinaryNode<Comparable> * & t ) const;

    private:

    BinaryNode<Comparable> *nullNode;
    const Comparable ITEM_NOT_FOUND;

    const Comparable & elementAt( BinaryNode<Comparable> *t ) const;

    void reclaimMemory( BinaryNode<Comparable> * t ) const;
    void printTree( BinaryNode<Comparable> *t ) const;
    BinaryNode<Comparable> * clone( BinaryNode<Comparable> *t ) const;

        // Tree manipulations
    void rotateWithLeftChild( BinaryNode<Comparable> * & k2 ) const;
    void rotateWithRightChild( BinaryNode<Comparable> * & k1 ) const;
};


/**
* Construct the tree.
*/
template <class Comparable> SplayTree<Comparable>::SplayTree( const Comparable & notFound ) : ITEM_NOT_FOUND( notFound )
{
    nullNode = new BinaryNode<Comparable>;
    nullNode->left = nullNode->right = nullNode;
    nullNode->element = notFound;
    root = nullNode;
}

/**
* Copy constructor.
*/
template <class Comparable> SplayTree<Comparable>::SplayTree( const SplayTree<Comparable> & rhs ) : ITEM_NOT_FOUND( rhs.ITEM_NOT_FOUND )
{
    nullNode = new BinaryNode<Comparable>;
    nullNode->left = nullNode->right = nullNode;
    nullNode->element = ITEM_NOT_FOUND;
    root = nullNode;
    *this = rhs;
}

/**
* Destructor.
*/
template <class Comparable> SplayTree<Comparable>::~SplayTree( )
{
    makeEmpty( );
    delete nullNode;
}

/**
* Insert x into the tree.
*/
template <class Comparable> void SplayTree<Comparable>::insert(  Comparable & x )
{
    static BinaryNode<Comparable> *newNode = NULL;

    if( newNode == NULL )
        newNode = new BinaryNode<Comparable>;
    newNode->element = x;

    if( root == nullNode )
    {
        newNode->left = newNode->right = nullNode;
        root = newNode;
    }
    else
    {
        splay( x, root );
        if( x < root->element )
        {
            newNode->left = root->left;
            newNode->right = root;
            root->left = nullNode;
            root = newNode;
        }
        else
        if( root->element < x )
        {
            newNode->right = root->right;
            newNode->left = root;
            root->right = nullNode;
            root = newNode;
        }
        else
            return;
    }
    newNode = NULL;  // So next insert will call new
}

/**
* Remove x from the tree.
*/
template <class Comparable> void SplayTree<Comparable>::remove(  Comparable & x )
{
    BinaryNode<Comparable> *newTree;

        // If x is found, it will be at the root
    splay( x, root );
    if( root->element != x )
        return;  // Item not found; do nothing

    if( root->left == nullNode )
        newTree = root->right;
    else
    {
        // Find the maximum in the left subtree
        // Splay it to the root; and then attach right child
        newTree = root->left;
        splay( x, newTree );
        newTree->right = root->right;
    }
    delete root;
    root = newTree;
}

/**
* Find the smallest item in the tree.
* Not the most efficient implementation (uses two passes), but has correct
*    amortized behavior.
* A good alternative is to first call Find with parameter
*    smaller than any item in the tree, then call findMin.
* Return the smallest item or ITEM_NOT_FOUND if empty.
*/
template <class Comparable> const Comparable & SplayTree<Comparable>::findMin( )
{
    if( isEmpty( ) )
        return ITEM_NOT_FOUND;

    BinaryNode<Comparable> *ptr = root;

    while( ptr->left != nullNode )
        ptr = ptr->left;

    splay( ptr->element, root );
    return ptr->element;
}

/**
* Find the largest item in the tree.
* Not the most efficient implementation (uses two passes), but has correct
*    amortized behavior.
* A good alternative is to first call Find with parameter
*    larger than any item in the tree, then call findMax.
* Return the largest item or ITEM_NOT_FOUND if empty.
*/
template <class Comparable> const Comparable & SplayTree<Comparable>::findMax( )
{
    if( isEmpty( ) )
        return ITEM_NOT_FOUND;

    BinaryNode<Comparable> *ptr = root;

    while( ptr->right != nullNode )
        ptr = ptr->right;

    splay( ptr->element, root );
    return ptr->element;
}

/**
* Find item x in the tree.
* Return the matching item or ITEM_NOT_FOUND if not found.
*/
template <class Comparable> const Comparable & SplayTree<Comparable>::find(  Comparable & x )
{
    if( isEmpty( ) )
        return ITEM_NOT_FOUND;
    splay( x, root );
    if( root->element != x )
        return ITEM_NOT_FOUND;

    return root->element;
}

/**
* Make the tree logically empty.
*/
template <class Comparable> void SplayTree<Comparable>::makeEmpty( )
{
/******************************
* Comment this out, because it is prone to excessive
* recursion on degenerate trees. Use alternate algorithm.

    reclaimMemory( root );
    root = nullNode;
*******************************/
    findMax( );        // Splay max item to root
    while( !isEmpty( ) )
        remove( root->element );
}

/**
* Test if the tree is logically empty.
* @return true if empty, false otherwise.
*/
template <class Comparable> bool SplayTree<Comparable>::isEmpty( ) const
{
    return root == nullNode;
}

/**
* Print the tree contents in sorted order.
*/
template <class Comparable> void SplayTree<Comparable>::printTree( ) const
{
    if( isEmpty( ) )
        cout << "Empty tree" << endl;
    else
        printTree( root );
}

/**
* Deep copy.
*/
template <class Comparable> const SplayTree<Comparable> &SplayTree<Comparable>::operator=( const SplayTree<Comparable> & rhs )
{
    if( this != &rhs )
    {
        makeEmpty( );
        root = clone( rhs.root );
    }

    return *this;
}

/**
* Internal method to perform a top-down splay.
* The last accessed node becomes the new root.
* This method may be overridden to use a different
* splaying algorithm, however, the splay tree code
* depends on the accessed item going to the root.
* x is the target item to splay around.
* t is the root of the subtree to splay.
*/
template <class Comparable> void SplayTree<Comparable>::splay(  Comparable & x, BinaryNode<Comparable> * & t ) const
{
    BinaryNode<Comparable> *leftTreeMax, *rightTreeMin;
    static BinaryNode<Comparable> header;

    header.left = header.right = nullNode;
    leftTreeMax = rightTreeMin = &header;

    nullNode->element = x;  // Guarantee a match

    for( ; ; )
        if( x < t->element )
        {
            if( x < t->left->element )
                rotateWithLeftChild( t );
            if( t->left == nullNode )
                break;
            // Link Right
            rightTreeMin->left = t;
            rightTreeMin = t;
            t = t->left;
        }
        else if( t->element < x )
        {
            if( t->right->element < x )
                rotateWithRightChild( t );
            if( t->right == nullNode )
                break;
            // Link Left
            leftTreeMax->right = t;
            leftTreeMax = t;
            t = t->right;
        }
        else
            break;

    leftTreeMax->right = t->left;
    rightTreeMin->left = t->right;
    t->left = header.right;
    t->right = header.left;
}

/**
* Rotate binary tree node with left child.
*/
template <class Comparable> void SplayTree<Comparable>::rotateWithLeftChild( BinaryNode<Comparable> * & k2 ) const
{
    BinaryNode<Comparable> *k1 = k2->left;
    k2->left = k1->right;
    k1->right = k2;
    k2 = k1;
}

/**
* Rotate binary tree node with right child.
*/
template <class Comparable> void SplayTree<Comparable>::rotateWithRightChild( BinaryNode<Comparable> * & k1 ) const
{
    BinaryNode<Comparable> *k2 = k1->right;
    k1->right = k2->left;
    k2->left = k1;
    k1 = k2;
}

/**
* Internal method to print a subtree t in sorted order.
* WARNING: This is prone to running out of stack space.
*/
template <class Comparable> void SplayTree<Comparable>::printTree( BinaryNode<Comparable> *t ) const
{
    if( t != t->left )
    {
        printTree( t->left );
        cout << t->element.name << ": " << t->element.error << endl;
        printTree( t->right );
    }
}

/**
* Internal method to reclaim internal nodes in subtree t.
* WARNING: This is prone to running out of stack space.
*/
template <class Comparable> void SplayTree<Comparable>::reclaimMemory( BinaryNode<Comparable> * t ) const
{
    if( t != t->left )
    {
        reclaimMemory( t->left );
        reclaimMemory( t->right );
        delete t;
    }
}

/**
* Internal method to clone subtree.
* WARNING: This is prone to running out of stack space.
*/
template <class Comparable> BinaryNode<Comparable> * SplayTree<Comparable>::clone( BinaryNode<Comparable> * t ) const
{
    if( t == t->left )  // Cannot test against nullNode!!!
        return nullNode;
    else
        return new BinaryNode<Comparable>( t->element, clone( t->left ), clone( t->right ) );
}



int main()
{

    tri ITEM_NOT_FOUND=*(new tri("not found",-9999));

    SplayTree<tri> t( ITEM_NOT_FOUND );


    tri mt=*(new tri("syv",7));

    t.insert(*(new tri("fem",5)));
    t.insert(*(new tri("et",1)));
    t.insert(mt);
    t.insert(*(new tri("ni",9)));
    t.insert(*(new tri("tre",3)));

// VIRKER IKKE DA KLASSES SplayTree benytter < og > på pointer, og ikke på INDHOLD af pointer...

    cout << t.findMin().name << endl;
    cout << t.findMax().name << endl << endl;

    t.printTree();

    return 0;
}


Jeg kan desværre ikke få det til at virke med const parametre.
Det er muligvis noget med om det er referencen eller indholdet, der er const.

Jeg kan ikke rigtig se nogen løsning, hvor du helt undgår at rette i templaten.

Iøvrigt noget dejligt overskueligt kode. Der kunne jeg lære noget :-))
Avatar billede greybeard Nybegynder
22. marts 2002 - 00:40 #8
Jeg tror nu nok, at jeg ville vælge at sende en compareTo metode med som parameter til SplayTree konstruktoren.

Så kan du lave en compareTo metode, der passer til din type, og derved få en større alsidighed. Da det nu ikke er muligt at overloade operatorer på alle typer.
Avatar billede martinskou Nybegynder
22. marts 2002 - 08:59 #9
Tak for hjælpen!

Jeg skylder vist lige at nævne at koden til klassen SplayTreee er skrevet af Mark Allen Weiss, og kan downloades fra han website http://www.cs.fiu.edu/~weiss/
Avatar billede greybeard Nybegynder
22. marts 2002 - 15:25 #10
Selv tak
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester