Capitulo V Listas Enlazadas

Documentos relacionados
Tema 6. Gestión dinámica de memoria

Apuntadores en C y C++

Laboratorio de Arquitectura de Redes. Punteros en lenguaje C

DEFINICION. Ing. M.Sc. Fulbia Torres Asignatura: Estructuras de Datos Barquisimeto 2006

Tema 2. Memoria Dinámica. 2.1 Datos estáticos y dinámicos

UNIVERSIDAD DE LOS ANDES NUCLEO UNIVERSITARIO RAFAEL RANGEL (NURR) DEPARTAMENTO DE FISICA Y MATEMATICA AREA COMPUTACION TRUJILLO EDO.

Capítulo. Listas, pilas y colas en C. Contenido. Introducción

2.2 Nombres, Ligado y Ámbito

Tema: Tipos Abstractos de Datos (TAD s) en C++.

Apuntadores (Punteros)

Elementos de un programa en C

Memoria Dinámica. Jornadas de Marzo 2010 Grupo de Usuarios de Linux Tania Pérez

Relación de prácticas de la asignatura METODOLOGÍA DE LA PROGRAMACIÓN Segundo Cuatrimestre Curso º Grado en Informática

Tema: Punteros a Objetos. Puntero this.

Vectores. 27/05/05 Programación Digital I 1

Clases e instancias. Algoritmos y Estructuras de Datos I. Clases e instancias. memoria dinámica.

Contenidos. Gestión dinámica de memoria. Gestión dinámica de memoria. Introducción. 1. Introducción 2. El operador NEW 3. El operador DELETE

324 MR Versión 1 Prueba Integral 1/3 Semana 10 Lapso

Tabla de Símbolos. Programación II Margarita Álvarez

Programación. Test Autoevaluación Tema 3

TIPO DE DATO ABSTRACTO (TDA)

Práctica 3. Paso de parámetros entre subrutinas. 3. Consideraciones sobre el paso de parámetros

Punteros. Definición Un puntero es un dato que contiene una dirección de memoria.

Curso de Programación en C. Licenciatura, FCQeI. APUNTADORES.

PRÁCTICA No. 13 ÁRBOL BINARIO DE BÚSQUEDA

Algoritmos y Programación I

Relación de prácticas de la asignatura METODOLOGÍA DE LA PROGRAMACIÓN Segundo Cuatrimestre Curso º Grado en Informática

Prof. Dr. Paul Bustamante

PILAS Fundamentos

USO DE SUBRUTINAS, TRANSMISIÓN DE PARÁMETROS Y COMPILACIÓN CONDICIONAL EN C++

Árboles. Cursos Propedéuticos Dr. René Cumplido M. en C. Luis Rodríguez Flores

Tema ADQUISICIÓN Y TRATAMIENTO DE DATOS. Departamento de Ciencias de la Computación e IA. Subprogramas en C

Vectores y matrices. Fundamentos de Programación Fundamentos de Programación I

Unidad Didáctica 2. Elementos básicos del lenguaje Java Tipos, declaraciones, expresiones y asignaciones

Tema 7.- Fundamentos de la Programación Orientada a Objetos

Tema: Arreglos de Objetos en C++.

TAD: Pila. TALLER: TAD Pila

Programación Estructurada

TEMA 7: Ficheros. TEMA 7: Ficheros Concepto de fichero

Descripción y Contenido del Curso. Programación C++ Capacity Academy.

Procesos e Hilos en C

Tecnólogo Informático- Estructuras de Datos y Algoritmos- 2009

Instituto Tecnológico de Celaya

INTRODUCCIÓN AL TIPO COMPUESTO CADENA CONTENIDOS

Procesadores de lenguaje Tema 6 La tabla de símbolos

ELO320 Estructuras de Datos y Algoritmos. Arboles Binarios. Tomás Arredondo Vidal

El lenguaje C. 1. Estructuras. Principios de Programación Definicion de estructuras

Resumen de Sintaxis en C

3. Indicar la salida por pantalla (2 puntos-15 minutos)

Estructura de Datos. TDA: Listas. Primer Semestre, Indice. Tipos de estructura de datos lineales

Lección 2 Introducción al lenguaje C

Principios de Computadoras II

Programación de Computadores 4 Iteraciones y Decisiones. Prof. Javier Cañas. Universidad Técnica Federico Santa María Departamento de Informática

Tema 5. Estructura de datos Pila

Informática I para Bachillerato

Estructuras de datos: Pilas, Colas, Listas

CI2126 PRÁCTICA 9: TAD COLA. 1) Implemente las operaciones C_Insert y C_Remove del TAD COLA usando a. un arreglo. La estructura sería:

