190 likes | 358 Views
Dinamismo y Contenedores. (C++ Avanzado). Depto. de Computación. Facultad de Ciencias Exactas y Naturales Universidad de Buenos Aires. Algoritmos y Estructuras de Datos II 1er Cuatrimetre de 2005. Punteros: Declaración : int *p; ← p es puntero a un int
E N D
Dinamismo y Contenedores (C++ Avanzado) Depto. de Computación Facultad de Ciencias Exactas y Naturales Universidad de Buenos Aires Algoritmos y Estructuras de Datos II 1er Cuatrimetre de 2005
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 Repaso…
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)? 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) • Punteros: • Ej: float suma(float *a,float *b){ • return = *a + *b; • }
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 • Const: • Seguridad en el manejo de datos . • Ej: float suma (const float *a, const float *b) “a es un puntero a un float constante” • 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)
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; • } Parámetro formal Operadores que uso en la definición del template deben estar sobrecargados adecuadamente. Dinamismo y Contenedores Algoritmos y Estructuras de Datos II • Templates: • Reutilización de código. • Evita tener que programar funciones sobrecargadas. • Templates de clases • Ej: • La clase conjunto acotado que vimos anteriormente.
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 Lista Enlazada (un ejemplo de contenedor) • Abstractamente: elem1 elem2 elem3 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ón del mismo (las listas no permiten este acceso directo).
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II Lista Enlazada (un ejemplo de contenedor) • La implementación: Vamos a hacerlo (un poquito) más interesante: firstPtr lastPtr Definimos la clase template ListNode: template <class NodeType> class ListNode { friend class List<NodeType>; //hace que List sea friend public: ListNode(const NodeType &); //constructor NodeType getData() const; //devuelve datos del nodo private: NodeType data; //dato del nodo ListNode<NodeType> *nextPtr; //ptro al siguiente nodo };
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II Lista Enlazada (un ejemplo de contenedor) //constructor template <class NodeType> ListNode<NodeType>::ListNode(const NodeType &info) { this.data = info; this.nextPtr = NULL; } // Devuelve una copia del dato del nodo template <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 nodo ListNode<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 nuevo template<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 defecto template<class NodeType> List<NodeType>::List() { firstPtr = NULL; lastPtr = NULL; }
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II Lista Enlazada (un ejemplo de contenedor) • // destructor • template<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 lista • template<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 firstPtr lastPtr newPtr
Dinamismo y Contenedores Algoritmos y Estructuras de Datos II Lista Enlazada (un ejemplo de contenedor) //inserta un nodo al final de la lista template<class NodeType> void List<NodeType>::insertAtBack( const NodeType &value) { /*ejercicio*/} //borra un nodo del comienzo de la lista template<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 lista template<class NodeType> void List<NodeType>::removeFromBack(NodeType &value) { /*ejercicio*/} firstPtr lastPtr tmpPtr
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; • } • }
Destructores: • ~List(); • No se lo invoca explícitamente (lo invoca internamente el delete de list). 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).