dinamismo y contenedores facultad de ciencias exactas y naturales universidad de buenos aires (c++...
TRANSCRIPT
Dinamismo y Contenedores
Facultad de Ciencias Exactas y NaturalesUniversidad de Buenos Aires
(C++ Avanzado)Depto. deComputación
Algoritmos y Estructuras de Datos II1er Cuatrimetre de 2005
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Repaso…
Punteros:
Declaración: int *p; ← p es puntero a un int
Operadores: Supongamos p un puntero, y s una variable.
*p : devuelve el contenido de lo que apunta p (op. de des-referenciación)
&s : devuelve la dirección de la variable s (op. de referenciación)
Ejemplo: Cuánto vale…
x = *p;x = 200;p = &x;*p = 400;*p = &x;
( Tipo de dato al que apunta)
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Llamadas a función:
x Valor: Se copian los objetos.
Ej: float suma(float a,float b)
x Referencia:
• Argumentos de referencia: se pueden modificar los pasados como parámetro.
Ej: float suma(float &a,float &b){a = a + b;return a;
} ¿cuánto vale x luego de la llamada suma( x=3 , y=4)?
• Punteros:
Ej: float suma(float *a,float *b){return = *a + *b;
}
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Const:• Seguridad en el manejo de datos.
Ej: float suma (const float *a, const float *b)
• 4 maneras de pasarle un puntero a una función
• ptr no constante a dato no constante. (- restrictivo)• ptr no constante a dato constante.• ptr constante a dato no constante.• ptr constante a dato constante. (+ restrictivo)
“a es un puntero a un float constante”
Los objetos grandes, como las estructuras de datos, se deben pasar con punteros a datos constantes (o referencias a datos constantes), con el fin de lograr :desempeño de la llamada por referencia, y la seguridad de la llamada por valor.
Los objetos grandes, como las estructuras de datos, se deben pasar con punteros
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Templates:
• Reutilización de código.
• Evita tener que programar funciones sobrecargadas.
Parámetro formal
Templates de funciones Ej: template<class T>
void printArray(const T *arreglo, const int cant) {
for (int i=0; i<cant; i++)cout << arreglo[i] << " ";
cout<<endl; }
Templates de clases Ej:
La clase conjunto acotado que vimos anteriormente.
Operadores que uso en la definición del template deben estar sobrecargados adecuadamente.
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Asignación dinámica de memoria
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Supongamos:
Class Node{ public:
Node(int);void SetData(int);. . .
private:int data;Node *nextPtr;
}
Ejemplo de clase auto-referenciada
Estructuras dinámicas de datos requieren asignación dinámica de memoria.
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Operadores:
new : toma como argumento el tipo de objeto que está asignando dinámicamente y devuelve un puntero a dicho
objeto.
Ej:Node *nuevoPtr = new
Node(10);
delete: toma como argumento el puntero al objeto a ser destruido, y libera la memoria asignada por el new.
Ej:
delete nuevoPtr;Cuando ya no es necesaria la memoria que asigné dinámicamente con new, se debe usar delete para devolver la memoria al sistema.
SINO → LEAKS (fuga de memoria)
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Lista Enlazada (un ejemplo de contenedor)
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Abstractamente:
elem1 elem2 elem3
Lista Enlazada (un ejemplo de contenedor)
nodo
¿por qué es mejor que un arreglo?
- si sobredimensionamos un arreglo → desperdiciamos espacio.
- si el arreglo es ordenado → la inserción y el borrado son costosos.
¿siempre es mejor que un arreglo?
+ en un arreglo, puedo acceder inmediatamente a cualquier posicióndel mismo (las listas no permiten este acceso directo).
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
La implementación:
Lista Enlazada (un ejemplo de contenedor)
template <class NodeType>class ListNode {
friend class List<NodeType>; //hace que List sea friend public:
ListNode(const NodeType &); //constructorNodeType getData() const; //devuelve datos del nodo
private:NodeType data; //dato del nodoListNode<NodeType> *nextPtr; //ptro al siguiente nodo
};
Vamos a hacerlo (un poquito) más interesante:
firstPtr lastPtr
Definimos la clase template ListNode:
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Lista Enlazada (un ejemplo de contenedor)
//constructortemplate <class NodeType>ListNode<NodeType>::ListNode(const NodeType &info){ this.data = info; this.nextPtr = NULL;}
// Devuelve una copia del dato del nodotemplate <class NodeType>NodeType ListNode<NodeType>::getData() const { return data; }
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Lista Enlazada (un ejemplo de contenedor)
Definimos la clase template List:
template <class NodeType>class List { public:
List();~List();void insertAtFront(const NodeType &);void insertAtBack(const NodeType &);bool removeFromFront(NodeType &);bool removeFromBack(NodeType &);bool isEmpty();
private:ListNode<NodeType> *firstPtr;ListNode<NodeType> *lastPtr;//este método sirve para asignar un nuevo nodoListNode<NodeType> *getNewNode(const NodeType &);
};
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Lista Enlazada (un ejemplo de contenedor)
// devuelve un puntero a un nodo nuevotemplate<class NodeType>ListNode<NodeType> *List<NodeType>::getNewNode(const NodeType &value){ ListNode<NodeType> *ptr = new ListNode<NodeType>(value); assert( ptr != NULL ); return ptr;}
// Es una lista vacía?template<class NodeType>bool List<NodeType>::isEmpty(){ return (firstPtr == NULL);}
// constructor por defectotemplate<class NodeType>List<NodeType>::List(){ firstPtr = NULL; lastPtr = NULL;}
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Lista Enlazada (un ejemplo de contenedor)
// destructortemplate<class NodeType>List<NodeType>::~List(){ if ( ! isEmpty() ) { ListNode<NodeType> *tmpPtr, *currentPtr ;
currentPtr = this.firstPtr;while ( currentPtr != NULL ) {
tmpPtr = currentPtr; currentPtr = currentPtr->nextPtr; delete tmpPtr; }
}}
//inserta un nodo al inicio de la listatemplate<class NodeType>void List<NodeType>::insertAtFront( const NodeType &value){ ListNode<NodeType> *newPtr = getNewNode( value ); if ( isEmpty() )
firstPtr = lastPtr = newPtr; else { newPtr->nextPtr = firstPtr;
firstPtr = newPtr; }}
firstPtr lastPtr
currentPtr
lastPtr
newPtr
firstPtr
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Lista Enlazada (un ejemplo de contenedor)//inserta un nodo al final de la listatemplate<class NodeType>void List<NodeType>::insertAtBack( const NodeType &value){ /*ejercicio*/}
//borra un nodo del comienzo de la listatemplate<class NodeType>bool List<NodeType>::removeFromFront(NodeType &value){ if ( isEmpty() )
return false; else {
ListNode<NodeType> *tmpPtr = firstPtr; if ( firstPtr == lastPtr)
firstPtr = lastPtr = NULL;else firstPtr = firstPtr->nextPtr;
value = tmpPtr->data;delete tmpPtr;return true;
}}
//borra un nodo del fin de la listatemplate<class NodeType>void List<NodeType>::removeFromBack(NodeType &value){ /*ejercicio*/}
lastPtr
tmpPtr
firstPtr
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Tipos de constructores:
por Defecto:
List();
• Constructor con argumentos predeterminados:
Nodo(int=3); //siempre crea un nodo con dato = 3
Node::Node(int valor){ this.dato = valor; this.nextPtr = NULL;}
por Defecto:
Node(int valor); //este toma un parámetro para establecer a dato.
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
de Copia: Generan una instancia nueva, en base a una copia de la instancia pasada como parámetro.
List(Const List<NodeType> &);
• Por Referencia: Genera un alias.
template<class NodeType>List<NodeType>::List(Const List<NodeType> &lista)
{ this.firstPtr = lista.firstPtr; this.lastPtr = lista.lastPtr;}
• Por Copia: Genera una copia.
template<class NodeType>List<NodeType>::List(Const List<NodeType> &lista)
{ ListNode<NodeType>* it = lista.firstPtr; while( it!= NULL) {
this.insertAtBack(*it);it = it->nextPtr;
}}
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II
Operador de asignación: No construye una nueva instancia, sino que reutiliza una existente.
List& operator=(Const List<NodeType> &);
• Permite hacer:
la = lb; //asigna a la la lista lb (puede ser por copia o referencia).
~List();
No se lo invoca explícitamente (lo invoca internamente el delete de list).
Destructores: