Introducción a punteros en C

Slides:



Advertisements
Presentaciones similares
Tablas. Descripción general Introducción a las tablas Creación de tablas Uso de tablas.
Advertisements

Unidad 5 Listas Enlazadas Bibliografía: Algoritmos y Estructuras de datos de Aguilar y Martinez. Unidad 9 Autor: Ing Rolando Simon Titiosky.
Clase 3: Punteros y Referencias
Programación I Teoría III
Programación I Teoría IV
Programación, Algoritmos y Estructuras de Datos
Tipos de Datos Básicos y Estructurados
Tema 1. Introducción a la programación (Lenguaje java).
Algoritmos y Estructuras de Datos
Unidad 3 Punteros.
C++ LISTAS C++ 11/04/2017 Ing. Edgar Ruiz Lizama.
Índice. Revisando conceptos acerca de la memoria.
Estructuras.
Algoritmos para Ordenar datos
Unidad VI Registros (estructuras, uniones y enumeraciones)
Programación I Técnico Universitario en Web Dpto. de Informática FCFMyN - UNSL -11-
1 Estructuras de Datos Elementales:stacks (pilas), queues (colas), linked lists (listas enlazadas), y rooted trees (árboles con raíz) Agustín J. González.
Informática Ingeniería en Electrónica y Automática Industrial
El lenguaje de programación C - Vectores y matrices -
1 Asignación Dinámica de Memoria Agustín J. González Versión original de Kip Irvine ELO 329.
Introducción a los punteros Prof. Domingo Hernández.
Manejo de Punteros y objetos en memoria dinámica en C++
Computación I Primer Semestre 2006 Capítulo IV Ciclos y Colecciones (con un sabor a algoritmos)
TEORIA DE LA INFORMACION INGENIERO ANYELO QUINTERO.
Informática Ingeniería en Electrónica y Automática Industrial
Listas Ligadas Simples. Definíción I  Es, en sencillas palabras. un grupo de datos organizados secuencialmente, pero a diferencia de los arreglos, la.
APUNTADORES.
1 Asignación Dinámica de Memoria Agustín J. González ELO 329.
Estructuras con punteros: Nodos y Listas. Un programa C.
PROGRAMACION DE Pilas o Stacks
MEMORIA DINÁMICA.
TIPOS DE DATOS PARCIAL III Punteros. Un puntero es una variable que hace referencia a una dirección de memoria Sintaxis: Tipo_Dato *nombre_variable_puntero;
Tema 1. Estructuras de datos Objetivo: Objetivo: El alumno resolverá problemas de almacenamiento, recuperación y ordenamiento de datos y las técnicas de.
UNIDAD 8 Lista Enlazada: Eliminar Deseamos eliminar un elemento llamado elem de la lista enlazada. Es posible que la variable ini sea modificada. main(){
Introducción al Lenguaje C (I) Tipos básicos, arrays y punteros Fundamentos de Programación Departamento de Lenguajes y Sistemas Informáticos Versión
Lenguaje de Programación II Prof. Rafael Montenegro B. Carrera: T.S.U en Informática Periodo: 2014-I.
AYUDANTÍA 2 Lenguaje Imperativo y Java. Punteros Dirección a memoria (puede apuntar a NULL). Permite trabajar con memoria (variables dinámicas de heap).
Memoria Dinámica Jornadas de Marzo 2010 Grupo de Usuarios de Linux Tania Pérez.
El lenguaje de Programación C Fernando J. Pereda.
Estructura de Datos Luis Humeau Waldi Saturno
L ISTAS ENLAZADAS M.IA. Daniel Alejandro García López.
Taller de Java Universidad de los Andes
BREVE INTRODUCCION A LA PROGRAMACION
Programación en C - manejo de Archivos
Estructuras PILA - COLA - LISTA.
Programación Avanzada
Algunas ideas básicas de C++
Manejo de Punteros y objetos en memoria dinámica en C++
TIPOS DE DATOS Cadenas y caracteres PARCIAL III.
Nociones básicas sobre C++
Listas enlazadas particulares
LISTAS..
Manejo de Punteros y objetos en memoria dinámica en C++
Estructuras de datos y algoritmos
Listas Dinámicas.
Nociones básicas sobre C++
Manejo de Punteros y objetos en memoria dinámica en C++
Manejo de Punteros y objetos en memoria dinámica en C++
Árboles clase 6 Apoyo de Práctica. Resumen ●Árboles ○Concepto ○Características ○Dinámica ○Recorridos o barridos. ●Ejercicio Sugerido.
Listas ligadas Dra. María de Lourdes López García
UNIDAD 8 Agregar al Inicio
Informática Ingeniería en Electrónica y Automática Industrial
Manejo de Punteros y objetos en memoria dinámica en C++
ÁRBOLES DE EXPRESION. Un árbol de expresión sirve para evaluar expresiones del tipo: (a+b)*c/d Para que un árbol represente una expresión se deben tomar.
Informática Ingeniería en Electrónica y Automática Industrial
Manejo de Punteros y objetos en memoria dinámica en C++
Manejo de Punteros y objetos en memoria dinámica en C++
Manejo de Punteros y objetos en memoria dinámica en C++
Asignación Dinámica de Memoria
Memoria estática versus dinámica con Estructuras
Transcripción de la presentación:

Introducción a punteros en C Algoritmos y Estructuras de Datos II (2015) Leonardo M. Rodríguez (presionar F5)

PARTE I: Uso básico de punteros

4 x1 3 x2 'z' c2 'a' c1 3.4 f1 int x1 = 4; int x2 = 3; char c1 = 'a'; char c2 = 'z'; float f1 = 3.4; x1 = x2 * 2; 3 x2 'z' c2 'a' c1 3.4 f1

x1 6 3 x2 'z' c2 'a' c1 3.4 f1 int x1 = 4; int x2 = 3; char c1 = 'a'; char c2 = 'z'; float f1 = 3.4; x1 = x2 * 2; 3 x2 'z' c2 'a' c1 3.4 f1

x1 6 3 x2 'z' c2 p 'a' c1 q 3.4 f1 r int *p = & x1; int *q = & x2; char *r = & c2; p = q; 3 x2 'z' c2 p 'a' c1 q 3.4 f1 r

x1 6 3 x2 'z' c2 p 'a' c1 q 3.4 f1 r int *p = & x1; int *q = & x2; char *r = & c2; p = q; *p = 9; 3 x2 'z' c2 p 'a' c1 q 3.4 f1 r

x1 6 x2 9 'z' c2 p 'a' c1 q 3.4 f1 r int *p = & x1; int *q = & x2; char *r = & c2; p = q; *p = 9; q = & x1; x2 9 'z' c2 p 'a' c1 q 3.4 f1 r

x1 6 x2 9 'z' c2 p 'a' c1 q 3.4 f1 r int *p = & x1; int *q = & x2; char *r = & c2; p = q; *p = 9; q = & x1; *q = *p + 1; x2 9 'z' c2 p 'a' c1 q 3.4 f1 r

x1 10 x2 9 'z' c2 p 'a' c1 q 3.4 f1 r int *p = & x1; int *q = & x2; char *r = & c2; p = q; *p = 9; q = & x1; *q = *p + 1; r = & c1; x2 9 'z' c2 p 'a' c1 q 3.4 f1 r

x1 10 x2 9 'z' c2 p 'a' c1 q 3.4 f1 r int *p = & x1; int *q = & x2; char *r = & c2; p = q; *p = 9; q = & x1; *q = *p + 1; r = & c1; *r = c2; x2 9 'z' c2 p 'a' c1 q 3.4 f1 r

x1 10 x2 9 'z' c2 p c1 'z' q 3.4 f1 r int *p = & x1; int *q = & x2; char *r = & c2; p = q; *p = 9; q = & x1; *q = *p + 1; r = & c1; *r = c2; x2 9 'z' c2 p c1 'z' q 3.4 f1 r

Checkpoint int *p; Declaración de un puntero. En este caso la variable p es un puntero a una variable de tipo entero. El tipo de los punteros (color de la flecha) es muy importante. (&) Operador de referencia (“crear una flecha”) (*) Operador de dereferenciación (“seguir la flecha”)

PARTE II: Pasaje de referencias

¿Qué número imprime en pantalla este programa? int main (void) { int x = 4; mitad(x); printf(“%d\n”, x); return 0; } void mitad(int y) { y = y / 2; ¿Qué número imprime en pantalla este programa?

x 4 int main (void) { int x = 4; mitad(x); printf(“%d\n”, x); return 0; } void mitad(int y) { y = y / 2;

x 4 y 4 int main (void) { int x = 4; mitad(x); printf(“%d\n”, x); return 0; } void mitad(int y) { y = y / 2; y 4

x 4 y 2 int main (void) { int x = 4; mitad(x); printf(“%d\n”, x); return 0; } void mitad(int y) { y = y / 2; y 2

x 4 y 2 int main (void) { int x = 4; mitad(x); printf(“%d\n”, x); return 0; } void mitad(int y) { y = y / 2; IMPRIME 4! y 2

¿Qué número imprime en pantalla este programa? int main (void) { int x = 4; mitad(&x); printf(“%d\n”, x); return 0; } void mitad(int *y) { *y = *y / 2; ¿Qué número imprime en pantalla este programa?

x 4 int main (void) { int x = 4; mitad(&x); printf(“%d\n”, x); return 0; } void mitad(int *y) { *y = *y / 2;

x 4 y int main (void) { int x = 4; mitad(&x); printf(“%d\n”, x); return 0; } void mitad(int *y) { *y = *y / 2; y

x 2 y int main (void) { int x = 4; mitad(&x); printf(“%d\n”, x); return 0; } void mitad(int *y) { *y = *y / 2; y

x 2 y int main (void) { int x = 4; mitad(&x); printf(“%d\n”, x); return 0; } void mitad(int *y) { *y = *y / 2; IMPRIME 2! y

PARTE III: Punteros y arreglos

int a[4] = {1,3,8,6}; int *p = NULL; 1 3 8 6 a

int a[4] = {1,3,8,6}; int *p = NULL; p = a; 1 3 8 6 a p

int a[4] = {1,3,8,6}; int *p = NULL; p = a; *p = 5; 1 3 8 6 a p

a p int a[4] = {1,3,8,6}; int *p = NULL; p = a; *p = 5; *(p + 1) = 0;

a p int a[4] = {1,3,8,6}; int *p = NULL; p = a; *p = 5; *(p + 1) = 0; 8 6 a p

a p int a[4] = {1,3,8,6}; int *p = NULL; p = a; *p = 5; *(p + 1) = 0; 8 7 a p

a p int a[4] = {1,3,8,6}; int *p = NULL; p = a; *p = 5; *(p + 1) = 0; 3 7 a p

a p int a[4] = {1,3,8,6}; int *p = NULL; p = a; *p = 5; *(p + 1) = 0; 3 7 a p

a p int a[4] = {1,3,8,6}; int *p = NULL; p = a; *p = 5; *(p + 1) = 0; 2 7 a p

Checkpoint Arreglos y punteros int a[4] = {1,3,5,8} En la asignación siguiente, el arreglo “decae” o “se convierte” a un puntero a su primer elemento. int *p = a; Un poco de aritmética de punteros Nos aprovechamos que los arreglos siempre se alojan en memoria contigua (consecutiva) *(p + 1) = 4 “Seguir la flecha de p y moverse 1 lugar a la derecha” Esa operación es equivalente a usar la notación de arreglos: p[1] = 4; p = p + 1; “Desplazar la flecha 1 lugar a la derecha”

PARTE IV: Punteros y estructuras

struct _punto { int x; Int y; }; struct _punto r; r.x = 0; x y r

x r y struct _punto { int x; Int y; }; struct _punto r; r.x = 0;

x r y struct _punto { int x; Int y; }; struct _punto r; 1 r.x = 0; struct _punto *p = NULL; x y r 1

p x r y struct _punto { int x; Int y; }; struct _punto r; 1 r.x = 0; struct _punto *p = NULL; p = & r; x y r 1 p

p x r y struct _punto { int x; Int y; }; struct _punto r; 1 r.x = 0; struct _punto *p = NULL; p = & r; (*p).x = 2; x y r 1 p

p x r y struct _punto { int x; Int y; 2 }; struct _punto r; 1 r.x = 0; struct _punto *p = NULL; p = & r; (*p).x = 2; p->y = 3; x y r 2 1 p

p x r y struct _punto { int x; Int y; 2 }; struct _punto r; 3 r.x = 0; struct _punto *p = NULL; p = & r; (*p).x = 2; p->y = 3; x y r 2 3 p

p x r y struct _punto { int x; Int y; 2 }; typedef struct _punto *punto_t; struct _punto r; r.x = 0; r.y = 1; struct _punto *p = NULL; p = & r; (*p).x = 2; p->y = 3; x y r 2 3 p

p x r y struct _punto { int x; Int y; 2 }; typedef struct _punto *punto_t; struct _punto r; r.x = 0; r.y = 1; punto_t p = NULL; p = & r; (*p).x = 2; p->y = 3; x y r 2 3 p

Checkpoint Punteros y estructuras El operador “->” sirve para acceder al campo de una estructura a partir de un puntero. (*p).x es equivalente a p->x De paso vimos... Sinónimos de tipos typedef es útil para hacer sinónimos de tipos. typedef int entero; typedef char caracter; typedef int *puntero_a_entero; entero x = 0; puntero_a_entero p = & x;

PARTE V: Memoria Dinámica

HEAP STACK void g() { int x = 2; int y = 1; return; } void f() { int z = 0; g(); int main() { int x = 0; int i = 0; f(); return 0; HEAP STACK x y 2 1 x z 1 x i

HEAP STACK int main() { int *p = NULL; p = calloc(2, sizeof(int)); free(p); p = NULL; return (0); } HEAP STACK p

HEAP STACK int main() { int *p = NULL; p = calloc(2, sizeof(int)); free(p); p = NULL; return (0); } HEAP STACK p

HEAP STACK int main() { int *p = NULL; p = calloc(2, sizeof(int)); free(p); p = NULL; return (0); } HEAP STACK 2 p

HEAP STACK int main() { int *p = NULL; p = calloc(2, sizeof(int)); free(p); p = NULL; return (0); } HEAP STACK 2 DANGLING POINTER p

HEAP STACK int main() { int *p = NULL; p = calloc(2, sizeof(int)); free(p); p = NULL; return (0); } HEAP STACK p

HEAP STACK int main() { int *p = NULL; p = calloc(2, sizeof(int)); free(p); p = NULL; return (0); } HEAP STACK p

HEAP STACK void modificar (int *q) { q[1] = 2; return; } int main() { int *p = NULL; p = calloc(2, sizeof(int)); assert(p != NULL); modificar(p); free(p); p = NULL; return (0); HEAP STACK p

HEAP STACK void modificar (int *q) { q[1] = 2; return; } int main() { int *p = NULL; p = calloc(2, sizeof(int)); assert(p != NULL); modificar(p); free(p); p = NULL; return (0); HEAP STACK p

HEAP STACK void modificar (int *q) { q[1] = 2; return; } int main() { int *p = NULL; p = calloc(2, sizeof(int)); assert(p != NULL); modificar(p); free(p); p = NULL; return (0); HEAP STACK p

HEAP STACK void modificar (int *q) { q[1] = 2; return; } int main() { int *p = NULL; p = calloc(2, sizeof(int)); assert(p != NULL); modificar(p); free(p); p = NULL; return (0); HEAP STACK q p

HEAP STACK void modificar (int *q) { q[1] = 2; return; } int main() { int *p = NULL; p = calloc(2, sizeof(int)); assert(p != NULL); modificar(p); free(p); p = NULL; return (0); HEAP STACK 2 q p

HEAP STACK void modificar (int *q) { q[1] = 2; return; } int main() { int *p = NULL; p = calloc(2, sizeof(int)); assert(p != NULL); modificar(p); free(p); p = NULL; return (0); HEAP STACK q 2 p

HEAP STACK void modificar (int *q) { q[1] = 2; return; } int main() { int *p = NULL; p = calloc(2, sizeof(int)); assert(p != NULL); modificar(p); free(p); p = NULL; return (0); HEAP STACK 2 p

HEAP STACK void modificar (int *q) { q[1] = 2; return; } int main() { int *p = NULL; p = calloc(2, sizeof(int)); assert(p != NULL); modificar(p); free(p); p = NULL; return (0); HEAP STACK p

HEAP STACK void modificar (int *q) { q[1] = 2; return; } int main() { int *p = NULL; p = calloc(2, sizeof(int)); assert(p != NULL); modificar(p); free(p); p = NULL; return (0); HEAP STACK p

HEAP STACK void amnesia() { int *q = NULL; q = calloc(1, sizeof(int)); return; } int main() { amnesia(); for (int i = 0; i<5; i++) { return (0); HEAP STACK

HEAP STACK void amnesia() { int *q = NULL; q = calloc(1, sizeof(int)); return; } int main() { amnesia(); for (int i = 0; i<5; i++) { return (0); HEAP STACK

HEAP STACK void amnesia() { int *q = NULL; q = calloc(1, sizeof(int)); return; } int main() { amnesia(); for (int i = 0; i<5; i++) { return (0); HEAP STACK q

HEAP STACK void amnesia() { int *q = NULL; q = calloc(1, sizeof(int)); return; } int main() { amnesia(); for (int i = 0; i<5; i++) { return (0); HEAP STACK q

HEAP STACK void amnesia() { int *q = NULL; q = calloc(1, sizeof(int)); return; } int main() { amnesia(); for (int i = 0; i<5; i++) { return (0); HEAP STACK q MEMORY LEAK

HEAP STACK void amnesia() { int *q = NULL; q = calloc(1, sizeof(int)); return; } int main() { amnesia(); for (int i = 0; i<5; i++) { return (0); HEAP STACK

HEAP $> gcc -g -o ejemplo ejemplo.c $> valgrind --show-reachable=yes --leak-check=full ./ejemplo ==8066== HEAP SUMMARY: ==8066== in use at exit: 24 bytes in 6 blocks ==8066== total heap usage: 6 allocs, 0 frees, 24 bytes allocated ==8066== ==8066== 4 bytes in 1 blocks are definitely lost in loss record 1 of 2 ==8066== at 0x4C272B8: calloc (vg_replace_malloc.c:566) ==8066== by 0x40052A: amnesia (ejemplo.c:6) ==8066== by 0x400543: main (ejemplo.c:12) ==8066== 20 bytes in 5 blocks are definitely lost in loss record 2 of 2 ==8066== by 0x400556: main (ejemplo.c:14) ==8066== LEAK SUMMARY: ==8066== definitely lost: 24 bytes in 6 blocks ==8066== indirectly lost: 0 bytes in 0 blocks ==8066== possibly lost: 0 bytes in 0 blocks ==8066== still reachable: 0 bytes in 0 blocks ==8066== suppressed: 0 bytes in 0 blocks

p struct _data { int x; int *a; }; struct _data *p = NULL; p = calloc(1, sizeof(struct _data)); p->x = 1; p->a = calloc(3, sizeof(int)); .... free(p->a); p->a = NULL; free(p); p = NULL; p

x p a struct _data { int x; int *a; }; struct _data *p = NULL; struct _data { int x; int *a; }; struct _data *p = NULL; p = calloc(1, sizeof(struct _data)); p->x = 1; p->a = calloc(3, sizeof(int)); .... free(p->a); p->a = NULL; free(p); p = NULL; p

x p a 1 struct _data { int x; int *a; }; struct _data *p = NULL; p = calloc(1, sizeof(struct _data)); p->x = 1; p->a = calloc(3, sizeof(int)); .... free(p->a); p->a = NULL; free(p); p = NULL; 1 p a

x p a 1 struct _data { int x; int *a; }; struct _data *p = NULL; p = calloc(1, sizeof(struct _data)); p->x = 1; p->a = calloc(3, sizeof(int)); .... free(p->a); p->a = NULL; free(p); p = NULL; 1 p a

x p a 1 struct _data { int x; int *a; }; struct _data *p = NULL; p = calloc(1, sizeof(struct _data)); p->x = 1; p->a = calloc(3, sizeof(int)); .... free(p->a); p->a = NULL; free(p); p = NULL; 1 p a

x p a 1 struct _data { int x; int *a; }; struct _data *p = NULL; p = calloc(1, sizeof(struct _data)); p->x = 1; p->a = calloc(3, sizeof(int)); .... free(p->a); p->a = NULL; free(p); p = NULL; 1 p a

x p a 1 struct _data { int x; int *a; }; struct _data *p = NULL; p = calloc(1, sizeof(struct _data)); p->x = 1; p->a = calloc(3, sizeof(int)); .... free(p->a); p->a = NULL; free(p); p = NULL; p

p struct _data { int x; int *a; }; struct _data *p = NULL; p = calloc(1, sizeof(struct _data)); p->x = 1; p->a = calloc(3, sizeof(int)); .... free(p->a); p->a = NULL; free(p); p = NULL; p

Checkpoint Memoria estática: Se ubica en la pila. Liberada por el sistema operativo. Tiene tamaño limitado. TIPS: Consultar el tamaño máximo permitido de la pila usando “ulimit -s” En GDB se puede analizar la pila actual usando el comando “frame”. Memoria dinámica: Se ubica en el heap. En C es liberada por el programador. En otros lenguajes como Java es liberada por el garbage collector (ver wikipedia). No tiene límite (depende del SO). CALLOC ( <cantidad de bloques>, <tamaño de cada bloque>) Crea una secuencia contigua de bloques de memoria y devuelve un puntero al bloque inicial. Inicializa todo el bloque nuevo con 0 (a nivel bit). Si no hay memoria en el sistema devuelve NULL. Incluir librería estándar para tenerla disponible: #include <stdlib.h>

Checkpoint Dangling pointer (puntero colgante) Puntero apuntando a una zona de memoria que ya fue liberada. Intentar dereferenciar un puntero colgante puede resultar en un error de violación de segmento. free() sólo libera la memoria pero no modifica el puntero. Memory leak (fuga de memoria) Memoria del heap que nunca es liberada. Una causa de memory leak es cuando queda memoria “suelta” en el heap a la cuál no apunta ningún puntero. El programador no tiene forma de liberarla pues se ha perdido el acceso a ella. Los programas con memory leaks se vuelven lentos con el tiempo, ya que el heap se llena de bloques de memoria sin uso. Utilizar el comando valgrind para chequear fugas de memoria. Violación de segmento Dereferenciar (*p) un puntero NULL o colgante. Hacer free(p) donde p es colgante. Pasarse de rango en un arreglo, pues se accede a memoria inválida.

PARTE VI: Introducción a Listas Enlazadas

list struct _node { struct _node *next; int elem; }; typedef struct _node *list_t; La lista vacía [] es representada con un puntero nulo. list_t list = NULL;

list 4 3 9 3 struct _node { struct _node *next; int elem; }; 9 3 list struct _node { struct _node *next; int elem; }; typedef struct _node *list_t; La lista no vacía es representada como una “cadena” de nodos. En este ejemplo usaremos listas de enteros. [4, 3, 0, 9] 3

list 4 3 9 3 INSERCIÓN AL COMIENZO list_t aux = NULL; 9 3 list INSERCIÓN AL COMIENZO list_t aux = NULL; aux = calloc(1, sizeof(struct _node)); aux->elem = 7; aux->next = list; list = aux; 3

list aux 4 3 9 3 INSERCIÓN AL COMIENZO list_t aux = NULL; 9 3 list INSERCIÓN AL COMIENZO list_t aux = NULL; aux = calloc(1, sizeof(struct _node)); aux->elem = 7; aux->next = list; list = aux; 3 aux

list aux 4 3 9 3 INSERCIÓN AL COMIENZO list_t aux = NULL; 9 3 list INSERCIÓN AL COMIENZO list_t aux = NULL; aux = calloc(1, sizeof(struct _node)); aux->elem = 7; aux->next = list; list = aux; 3 aux

list aux 4 3 9 3 INSERCIÓN AL COMIENZO list_t aux = NULL; 9 3 list INSERCIÓN AL COMIENZO list_t aux = NULL; aux = calloc(1, sizeof(struct _node)); aux->elem = 7; aux->next = list; list = aux; 3 aux 7

list aux 4 3 9 3 INSERCIÓN AL COMIENZO list_t aux = NULL; 9 3 list INSERCIÓN AL COMIENZO list_t aux = NULL; aux = calloc(1, sizeof(struct _node)); aux->elem = 7; aux->next = list; list = aux; 7 3 aux

list aux 4 3 9 3 INSERCIÓN AL COMIENZO list_t aux = NULL; 9 3 list INSERCIÓN AL COMIENZO list_t aux = NULL; aux = calloc(1, sizeof(struct _node)); aux->elem = 7; aux->next = list; list = aux; 7 3 aux

4 3 9 3 list 7 3 [7,4,3,0,9]

list 4 3 9 3 INSERCIÓN AL ÚLTIMO (CASO LISTA NO VACÍA) 9 3 list INSERCIÓN AL ÚLTIMO (CASO LISTA NO VACÍA) list_t aux = NULL; aux = calloc(1, sizeof(struct _node)); aux->elem = 7; list_t curr = list; while (curr->next != NULL) { curr = curr->next; } curr->next = aux; 3

list aux 4 3 9 3 INSERCIÓN AL ÚLTIMO (CASO LISTA NO VACÍA) 9 3 list INSERCIÓN AL ÚLTIMO (CASO LISTA NO VACÍA) list_t aux = NULL; aux = calloc(1, sizeof(struct _node)); aux->elem = 7; list_t curr = list; while (curr->next != NULL) { curr = curr->next; } curr->next = aux; 3 aux

list aux 4 3 9 3 INSERCIÓN AL ÚLTIMO (CASO LISTA NO VACÍA) 9 3 list INSERCIÓN AL ÚLTIMO (CASO LISTA NO VACÍA) list_t aux = NULL; aux = calloc(1, sizeof(struct _node)); aux->elem = 7; list_t curr = list; while (curr->next != NULL) { curr = curr->next; } curr->next = aux; aux

list aux 4 3 9 3 INSERCIÓN AL ÚLTIMO (CASO LISTA NO VACÍA) 9 3 list INSERCIÓN AL ÚLTIMO (CASO LISTA NO VACÍA) list_t aux = NULL; aux = calloc(1, sizeof(struct _node)); aux->elem = 7; list_t curr = list; while (curr->next != NULL) { curr = curr->next; } curr->next = aux; aux 7

list curr aux 4 3 9 3 INSERCIÓN AL ÚLTIMO (CASO LISTA NO VACÍA) 9 3 list INSERCIÓN AL ÚLTIMO (CASO LISTA NO VACÍA) list_t aux = NULL; aux = calloc(1, sizeof(struct _node)); aux->elem = 7; list_t curr = list; while (curr->next != NULL) { curr = curr->next; } curr->next = aux; curr 7 aux

list curr aux 4 3 9 3 INSERCIÓN AL ÚLTIMO (CASO LISTA NO VACÍA) 9 3 list INSERCIÓN AL ÚLTIMO (CASO LISTA NO VACÍA) list_t aux = NULL; aux = calloc(1, sizeof(struct _node)); aux->elem = 7; list_t curr = list; while (curr->next != NULL) { curr = curr->next; } curr->next = aux; curr 7 aux

list curr aux 4 3 9 3 INSERCIÓN AL ÚLTIMO (CASO LISTA NO VACÍA) 9 3 list INSERCIÓN AL ÚLTIMO (CASO LISTA NO VACÍA) list_t aux = NULL; aux = calloc(1, sizeof(struct _node)); aux->elem = 7; list_t curr = list; while (curr->next != NULL) { curr = curr->next; } curr->next = aux; curr 7 aux

4 3 9 3 list 7 [4,3,0,9,7]

list 4 3 7 9 3 BORRAR UN NODO (CON ERRORES!) list_t curr = list; 7 9 3 list BORRAR UN NODO (CON ERRORES!) list_t curr = list; list_t prev = NULL; while (curr != NULL && curr->elem != 7) { prev = curr; curr = curr->next; } prev->next = curr->next; free(curr); curr = NULL; 3

list curr 4 3 7 9 3 BORRAR UN NODO (CON ERRORES!) list_t curr = list; 7 9 3 list BORRAR UN NODO (CON ERRORES!) list_t curr = list; list_t prev = NULL; while (curr != NULL && curr->elem != 7) { prev = curr; curr = curr->next; } prev->next = curr->next; free(curr); curr = NULL; curr 3

list prev curr 4 3 7 9 3 BORRAR UN NODO (CON ERRORES!) 7 9 3 list BORRAR UN NODO (CON ERRORES!) list_t curr = list; list_t prev = NULL; while (curr != NULL && curr->elem != 7) { prev = curr; curr = curr->next; } prev->next = curr->next; free(curr); curr = NULL; prev curr 3

list prev curr 4 3 7 9 3 BORRAR UN NODO (CON ERRORES!) 7 9 3 list BORRAR UN NODO (CON ERRORES!) list_t curr = list; list_t prev = NULL; while (curr != NULL && curr->elem != 7) { prev = curr; curr = curr->next; } prev->next = curr->next; free(curr); curr = NULL; prev curr 3

list prev curr 4 3 7 9 3 BORRAR UN NODO (CON ERRORES!) BORRAR UN NODO (CON ERRORES!) list_t curr = list; list_t prev = NULL; while (curr != NULL && curr->elem != 7) { prev = curr; curr = curr->next; } prev->next = curr->next; free(curr); curr = NULL; prev curr 3

list prev curr 4 3 7 9 3 BORRAR UN NODO (CON ERRORES!) BORRAR UN NODO (CON ERRORES!) list_t curr = list; list_t prev = NULL; while (curr != NULL && curr->elem != 7) { prev = curr; curr = curr->next; } prev->next = curr->next; free(curr); curr = NULL; prev curr 3

list prev curr 4 3 9 3 BORRAR UN NODO (CON ERRORES!) BORRAR UN NODO (CON ERRORES!) list_t curr = list; list_t prev = NULL; while (curr != NULL && curr->elem != 7) { prev = curr; curr = curr->next; } prev->next = curr->next; free(curr); curr = NULL; prev curr 3 Ejercicio: Arreglar el código. No funciona cuando: - La lista es vacía. - El “7” no está en la lista. - El “7” está en el primer nodo.

4 3 9 3 list 3 [4,3,0,9]

PARTE VII: Diccionario con Listas Enlazadas

dict 3 3 2 4 length length list next pair next next pair pair index data index data index data index data content content content content length content length content length 3 2 4

(to be continued...)