Вы находитесь на странице: 1из 9

// Oliverio Alonso Piñera - Estructura de Datos

// Contenido:
// Clase abstracta para arboles n-arios nTree<T, TNode>.
//
// Clase de arboles n-arios basada en nodos binarios nTreeNode<T>
//
//-----------------------------------------------------------------------
------

#ifndef __EDI_N_TREE_H
#define __EDI_N_TREE_H

#include <iostream>
#include <stdexcept>
#include <stdarg.h>

#include <_iterator.h>
#include <_stack.h>
#include <_binaryNode.h>

using namespace std;

//----------------------------------------------------------------
//
// Definicion de la clase nTree
//
//----------------------------------------------------------------

template <class T, class TNode>


class nTree {
public:
virtual T label (TNode node) const = 0;
/* Necesita: un nodo del rbol receptor.
Produce: el valor de la etiqueta del nodo.
Error: si el nodo es el nodo nulo. */
virtual TNode root () const = 0;
/* Produce: el nodo raz del rbol receptor. */
virtual TNode parent (TNode node) const = 0;
/* Necesita: un nodo del rbol receptor.
Produce: el nodo padre del nodo dado.
Excepcin: si el nodo es la raz del rbol retorna el nodo nulo
Error: si el nodo es el nodo nulo. */
virtual TNode leftMostChild (TNode node) const = 0;
/* Necesita: un nodo del rbol receptor.
Produce: el primer hijo del nodo dado.
Excepcin: si el nodo es una hoja retorna el nodo nulo.
Error: si el nodo es el nodo nulo. */
virtual TNode rightSibling (TNode node) const = 0;
/* Necesita: un nodo del rbol receptor.
Produce: el primer nodo hermano del nodo
dado situado a la derecha.
Excepcin: si el nodo no tiene hermano a
la derecha retorna el nodo nulo.
Error: si el nodo es el nodo nulo. */
virtual nTree & subTree (TNode node) const = 0;
/* Necesita: un nodo del rbol receptor.
Produce: el subrbol n-ario que tiene como
raz el nodo dado.
Error: si el nodo es el nodo nulo. */
virtual bool isLeaf (TNode node) const = 0;
/* Necesita: un nodo del rbol receptor.
Produce: cierto si el nodo es una hoja
Error: si el nodo es el nodo nulo. */
};

//----------------------------------------------------------------
//
// Definicion de la clase nTreeNode
//
//----------------------------------------------------------------

template <class T> class nTreeNode; //forward declaration

template <class T>


istream & operator >> (istream & in, nTreeNode<T> & t);

template <class T>


istream & operator >> (istream & in, nTreeNode<T>* & t);

//
// Clase nTreeNode
// Clase de los arboles n-arios basada en nodos binarios
//

template <class T>