INTRODUCCIóN A LA PROGRAMACIóN APUNTES DE JAVA APUNTES DE JAVA

Examen escrito de Programación 1. Jueves 5 de febrero de Problema 1 o (3.5 puntos)

Programación estructurada (Introducción a lenguaje C)

Organización de Computadoras

RESUMEN DE CONCEPTOS BASICOS DE PROGRAMACION JAVA

Tema 2. El lenguaje JAVA

LENGUAJE DE PROGRAMACION I. Ing. JAVIER ECHEGARAY ROJO Ing. WILDER ROMAN MUNIVE. Ing. Javier Echegaray Rojo / Ing. Wilder Román Munive Pag 1

1. Conceptos de memoria.

Examen Principios de Programación Febrero 2012

UNIDAD 9. DATOS COMPLEJOS PILAS

Tema: Sobrecarga de Operadores.

Ejercicio 1 (2 puntos. Tiempo: 25 minutos)

Instituto Politécnico Nacional

Introducción al tipo de dato ARRAY

Unidad II. Fundamentos de programación en Java. Ing. José Luis Llamas Cárdenas

Guía - Taller # 2 (JAVA)

Ficheros conceptos. Manejo de ficheros en C. Apertura del fichero Función fopen: nombre del fichero. Apertura del fichero Función fopen

PROGRAMA DE ASIGNATURA DE PROGRAMACIÓN I

Estructuras de Datos Dinámicas. Diseñar y programar en lenguaje C soluciones utilizando estructuras de datos dinámicas

Un elemento de cualquier clase llamada Info; Un puntero a un nuevo nodo llamado sig; De tal forma una unión de nodos hace que tengamos una lista:

Tema 7. Generación de código

Se guardan en archivos con extencion c y los cabezales con extension h

Ejercicio 1. Ejercicio 2

Introducción a C++ y Code::Blocks

Todo programa en 'C' consta de una o más funciones, una de las cuales se llama main.

Carlos Montenegro. Programación Orientada a Objetos Proyecto Curricular de Ingeniería de Sistemas

Práctica de constantes, expresiones y operadores. Programación en C 1

LENGUAJE. Tema 2 Elementos de un programa

PROGRAMACIÓN EN C#.NET Módulo 4.- Arreglos y cadenas. Ing. Bruno López Takeyas

TEMA 8: ESTRUCTURAS DE DATOS COMPLEJAS 1 VECTORES ESTÁTICOS 2 2 CADENAS O VECTORES DE CARACTERES 6 3 PASO DE CADENAS Y ARRAYS A FUNCIONES 8

Primer Parcial de Programación 3 (1/10/2009)

Uso avanzado de punteros

Curso de Programación Avanzada en C

Una variable de clase escalar tiene un nivel de indirección igual a 1. Por ejemplo, las variables i, b y x definidas como se muestra a continuación.

Fundamentos de Informática

Examen escrito de Programación 1

INGENIERIA DE SISTEMAS 1 ESTRUCTURAS DE DATOS (Listas simples) INTRODUCCIÓN A LAS ESTRUCTURAS DE DATOS

Introducción al tipo Vector Cómo guardar una colección de datos conceptualmente relacionados? - almacenar los 100 primeros números primos, - al

Sistemas operativos. Tema 10: Sistemas de ficheros

Transcripción:

Capitulo V Listas Enlazadas Muere lentamente, quien abandona un proyecto antes de iniciarlo, no preguntando de un asunto que desconoce o no respondiendo cuando le indagan sobre algo que sabe. Evitemos la muerte en suaves cuotas, recordando siempre que estar vivo exige un esfuerzo mucho mayor que el simple hecho de respirar. Pablo Neruda 5.1. Introducción a las Estructuras de Datos Dinámica Hasta ahora, todos los tipos de datos que se han visto, ya sean simples o estructurados, tienen una propiedad común: son estáticos. Esto significa que las variables que se declaran en un programa de alguno de estos tipos mantendrán la misma estructura durante la ejecución del mismo. Son variables estáticas y se definen en tiempo de compilación. Ejemplo 1: Si se declara un Vector de 5 elementos de tipo int, éste podrá cambiar su contenido, pero no su estructura. Hay muchas situaciones en las que se desea cambiar el tamaño de las estructuras usadas. La técnica usada para manejar estas situaciones es la asignación dinámica de memoria. Con este tipo de asignación se tendrán variables dinámicas o referenciadas, que pueden crearse y destruirse en tiempo de ejecución. Ejemplo 2: Si se pide diseñar un programa para gestionar una agenda de teléfonos con los datos de personas (nombre, apellidos, dirección, cumpleaños, teléfono, email, etc...). Qué estructura puede utilizarse para realizarla? Programación II 65 Lic. Katya Pérez Martínez

Una respuesta inmediata pareciera ser la de usar un array (vector o matriz), de la siguiente forma: #define MAX 50 Struct Persona char nombre[10]; char apellidos[10]; char dirección[15]; char email[20] ; Persona per[max]; Si se usa un arreglo de dimensión MAX, pueden surgir los siguientes problemas: Qué pasa si se quieren insertar más personas de MAX en la agenda? Hay que recompilar el programa para ampliar MAX Si el número de personas de la agenda es mucho menor que MAX se está desperdiciando memoria que podría ser utilizada por otros programas En muchos otros casos no es posible conocer anteladamente el numero de elementos que se van a usar. Ejemplo 3: Bases de datos para almacenar los datos de los estudiantes de la universidad Elementos de un dibujo de pantalla, cuyo tamaño depende del dibujo trazado 5.2. Mecanismos Para Enlazar Información a. LISTAS o Listas simplemente enlazadas Solo hay un enlace por nodo Solo se puede recorrer en una dirección o Listas doblemente enlazadas o Lista circular simplemente enlazada o Lista circular doblemente enlazada b. ÁRBOLES Y GRAFOS Programación II 66 Lic. Katya Pérez Martínez

5.3. El Tipo Puntero. Siempre que se habla de punteros hay que diferenciar claramente entre lo que es: Variable referencia o apuntadora (o simplemente puntero) Variable referenciada o apuntada. Una variable de tipo Puntero (variable referencia) contendrá una referencia, es decir la dirección en memoria de una variable de un tipo determinado (variable referenciada). Por tanto, siempre existirá asociado al tipo Puntero, otro tipo que es el de la variable referenciada. En C la definición será: Tipo *TipoP tipo de la variable referenciada. Un puntero es una representación simbólica de una dirección de memoria, es decir, contiene la dirección de un objeto o variable. También se define como una variable que contiene una dirección de memoria. Un puntero apunta a una posición en memoria Operadores * y & & permite devolver la dirección de memoria donde se encuentra almacenada el valor de una variable & Contiene la dirección o posición de memoria en la cual se ha almacenado una variable. El operador & es unario, es decir, tiene un solo operando, y devuelve la dirección de memoria de dicho operando. Supongamos el siguiente ejemplo: Para int x = 4; se tiene * (operador de indirección) Representa el contenido de una dirección de memoria del mismo tipo que ha sido declarada. Programación II 67 Lic. Katya Pérez Martínez

El operador * es unuario y toma a su operando como una dirección de memoria, entonces el operador accesa al contenido de esa dirección. Por ejemplo, suponga las variables declaradas anteriormente y la asignación, Declaración de puntero: TipoDato *NombrePuntero; Ejemplo 4: int *p; // declaración de puntero a una variable entera flota *pf; // declaración de puntero a una variable real Ejemplo 5: int *p; int y; p=&x; y=*p; // Declaración puntero a una variable entera // Declaración de variable de tipo entera // a p se le asigna la dirección de almacenamiento de la variable // se asigna a y el contenido donde apunta p Note que solamente un a puntero se le puede asignar una dirección de memoria. Gráficamente tenemos: Ejemplo 6: En un momento dado, la variable p será un puntero, o lo que es lo mismo, contendrá la dirección en memoria de una variable de tipo entero, que a su vez, contendrá un entero. Para acceder a la variable apuntada (referenciada) hay que hacerlo a través de la variable puntero, ya que aquella no tiene nombre (por esto, también se le denomina variable anónima). Programación II 68 Lic. Katya Pérez Martínez

NOTA Para intercambiar los valores de los parámetros actuales, las funciones deben recibir la dirección de memoria donde se encuentran las variables. main() TipoDato a,b;...... funcion(&a,&b);...... /*Traspaso de direcciones de las variables*/ funcion( TipoDato *x, TipoDato *y) */... /*Los parámetros apuntan a las direcciones Ejemplo : void intercambia(int *x, int *y) int temp; temp=*x; *x=*y; *y=temp; EJERCICIOS: PROGRAMAS DE PUNTEROS // Programa PUNTEROS. Uso de & y * #include <iostream.h> void main (void ) int a; int *P; a = 7; P = &a; // a es un entero // P es un puntero a un entero // P asignado a la dirección de a cout << "La dirección de a es " << &a << endl << "\n El valor de P es " << P << endl << endl; cout << "El valor de a es " << a << endl << "El valor de *P es " << *P << endl << endl; cout << "Demostrando que * y & son complementos de " << "cada uno. " << endl << "&*P = " << &*P << endl << "*&P = " << *&P <<endl; return 0; Programación II 69 Lic. Katya Pérez Martínez

// Programa PUNTEROS. Uso de & y * #include <iostream.h> main ( ) int a; int *aptr; a = 7; aptr = &a; // a es un entero // aptr es un apuntador a un entero // aptr asignado a la dirección de a cout << "La dirección de a es " << &a << endl << "El valor de aptr es " << aptr << endl << endl; cout << "El valor de a es " << a << endl << "El valor de *aptr es " << *aptr << endl << endl; cout << "Demostrando que * y & son complementos de " << "cada uno. " << endl << "&*aptr = " << &*aptr << endl << "*&aptr = " << *&aptr <<endl; return 0; // Programa Nº2 PUNTEROS.suma de dos números A y B y resultado en C #include <iostream.h> #include<conio.h> void main (void) int A, B, C; int *P1, *P2; // A, B y C son enteros // P1 y P2 son punteros a enteros A = 4; B = 6; P1 = &A; // a P1 se le asigna la dirección de A. P2 = &B; // a P2 se le asigna la dirección de B. C = (*P1) + (*P2); Cout<< el resultado de la suma de << *P1 << + <<*P2<< = <<C; getch(); Las listas enlazadas son estructura de datos naturales donde el número de elementos que la integran no es conocido, o en su mejor caso, la cantidad de los mismos puede variar. Programación II 70 Lic. Katya Pérez Martínez

Una lista enlazada es una estructura de datos en la que los objetos están ubicados linealmente. En lugar de índices de arreglo aquí se emplean punteros para agrupar linealmente los elementos. La lista enlazada permite implementar todas las operaciones de un conjunto dinámico. Si el predecesor de un elemento es NULL, se trata de la cabeza de la lista. Si el sucesor de un elemento es NULL, se trata de la cola de la lista. Cuando la cabeza es NULL, la lista está vacía o no existe la lista Toda lista cuenta con un encabezado y nodos. Gráficamente una lista simplemente enlazada se representa de la siguiente forma: Cabeza de la Lista Dirección de memoria Nodo Ultimo elemento de la Lista P Info 23 12 4 enlace NOTA Las listas almacenadas en arreglos están sujetos al tamaño del arreglo para su crecimiento. Si estos están vacíos se esta ocupando memoria sin uso. Además las listas reflejan el orden lógico y el orden físico de los elementos en el arreglo. Características: Las listas son una secuencia ordenada de elementos llamados nodo Toda lista tiene una cabecera y una cola. Todos los nodos de la lista son del mismo tipo. Los nodo pueden ser agregados o suprimidos en cualquier momento en la lista Programación II 71 Lic. Katya Pérez Martínez

Una lista enlazada es una secuencia ordenada de elementos llamados nodos 5.4. Tipo De Dato Abstracto Nodo Un NODO es una estructura compuesta básicamente de dos partes: Un campo de información, en cual se almacenan datos o estructuras Un campo de dirección, en el cual se almacena la dirección del nodo siguiente. La implementación de un nodo podría ser de la siguiente forma: El nodo puede contener objetos de cualquier tipo. Valor que almacenará el nodo. struct Nodo int info; nodo *sig; ; typedef Nodo *LISTA; Todo nodo contará con un apuntador hacia el siguiente nodo. 5.5. Punteros La construcción y manipulación de una lista enlazada requiere el acceso a los nodos de la lista a través de uno o más punteros a nodos. Normalmente, un programa incluye un puntero al primer nodo (cabeza) y un puntero al último nodo (cola). De cualquier forma el último elemento de la lista contiene un valor de 0, esto es, un puntero nulo (NULL) que señala el final de la lista. 5.5.1. Operador -> Programación II 72 Lic. Katya Pérez Martínez

Si p es un puntero a una estructura y m es un elemento de esa estructura entonces p->m accede al miembro m de la estructura puntada por p 5.6. Operaciones Basicas Sobre Listas Enlazadas Existen cinco operaciones básicas que se pueden hacer sobre listas enlazadas: Creación: de una lista vacía Vacía: Retorna verdadero si la lista L está vacía y falso en caso contrario. Inserción: Agregar un elemento al final de la lista. Acceso: Examinar el primer elemento de la lista. Eliminar: Se puede quitar el primer elemento de la lista, o remover todos los elementos de la misma. Buscar: ver si la lista contiene un elemento determinado. Anula: Permite convertir la lista en una lista vacía Imprime Lista: Imprime los elementos de la lista L Creación de una lista vacía A continuación implementamos el procedimiento para crear una lista vacía. void CREAR_LISTA (LISTA *L) *L = NULL; cout<< \n lista creada ; Inserción a) Inserción al Final de la lista En el siguiente segmento de código se ejemplifica solamente el caso en el que el elemento se adiciona al final de la lista tal y como si se tratase de una estructura Pila o Cola. Programación II 73 Lic. Katya Pérez Martínez

Se crea un nuevo nodo asociado al puntero T void Inserta_Final (LISTA *p, int elem) LISTA Q, T; T = new Nodo; T -> Info = elem; T -> sig = NULL; if(*p!= NULL) Q = *p; while ( Q-> sig!= NULL) Q = Q -> sig; Q -> sig = T; else *p = T; Recorrido hasta el final de la lista Se realiza el enlace al final de la lista b) Inserción al Final de la lista En el siguiente segmento de código se implementa el caso en el que el nuevo nodo se inserta en la cabeza de la lista: void Inserta_Inicio(LISTA *p, int elem) LISTA Q; Q = new Nodo; Q - > Info = elem; Q - > sig = *p; *p = Q; Para el siguiente ejemplo se ilustra el proceso de adición de un nuevo nodo p = Inserta_Inicio(&p,10); Programación II 74 Lic. Katya Pérez Martínez

Recorrido de una Lista: Para mostrar los elementos de la lista se realiza el recorrido de la misma, a partir del nodo cabeza de la lista hasta encontrar el último nodo. Recordemos que el último nodo tiene la propiedad que su miembro SIG es igual a NULL. void Recorrido (LISTA p) LISTA Q; Q = p; while ( Q!= NULL) cout<< \n << Q - > Info; Q= Q-> sig; Eliminar el nodo del inicio de la Lista La siguiente función recibe una lista y devuelve esa misma lista, sin el nodo que ocupaba inicialmente la posición de la cabeza. La función será la siguiente: Programación II 75 Lic. Katya Pérez Martínez

void Elimina_Inicio( LISTA *P) LISTA Q; Q = *P; if ( Q->sig!=NULL) *P = Q -> sig; delete Q; *P = NULL; Eliminar el nodo del Final de la Lista void Elimina_Final( LISTA *P) LISTA Q, T ; Q = *P; if ( Q->sig!=NULL) while (Q->sig!= else *p=null; delete Q; T = Q; Q = Q-> sig; T->sig = NULL; NULL) A continuación realizamos la implementación del programa completo de listas simples: Programación II 76 Lic. Katya Pérez Martínez

#include<iostream.h> #include<conio.h> struct Nodo int info; nodo *sig; ; typedef Nodo *LISTA; void CREAR_LISTA (LISTA *L) *L = NULL; cout<< \n lista creada ; void Inserta_Inicio(LISTA *p, int elem) LISTA Q; Q = new Nodo; Q - > Info = elem; Q - > sig = *p; *p = Q; void Recorrido (LISTA p) LISTA Q; Q = p; while ( Q!= NULL) cout<< \n << Q - > Info; Q= Q-> sig; void Elimina_Inicio( LISTA *P) LISTA Q; Q = *P; if ( Q->sig!=NULL) *P = Q -> sig; delete Q; *P = NULL; void Elimina_Final( LISTA *P) LISTA Q, T ; Q = *P; if ( Q->sig!=NULL) while (Q->sig!= NULL) T = Q; Q = Q-> sig; T->sig = NULL; else *p=null; delete Q; //PROGRAMA PRINCIPAL void main (void) LISTA A ; int n, e; CREAR_LISTA(&A) ; clrscr() ; cout<< «cuantos elementos desea ingresar a la lista «; for (int i = 1; i<=n; i++) cout<< ingrese elemento ; cin>>e; Inserta_Inicio(&A, e); Recorrido (A); getch(); Programación II 77 Lic. Katya Pérez Martínez

EJERCICIO Escribir un procedimiento para concatenar dos listas L1 y L2. L2 debe estar concatenado al final de L1. void CONCATENA (LISTA L1, LISTA L2) LISTA Q; Q = L1; while ( Q - >sig!= NULL) Q = Q->sig; Q->sig = L2; Recorrido (L1) ; EJERCICIOS 1. Escriba un programa que permita adicionar elementos no repetidos a una lista. Es decir antes de insertar un determinado elemento se debe verificar antes que éste no se encuentre en la lista. 2. Escriba las subrutinas que permitan adicionar elementos a una lista de forma ordenada 3. Escriba un programa que permita eliminar el elemento de la cola de una lista 4. Escriba un programa que permita contar los elementos de una lista Programación II 78 Lic. Katya Pérez Martínez