ESTRUCTURAS DINÁMICAS DE DATOS (LISTAS)

Documentos relacionados
ESTRUCTURAS DINÁMICAS DE DATOS (LISTAS)

Realizar el ejercicio anterior utilizando Punteros

APUNTADORES. Un apuntador es un objeto que apunta a otro objeto. Es decir, una variable cuyo valor es la dirección de memoria de otra variable.

ESTRUCTURAS DINÁMICAS DE DATOS EN LENGUAJE C

ESTRUCTURAS DINÁMICAS DE DATOS (PILAS) EN C

ESTRUCTURAS DINÁMICAS DE DATOS (COLAS) EN C

UNIVERSIDAD AUTONOMA DE MADRID ESCUELA POLITÉCNICA SUPERIOR ESTRUCTURAS DE DATOS Y ALGORITMOS

LISTAS ENLAZADAS FUNDAMENTOS TEORICOS

UNIDAD 8 Tipos de datos dinámicos: Punteros Asignación dinámica de memoria. Uso de punteros. Inicialización y asignación de punteros.

UNIDAD 8 Tipos de datos dinámicos: Punteros Asignación dinámica de memoria. Uso de punteros. Inicialización y asignación de punteros.

ESTRUCTURAS DINÁMICAS DE DATOS (PILAS)

Estructuras de Datos Dinámicas

Universidad Autónoma del Estado de México 2016, Año del 60 Aniversario de la Universidad Autónoma del Estado de México

Punteros. Índice. 1. Qué es un puntero y por que son importantes.

Ingeniera de Sistemas: Luz Esperanza Espitia Tutora de Estructura de datos.

Este material es de uso exclusivo para estudio, los textos fueron tomados textualmente de varios libros por lo que está prohibida su impresión y

Estructuras Dinámicas

ESTRUCTURAS. Struct Identificador_ tipo_estructura { Tipo miembro_1; /*Declaración de los miembros*/

Estructura de Datos. Listas Enlazadas

Tipos Recursivos de Datos

Tema 8. Listas. José M. Badía, Begoña Martínez, Antonio Morales y José M. Sanchiz

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

UNIVERSIDAD NACIONAL AUTÓNOMA DE MÉXICO

PUNTEROS (APUNTADORES)

IMPLEMENTACIÓN DE PILAS CON LISTAS EN C++

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

Tema 18: Memoria dinámica y su uso en C

Segundo Parcial de Programación 2 7 de junio de 2017

Listas. Programación en C LISTAS. Prof. Álvaro Sánchez Miralles. Programación en C. Listas. Objetivos

ESTRUCTURAS DINÁMICAS DE DATOS

Estructura de datos Colas

PUNTEROS O APUNTADORES C++

Capitulo V Listas Enlazadas

Profesor: José Miguel Rubio L.

ESTRUCTURA DE DATOS. Memoria estática Memoria dinámica Tipo puntero Declaración de punteros Gestión de memoria dinámica Resumen ejemplo

LISTAS. Prof. Ing. M.Sc. Fulbia Torres

Estructura de datos y algoritmos. Tema IV: TIPOS DE DATOS ABSTRACTOS DINÁMICOS LINEALES

Tema 6: Memoria dinámica

Unidad Nº V Listas Enlazadas

TEMA 8: Gestión dinámica de memoria

Listas enlazadas. Programación de Sistemas

Estructuras Dinámicas de datos.

Elementos de un programa en C

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

Arboles Binarios de Búsqueda en C++

WHILE Y DO WHILE BREAK EN LENGUAJE C. BUCLES MIENTRAS. FORZAR SALIDA O TERMINACIÓN. EJEMPLO (CU00534F)

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

Asignación de Memoria (Allocation) Algoritmos y Estructuras de Datos I. Asignación de Dinámica de Memoria

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

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

Instituto Politécnico Nacional

Informática PRÀCTICA 9 Curs Práctica Nº 9: Rango y precisión de representación de números en el ordenador.

1. El Tipo Abstracto de Datos.

Estructura de datos y de la información Boletín de problemas - Tema 10

Tema 1. Programación modular. Programación Avanzada Ingeniería Técnica en Informática de Gestión Jorge Badenas

Tema 13: Apuntadores en C

Punteros. Programación en C 1

Contenido PARTE II: ESTRUCTURAS DE DATOS AVANZADAS

A l g o r i t m o y E s t r u c t u r a d e D a t o s Ing. en Sistemas de Información - 1º año -

ALGORITMOS Y PROGRAMACIÓN I Unidad 3

2. Variables dinámicas

PUNTEROS EN C (APUNTADORES)

Lenguaje C, tercer bloque: Funciones

Definición de árbol. Árboles

A l g o r i t m o y E s t r u c t u r a d e D a t o s Ing. en Sistemas de Información - 1º año -

6. El TDA Lista Implementación con listas enlazadas. es de tipo genérico T. Pueden existir elementos repetidos (a diferencia de los conjuntos).

Estructuras Enlazadas AyED UTN-BA

TEMA 5. CONTROL DE FLUJO DEL PROGRAMA. Sentencia Instrucción Expresión Operadores + Operandos Sintaxis: Sentencia ;

Programación de sistemas Listas enlazadas

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

Examen Teórico (1/3 de la nota final)

(1) Recordemos qué es una pila...

Estructura de Datos: Lista. Facultad Ingeniería y Tecnología Informática Tecnicatura en Programación de Computadoras. Autora: Prof.

Implementación de las Clases Pila, Cola, Lista y Arbol

Árboles. Árboles. Árboles binarios de búsqueda. Árboles. Inserción en un árbol. Árbol binario de búsqueda

Ejercicio 1 (proyecto prlistas, paquete listas)

Estructuras. //identificador del cliente

Introducción a la Programación en C Funciones

Existen varios tipos de árboles: 5.1 Árboles binarios

UNIVERSIDAD BANCARIA DE MEXICO CONSTANCIA UNIDAD Y TRABAJO Guadalupe Godínez Maldonado Prof. Juan Carlos Martínez

Estructuras de datos: Pilas, Colas, Listas

TADs en C. Matías Bordese Algoritmos y Estructuras de Datos II - Laboratorio 2013

Hoja de ejercicios del Tema 9

Apuntadores en C y C++

EJERCICIO 2 (3 PUNTOS) A) Sea el árbol binario AVL de la figura siguiente: B) Dada la estructura de la figura siguiente:

Procesadores de lenguaje Tema 6 La tabla de símbolos

LISTAS ENLAZADAS DOBLES C++

Tema 5 Tabla de Símbolos

Tema 7- Modelo y Aplicación de Pila, Cola y. Tema 7- Modelo y Aplicación de. Lista Con Punto de Interés

Estructura de Datos. Centro Universitario UAEM Valle de México. Unidad II. Estructuras de Datos Lineales - Listas

Tema 6. Gestión dinámica de memoria

Estructura de Datos. Árboles Binarios de Búsqueda ABB. Primer Semestre, 2010

Funciones Definición de función

Tipos de Datos Abstractos (TDA)

TIPO DE DATO ABSTRACTO (TDA)

Capítulo 5. LISTAS. 5.1 Listas y listas vinculadas. Una lista es una colección lineal de elementos.

Estructuración del programa en partes más pequeñas y sencillas

PRÁCTICA No. 9 RECORRIDOS EN ÁRBOLES BINARIOS

EJEMPLOS DE ESTRUCTURAS EN C

Apuntadores (Punteros)

Transcripción:

2010 UNAN LEON Departamento de Computación Ing. En Sistemas Sabatino Docente: Ing. Karina Esquivel A. Asignatura: Practicas Profesionales. ESTRUCTURAS DINÁMICAS DE DATOS (LISTAS)

TEMA 3: ESTRUCTURAS DINÁMICAS DE DATOS (LISTAS) 3.1 INTRODUCCIÓN: Las estructuras dinámicas nos permiten crear estructuras de datos que se adapten a las necesidades reales a las que suelen enfrentarse nuestros programas. A través de estas podremos crear estructuras de datos muy flexibles, en cuanto al orden, la estructura interna o las relaciones entre los elementos que las componen. Las estructuras de datos están compuestas de otras pequeñas estructuras a las que llamaremos nodos o elementos, que agrupan los datos con los que trabajará nuestro programa y además uno o más punteros autoreferenciales, es decir, punteros a objetos del mismo tipo. Dentro de los datos de este tipo de datos podemos hablar de: Listas. Pilas. Colas. Árboles. 3.2 LISTA LINEAL ENLAZADA: Una lista lineal enlazada es un conjunto de elementos u objetos de cualquier tipo, originariamente vacía que, durante la ejecución del programa va creciendo o decreciendo elemento a elemento según las necesidades previstas. En una lista lineal cada elemento apunta al siguiente, es decir, cada elemento tiene información de dónde esta el siguiente. Por este motivo también se le llama lista enlazada. La forma más simple de estructura dinámica es la lista enlazada. En esta forma los nodos se organizan de modo que cada uno apunta al siguiente, y el último no apunta a nada, es decir, el puntero del nodo siguiente vale NULL. En las listas lineales existe un nodo especial: el primero. Normalmente diremos que nuestra lista es un puntero a ese primer nodo y llamaremos a ese nodo la cabeza de la lista. Eso es porque mediante ese único puntero podemos acceder a toda la lista. Cuando el puntero que usamos para acceder a la lista vale NULL, diremos que la lista está vacía. 2

El nodo típico para construir listas tiene esta forma: struct nodo int dato; struct nodo *siguiente; ; En el ejemplo, cada elemento de la lista sólo contiene un dato de tipo entero, pero en la práctica no hay límite en cuanto a la complejidad de los datos a almacenar. Dependiendo del número de punteros y de las relaciones entre nodos, podemos distinguir varios tipos de estructuras dinámicas: LISTAS SIMPLEMENTE ENLAZADA (o abiertas): Cada elemento (nodo) sólo dispone de un puntero, que apuntará al siguiente elemento de la lista o valdrá NULL si es el último elemento. Sólo se pueden recorrer hacia delante. PILAS: Son un tipo especial de lista, conocidas como listas LIFO (Last In, First Out): el último en entrar es el primero en salir). Los elementos se "amontonan" o apilan, de modo que sólo el elemento que está encima de la pila puede ser leído, y sólo pueden añadirse elementos encima de la pila. COLAS: Otro tipo de listas, conocidas como listas FIFO (First In, First Out: El primero en entrar es el primero en salir). Los elementos se almacenan en fila, pero sólo pueden añadirse por un extremo y leerse por el otro. LISTAS CIRCULARES: También llamadas listas cerradas, son parecidas a las listas enlazadas, pero el último elemento apunta al primero. De hecho, en las listas circulares no puede hablarse de "primero" ni de "último". Cualquier nodo puede ser el nodo de entrada y salida. Se recorren siempre en el mismo sentido. LISTAS DOBLEMENTE ENLAZADAS: Cada elemento dispone de dos punteros, uno apunta al siguiente elemento y el otro al elemento anterior. Al contrario que las listas abiertas anteriores, estas listas pueden recorrerse en los dos sentidos. 3.2.1 LISTAS SIMPLEMENTE ENLAZADAS: La forma más simple de estructura dinámica es la lista simplemente enlazada o lista abierta. En esta forma los nodos se organizan de modo que cada uno apunta al siguiente, y el último no apunta a nada, es decir, el puntero del nodo siguiente vale NULL: La anterior es una lista simplemente enlazada que consta de 4 elementos (nodos). 3

Para crear una lista debemos definir la clase de elementos que van a formar parte de la misma. Un tipo de dato genérico podría ser la siguiente estructura: struct nodo int dato; struct nodo *sig; ; El miembro de la estructura "sig", puede apuntar a un objeto del tipo nodo. De este modo, cada nodo puede usarse como un ladrillo para construir listas de datos, y cada uno mantendrá ciertas relaciones con otros nodos. En el ejemplo, cada elemento de la lista sólo contiene un dato de tipo entero, pero en la práctica no hay límite en cuanto a la complejidad de los datos a almacenar. Se pueden diseñar datos struct que actúen como nodos tan complejos como se desee. El nodo anterior se representará así (no consideramos el miembro datos, sólo el miembro sig, que ahora apunta a NULL. Para acceder a un nodo de la estructura sólo necesitaremos un puntero a un nodo. En el ejemplo anterior declaramos una variable de estructura, que va a ser un puntero a dicha estructura. Mediante typedef declaramos un nuevo tipo de dato: typedef struct nodo int dato; struct nodo *siguiente; elemento; elemento *c; //puntero a nodo Ahora elemento es un tipo de dato, sinónimo de struct nodo. El miembro siguiente ha sido declarado como puntero al dato struct nodo y no como puntero a tipo de dato elemento, ya que en ese instante, elemento no estaba aún definido. Por tanto, elemento es el tipo para declarar nodos. Ahora es un tipo de dato. La variable *c es un puntero al tipo de dato elemento. 4

En las listas simples enlazadas existe un nodo especial: el primero. Normalmente diremos que nuestra lista es un puntero a ese primer nodo y llamaremos a ese nodo cabeza de la lista. Eso es porque mediante ese único puntero podemos acceder a toda la lista. Nota: Es muy importante que nuestro programa nunca pierda el valor del puntero al primer elemento, ya que si no existe ninguna copia de ese valor, y se pierde, será imposible acceder al nodo y no podremos utilizar la información almacenada ni liberar el espacio de memoria que ocupa. Cuando el puntero que usamos para acceder a la lista vale NULL, diremos que la lista está vacía: *c = NULL; //lista vacía Inicialmente *siguiente apunta a NULL. Lo representamos gráficamente en la forma: 3.2.2 OPERACIONES BÁSICAS CON LISTAS: Con las listas se pueden realizar las siguientes operaciones básicas: a) Crear lista. b) Añadir o insertar elementos. c) Buscar o localizar elementos. d) Borrar elementos. Cada una de estas operaciones tendrá varios casos especiales, por ejemplo, no será lo mismo insertar un nodo en una lista vacía, o al principio de una lista no vacía, o la final, o en una posición intermedia. 3.2.2.1 CREAR UNA LISTA Si queremos crear una lista, podemos emplear la técnica de reservar memoria dinámicamente. Para ello escribimos una función llamada nuevo_elemento(): elemento *nuevo_elemento(void) elemento *q; q = (elemento *)malloc(sizeof(elemento)); if(q == NULL) puts( No se ha reservado memoria para el nuevo nodo ); return q; //devuelve la dirección del espacio de memoria reservado Cada vez que deseemos crear un nuevo nodo, debemos llamar a la función nuevo_elemento() para realizar la reserva de memoria. 5

Ejemplo #1: Código C que permite crear una lista asignando memoria de forma dinámica. //crear_lista.c #include<stdio.h> elemento *nuevo_elemento(void) elemento *q; q = (elemento *)malloc(sizeof(elemento)); if(q == NULL) puts( No se ha reservado memoria para el nuevo nodo ); return q; //devuelve la dirección del espacio de memoria reservado void main() elemento *q; q = NULL; q = nuevo_elemento(); q->siguiente = NULL; //puntero a un nodo //lista vacía //q apunta al nodo recién creado //fin de lista //operaciones... //Liberación de memoria reservada free(q); Gráficamente: 3.2.2.2 AÑADIR O INSERTAR ELEMENTOS EN UNA LISTA ENLAZADA Insertar un elemento en una lista vacía: Este es el caso más sencillo. Equivale a crear una lista, como en el caso anterior. Partiremos de que ya tenemos el nodo a insertar (creado en la llamada a la función nuevo_elemento() ) y, por supuesto un puntero que apunte a él, además el puntero a la lista valdrá NULL: El proceso es muy simple, bastará con que se realice lo siguiente: q = nuevo_elemento(); q->siguiente = NULL; 6

Gráficamente: Insertar un elemento en la primera posición de una lista: Podemos considerar el caso anterior como un caso particular de éste, la única diferencia es que en el caso anterior la lista es una lista vacía, pero siempre podemos, y debemos considerar una lista vacía como una lista. Por tanto, ahora la lista ya existe. De nuevo partiremos de un nodo a insertar, con un puntero que apunte a él (q=nuevo elemento()), y de una lista en este caso no vacía, apuntada por c: q = nuevo_elemento(); q->dato = valor; q->siguiente = c; c = q; Es fundamental no alterar el orden de las operaciones. Gráficamente, tenemos: Insertar un elemento en general: La inserción de un elemento en la lista, a continuación de otro elemento apuntado por c, es de la forma siguiente: q = nuevo_elemento(); q->dato = x; /*Valor insertado */ q->siguiente = c->siguiente; c->siguiente = q; 7

Gráficamente, tenemos: Inserción en la lista detrás del elemento apuntado por c. La inserción de un elemento en la lista antes de otro elemento apuntado por c, se hace insertado un nuevo elemento detrás del elemento apuntado por c, intercambiando previamente los valores del nuevo elemento y del elemento apuntado por c. q = nuevo_elemento(); c -> dato = x; /*Valor Insertado*/ *q = *c; c -> siguiente = q; Gráficamente, sería: Inserción en la lista antes del elemento apuntado por c. 8

3.2.2.3 BORRAR ELEMENTOS DE UNA LISTA ENLAZADA: De nuevo podemos encontrarnos con varios casos, según la posición del nodo a eliminar. Eliminar el primer nodo de una lista enlazada: Es el caso más simple. o Partiremos de una lista con uno o más nodos, y usaremos un puntero auxiliar, q: o Hacemos que q apunte al primer elemento de la lista, es decir a c. o Asignamos a c la dirección del segundo nodo de la lista: c = c->siguiente. o Liberamos la memoria asignada al primer nodo, q, el que queremos eliminar: free(q); Si no guardamos el puntero al primer nodo antes de actualizar c, después nos resultaría imposible liberar la memoria que ocupa. Si liberamos la memoria antes de actualizar c, perderemos el puntero al segundo nodo. q = p; c = c->siguiente; //Actualizar el comienzo de la lista free(q); Si la lista sólo tiene un nodo, el proceso es también válido, ya que el valor de c->siguiente es NULL, y después de eliminar el primer nodo la lista quedará vacía, y el valor de c será NULL. De hecho, el proceso que se suele usar para borrar listas completas es eliminar el primer nodo hasta que la lista esté vacía. Gráficamente, sería: Eliminar un nodo cualquiera de una lista enlazada: En todos los demás casos, eliminar un nodo se puede hacer siempre del mismo modo. Supongamos que tenemos una lista con al menos dos elementos, y un puntero c al nodo anterior al que queremos eliminar. Y un puntero auxiliar q. Si el nodo a eliminar es el último, el procedimiento es igualmente válido, ya que c pasará a ser el último, y c->siguiente valdrá NULL. 9

q = c -> siguiente; c -> siguiente = q -> siguiente; free(q); Gráficamente, sería: Borrar el sucesor del elemento apuntado por c Eliminar un elemento apuntado por c: q = c->siguiente; *c = *q; free(q); Gráficamente, sería: Borrar el elemento apuntado por c Borrar todos los elementos de una lista: Equivale a liberar la memoria reservada para cada uno de los elementos de la misma. Si el primer nodo está apuntado por c, empleamos el puntero auxiliar q: 10

q = c; //salvamos el puntero a la lista while(q!= NULL) c = c->sig; free(q); q = c; Hay que observar que antes de borrar el elemento apuntado por q, hacemos que c apunte al siguiente elemento ya que si no perdemos el resto de la lista. 3.2.2.4 RECORRIDO DE UNA LISTA CUYO PRIMER ELEMENTO ESTÁ APUNTADO POR c. Supongamos que hay que realizar una operación con todos los elementos de una lista, cuyo primer elemento está apuntado por c. Por ejemplo, escribir el valor de cada elemento de la lista. La secuencia de operaciones es la siguiente: q = p; /*salvamos el puntero al comienzo de la lista*/ while(q!=null) printf( %d,q->dato); q = q->siguiente; 3.2.2.5 BUSCAR UN ELEMENTO CON UN VALOR x DENTRO DE LA LISTA ENLAZADA. La búsqueda es secuencial y termina cuando se encuentra el elemento, o bien, cuando se llega al final de la lista. q = p; printf( Que valor desea buscar en la lista? ); scanf( %d,&x); while(q!= NULL && q->dato!= x) q = q->siguiente; 11

3.3 EJEMPLO COMPLETO DE LISTA LINEAL ENLAZADA: Programa que nos permita crear una lista clasificada, en la cual cada elemento conste de dos campos: uno que contenga un número entero y otro que sea un puntero a un elemento del mismo tipo. El programa incluirá las siguientes funciones: 1. Añadir un elemento. Esta función comprenderá dos casos: insertar un elemento al principio de la lista o insertar un elemento después de otro. 2. Borrar un elemento de la lista. Esta función buscará el elemento a borrar y después lo borrará. Hay que distinguir si se trata de la cabecera o de un elemento cualquiera. 3. Buscar un elemento en la lista. 4. Visualizar el contenido de la lista. /****************** Operaciones con listas **********************/ #include <stdio.h> #include <stdlib.h> #include <conio.h> #include<string.h> #define ListaVacia (cabecera==null) /*Lista simplemente enlazada. Cada elemento contiene un nº entero*/ typedef struct datos elemento; /*declaración del tipo elemento*/ struct datos /*elemento de una lista de enteros*/ int dato; elemento *siguiente; ; /*Funciones prototipos*/ elemento *NuevoElemento(void); void error(void); void menu(void); void anadir(elemento **, int); void borrar(elemento **, int); elemento *buscar(elemento *, int); void visualizar(elemento *); /*Función principal*/ void main() elemento *cabecera = NULL; elemento *q; int opcion, dato, k = 10; 12

while(1) do system("cls"); menu(); opcion = getchar(); while(opcion < '1' opcion > '5'); system("cls"); // Limpiar Pantalla switch(opcion) case '1': printf("insertar datos: "); scanf("%d",&dato); anadir(&cabecera,dato); break; case '2': printf("borrar dato: "); scanf("%d",&dato); borrar(&cabecera,dato); break; case '3': printf("buscar dato: "); scanf("%d",&dato); q = buscar(cabecera,dato); if(q) q->dato+=k; else printf("lista vacia\n"); break; case '4': visualizar(cabecera); break; case '5': exit(0); printf("\npulse una tecla para continuar"); getchar(); 13

//Definición de Funciones /* Crear un nuevo elemento */ elemento *NuevoElemento(void) elemento *q = (elemento *)malloc(sizeof(elemento)); return (q); /* Función Error */ void error (void) perror ("Error: insuficiente espacio de memoria.\n"); exit (-1); /* Función Menú */ void menu() printf("\n\t1. Insertar un elemento\n"); printf("\n\t2. Borrar un elemento\n"); printf("\n\t3. Buscar un elemento\n"); printf("\n\t4. Vizaualizar la lista\n"); printf("\n\t5. Salir\n"); printf("\nelija la opcion deseada:\n"); /* Introducir un elemento ordenadamente en la lista */ void anadir(elemento **cab, int dato) elemento *cabecera = *cab; elemento *actual = cabecera,*anterior = cabecera, *q; if (ListaVacia) /*Si la lista esta vacía, crear un nuevo elemento*/ cabecera = NuevoElemento(); cabecera->dato = dato; cabecera->siguiente = NULL; *cab=cabecera; return; /*Entrar en la lista y encontrar el punto de inserción*/ while(actual!= NULL && dato > actual->dato) anterior = actual; actual = actual->siguiente; 14

/*Dos casos: *1) Insertar al principio de la lista *2) Insertar después de anterior (incluye insertar al final)*/ q = NuevoElemento(); /*se genera un nuevo elemento*/ if(anterior == actual) /*insertar al principio*/ q->dato = dato; q->siguiente = cabecera; cabecera = q; else /*insertar después de anterior*/ q->dato = dato; q->siguiente = actual; anterior->siguiente = q; *cab = cabecera; /* Encontrar un dato y borrarlo */ void borrar(elemento **cab, int dato) elemento *cabecera = *cab; elemento *actual = cabecera, *anterior = cabecera; if (ListaVacia) printf("lista Vacia\n"); return; /*entrar en la lista y encontrar el elemento a borrar*/ while(actual!=null && dato!= actual->dato) anterior = actual; actual = actual->siguiente; /*si el dato no se encuentra retornar*/ if(actual == NULL) return; /*si el dato se encuentra, borrar el elmento*/ if(anterior == actual) /*borrar el elemento de cabecera*/ cabecera = cabecera->siguiente; 15

else anterior->siguiente = actual->siguiente; free(actual); *cab = cabecera; /* Buscar un elemento determinado en la lista */ elemento *buscar(elemento *cabecera, int dato) elemento *actual = cabecera; while(actual!= NULL && dato!= actual->dato) actual = actual->siguiente; return (actual); /* Visualizar la lista */ void visualizar(elemento *cabecera) elemento *actual = cabecera; if (ListaVacia) printf("lista Vaica\n"); else while(actual!= NULL) printf("%d ",actual->dato); actual = actual->siguiente; printf("\n"); 16