class nTreeNode : public nTree<T, binaryNode<T> *> {
friend istream & operator >> <>(istream & in, nTreeNode<T> & t);
friend istream & operator >> <>(istream & in, nTreeNode<T> * & t);

public:
// constructores
nTreeNode (const T & value);
nTreeNode (binaryNode<T> * root = (binaryNode<T> *) 0);
nTreeNode (const T & value, unsigned int grade, nTreeNode<T> * first
...);
/* Necesita: la etiqueta de la raz del rbol, el grado de
la raz del rbol (>0) y las direcciones de los
subrboles hijos de la raz.
Produce: un nuevo rbol n-ario con la raz etiquetada
con el valor value y que tiene como hijos las
races de los subrboles dados. */

nTreeNode (const nTreeNode<T> & rhs);

// destructor
virtual ~nTreeNode ();
// operaciones
virtual T label (binaryNode<T> * node) const;
//0(1)
virtual binaryNode<T> * root () const;
//0(1)
virtual binaryNode<T> * parent (binaryNode<T> * node) const;
//0(n)
virtual binaryNode<T> * leftMostChild(binaryNode<T> * node) const;
//0(1)
virtual binaryNode<T> * rightSibling (binaryNode<T> * node) const;
//0(1)
virtual nTreeNode<T> & subTree (binaryNode<T> * node) const;
//0(1)
virtual bool isLeaf (binaryNode<T> * node) const;
//0(1)

nTreeNode<T> & operator= (const nTreeNode<T> & rhs);

protected:
// area de datos
binaryNode<T> * theRoot;

// operaciones internas
binaryNode<T> * search (binaryNode<T> * initial, binaryNode<T> * node)
const;
/* Necesita: las direcciones de dos nodos binarios, node e
initial. El nodo initial es el nodo inicial a partir del
cual se busca el nodo node.
Produce: el nodo padre del nodo node.
Excepcin: si no se encuentra node retorna el nodo nulo.
Coste t.: O(n) */

nTreeNode (const T & value, VStack<nTreeNode<T> *> childs);


/* Necesita: la etiqueta de la raz del rbol, una pila con las
direcciones de los subrboles hijos de la raz de
izquierda a derecha.
Produce: un nuevo rbol n-ario con la raz etiquetada
con el valor value y que tiene como hijos las
races de los subrboles dados. */

//operaciones privadas para el control de errores


void assertNullNode(binaryNode<T> * node) const;
};

//----------------------------------------------------------------
//
// Implementacion de la clase nTreeNode
//
//----------------------------------------------------------------

template <class T>


nTreeNode<T>::nTreeNode (const T & value)
{
// construye un arbol que solo tiene raiz
theRoot = new binaryNode<T>(value, 0, 0);
}

template <class T>


nTreeNode<T>::nTreeNode (binaryNode<T> * root)
{
theRoot = root;
}

template <class T>


nTreeNode<T>::nTreeNode (const T & value, unsigned int grade, nTreeNode<T>
* first ...)
{
va_list lArgs;
VStack<nTreeNode<T> *> childs;

// tratar la lista de argumentos variable

va_start(lArgs, first); // inicio de argumentos desconocidos

childs.push(first);
for (unsigned int i = 1; i != grade; i++) {
nTreeNode<T> * t = va_arg(lArgs, nTreeNode<T> *);
childs.push(t);
}

va_end(lArgs); // finaliza el tratamiento

nTreeNode<T> * tree = new nTreeNode<T>(value, childs);

theRoot = tree->theRoot;
}

template <class T>


nTreeNode<T>::nTreeNode (const T & value, VStack<nTreeNode<T> *> childs)
{
binaryNode<T> * right = 0;

while (! childs.empty()) {
binaryNode<T> * root = childs.top()->theRoot;
childs.pop();
binaryNode<T> * left = root->left();

if (left)
left = left->clone();

right = new binaryNode<T>(root->label(), left, right);


}

theRoot = new binaryNode<T>(value, right, 0);


}

template <class T>


nTreeNode<T>::nTreeNode (const nTreeNode<T> & rhs)
{
// constructor de copia

if (rhs.theRoot)
theRoot = rhs.theRoot->clone();
else
theRoot = 0;
}

template <class T>


nTreeNode<T> & nTreeNode<T>::operator= (const nTreeNode<T> & rhs)
{
if (this == &rhs) return *this;

if (theRoot) {
theRoot->free();
delete theRoot;
}
if (rhs.theRoot)
theRoot = rhs.theRoot->clone();
else
theRoot = 0;
return *this;
}

template <class T>


nTreeNode<T>::~nTreeNode ()
{
// destructor

if (theRoot) {
theRoot->free();
delete theRoot;
theRoot = 0;
}
}

template <class T>


T nTreeNode<T>::label (binaryNode<T> * node) const
{
// etiqueta del nodo
assertNullNode(node);

return node->label();
}

template <class T>


binaryNode<T> * nTreeNode<T>::root () const
{
// raiz del arbol

return theRoot;
}

template <class T>


