Descargar la presentación
La descarga está en progreso. Por favor, espere
1
Introducción a punteros en C
Algoritmos y Estructuras de Datos II (2015) Leonardo M. Rodríguez (presionar F5)
2
PARTE I: Uso básico de punteros
3
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
4
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
5
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
6
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
7
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
8
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
9
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
10
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
11
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
12
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”)
13
PARTE II: Pasaje de referencias
14
¿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?
15
x 4 int main (void) { int x = 4; mitad(x); printf(“%d\n”, x);
return 0; } void mitad(int y) { y = y / 2;
16
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
17
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
18
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
19
¿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?
20
x 4 int main (void) { int x = 4; mitad(&x); printf(“%d\n”, x);
return 0; } void mitad(int *y) { *y = *y / 2;
21
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
22
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
23
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
24
PARTE III: Punteros y arreglos
25
int a[4] = {1,3,8,6}; int *p = NULL; 1 3 8 6 a
26
int a[4] = {1,3,8,6}; int *p = NULL; p = a; 1 3 8 6 a p
27
int a[4] = {1,3,8,6}; int *p = NULL; p = a; *p = 5; 1 3 8 6 a p
28
a p int a[4] = {1,3,8,6}; int *p = NULL; p = a; *p = 5; *(p + 1) = 0;
29
a p int a[4] = {1,3,8,6}; int *p = NULL; p = a; *p = 5; *(p + 1) = 0;
8 6 a p
30
a p int a[4] = {1,3,8,6}; int *p = NULL; p = a; *p = 5; *(p + 1) = 0;
8 7 a p
31
a p int a[4] = {1,3,8,6}; int *p = NULL; p = a; *p = 5; *(p + 1) = 0;
3 7 a p
32
a p int a[4] = {1,3,8,6}; int *p = NULL; p = a; *p = 5; *(p + 1) = 0;
3 7 a p
33
a p int a[4] = {1,3,8,6}; int *p = NULL; p = a; *p = 5; *(p + 1) = 0;
2 7 a p
34
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”
35
PARTE IV: Punteros y estructuras
36
struct _punto { int x; Int y; }; struct _punto r; r.x = 0; x y r
37
x r y struct _punto { int x; Int y; }; struct _punto r; r.x = 0;
38
x r y struct _punto { int x; Int y; }; struct _punto r; 1 r.x = 0;
struct _punto *p = NULL; x y r 1
39
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
40
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
41
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
42
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
43
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
44
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
45
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;
46
PARTE V: Memoria Dinámica
47
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
48
HEAP STACK int main() { int *p = NULL; p = calloc(2, sizeof(int));
free(p); p = NULL; return (0); } HEAP STACK p
49
HEAP STACK int main() { int *p = NULL; p = calloc(2, sizeof(int));
free(p); p = NULL; return (0); } HEAP STACK p
50
HEAP STACK int main() { int *p = NULL; p = calloc(2, sizeof(int));
free(p); p = NULL; return (0); } HEAP STACK 2 p
51
HEAP STACK int main() { int *p = NULL; p = calloc(2, sizeof(int));
free(p); p = NULL; return (0); } HEAP STACK 2 DANGLING POINTER p
52
HEAP STACK int main() { int *p = NULL; p = calloc(2, sizeof(int));
free(p); p = NULL; return (0); } HEAP STACK p
53
HEAP STACK int main() { int *p = NULL; p = calloc(2, sizeof(int));
free(p); p = NULL; return (0); } HEAP STACK p
54
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
55
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
56
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
57
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
58
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
59
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
60
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
61
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
62
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
63
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
64
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
65
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
66
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
67
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
68
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
69
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
70
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
71
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
72
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
73
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
74
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
75
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
76
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
77
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
78
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>
79
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.
80
PARTE VI: Introducción a Listas Enlazadas
81
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;
82
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
83
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
84
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
85
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
86
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
87
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
88
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
89
4 3 9 3 list 7 3 [7,4,3,0,9]
90
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
91
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
92
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
93
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
94
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
95
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
96
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
97
4 3 9 3 list 7 [4,3,0,9,7]
98
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
99
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
100
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
101
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
102
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
103
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
104
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.
105
4 3 9 3 list 3 [4,3,0,9]
106
PARTE VII: Diccionario con Listas Enlazadas
107
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
108
(to be continued...)
Presentaciones similares
© 2024 SlidePlayer.es Inc.
All rights reserved.