binaryNode<T> * nTreeNode<T>::parent (binaryNode<T> * node) const
{
// padre de un nodo

assertNullNode(node);

if (theRoot == node)
return 0;

return search(theRoot, node);


}

template <class T>


binaryNode<T> * nTreeNode<T>::leftMostChild (binaryNode<T> * node) const
{
// retorna el primer hijo de un nodo

assertNullNode(node);

return node->left();
}

template<class T>
binaryNode<T> * nTreeNode<T>::rightSibling (binaryNode<T> * node) const
{
// retorna el hermano mas cercano de un nodo

assertNullNode(node);

return node->right();
}

template <class T>


nTreeNode<T> & nTreeNode<T>::subTree (binaryNode<T> * node) const
{
// retorna el subarbol de raiz el nodo dado

assertNullNode(node);

nTreeNode<T> * tree = new nTreeNode<T>(node);

return *tree;
}

template <class T>


bool nTreeNode<T>::isLeaf (binaryNode<T> * node) const
{
// retorna cierto si el nodo es una hoja

assertNullNode(node);

return node->left() == 0;
}

template <class T>


binaryNode<T> * nTreeNode<T>::search (binaryNode<T> * initial, binaryNode<T>
* node) const
{
// busca el nodo padre del nodo node
if (isLeaf(initial))
return 0;

binaryNode<T> * child = leftMostChild(initial);

while (child) {
binaryNode<T> * parent = search(child, node);

if (parent)
return parent;

if (child == node)
return initial;

child = rightSibling(child);
}
return 0;
}

template <class T>


void nTreeNode<T>::assertNullNode(binaryNode<T> * node) const
{
if (node==0)
throw runtime_error("Operacin sobre un nodo nulo en nTreeNode") ;
}

//-------------------------------------------------------------------
// Operadores de Entrada/Salida
//-------------------------------------------------------------------

template <class T>


istream & operator >> (istream & in, nTreeNode<T> & t)
{
in >> t.theRoot;

return in;
}

template <class T>


istream & operator >> (istream & in, nTreeNode<T> * & t)
{
nTreeNode<T> * p = new nTreeNode<T>((T) 0);

in >> p->theRoot;
t = p;

return in;
}

//OJO: La salida no da el arbol en predorden inorden sino la


//representacion interna del mismo
//Esta salida permite observar el contenido del arbol pero
//habria que hacerlo correctamente.
template <class T>
ostream & operator << (ostream & out, const nTreeNode<T> & t)
{
binaryNode<T> * root = t.root();

out << root;

return out;
}

template <class T>


ostream & operator << (ostream & out, nTreeNode<T> * t)
{
if (t)
out << *t;

return out;
}

//Recorrido por niveles


template <class T>
void levelorderNTree(nTreeNode<T> & t)
{
VQueue < binaryNode<T> * > q;
q.enqueue(t.root());
cout << "( " ;
while (!q.empty())
{
binaryNode<T> * n=q.front();
q.dequeue();
cout << t.label(n) << ' ';// << flush;
binaryNode<T>* child = t.leftMostChild (n);
while (child)
{
q.enqueue (child) ;
child = t.rightSibling(child);
}
}
cout << " )" << endl;
}

template <class T>


void levelorderNTree2 (const nTreeNode <T> & t )
{
if(t.isLeaf(t.root()))
cout << "( " << t.label(t.root()) << " )";
else {
VQueue < nTreeNode <T> > q;
q.enqueue(t);
cout << "( " ;
nTreeNode<T> a;
while (!q.empty())
{
a = q.front();
q.dequeue();
cout << a.label (a.root()) << ' ' << flush;
binaryNode<T>* child = t.leftMostChild (a.root());
while (child)
{
q.enqueue (t.subTree(child)) ;
// cout << q.empty() << endl;
child = t.rightSibling(child);
}
}
cout << " )" << endl;
}
}

#endif

Вам также может понравиться