Documente Academic
Documente Profesional
Documente Cultură
Captulo 2.
20-01-2010
Estructura
Arreglo
String
rboles
listas
grafos
20-01-2010
El vnculo es el elemento de datos de una componente que permite accesar a otra componente.
Una componente puede contener informacin de uno o ms vnculos.
El programador debe disponer de elementos del lenguaje que le permitan crear nuevos tipos de
datos, y mediante estos tipos crear funciones o mtodos que realicen operaciones sobre las
componentes.
Cuando el nmero mximo de componentes es conocido de antemano, las componentes pueden
modelarse como una serie de arreglos agrupados en una estructura. En la cual se emplea uno o
varios arreglos para establecer el o los vnculos entre las componentes. Se suele definir como
cursor a una variable que contiene el valor del ndice de una componente.
Otro mecanismo para establecer vnculos es el puntero, que es una variable que contiene la
direccin de otra componente. La vinculacin a travs de punteros suele emplearse
preferentemente en situaciones dinmicas, en las cuales el nmero de las componentes vara
durante la ejecucin del programa; esto debido a que se crean, insertan y descartan
componentes.
20-01-2010
Ejemplos de uso:
mostrar(A, 0, 4); imprime 0 1 2 3 4
mostrar(A+2, 0, 4); imprime 2 3 4 5 6
La manipulacin de arreglos no suele verificar el rango del ndice. En el caso de haberse
definido adyacentes los arreglos A y B, la referencia a A[12] est accesando efectivamente a
B[2], por eso se muestra un 12; pero es un error por acceso fuera de rango.
printf(" %d
printf(" %d
printf(" %d
printf(" %d
printf(" %d
arr[3][5]
arr[3]
20-01-2010
ar
(*pt[2])[5]
20-01-2010
20-01-2010
7
3
20-01-2010
8
//Definiciones de tipos
typedef struct fecha Fecha;
typedef Fecha * pFecha;
En este mbito, las definiciones de las instancias para las variables, quedan:
Fecha fecha3 = {1, 5, 2004}; //definicin e inicializacin.
pFecha pfecha3=&fecha3;
Observar que las definiciones no son precedidas por struct.
Es preciso crear mtodos para desplegar variables que son estructuras:
Se ilustra pasar el argumento como una estructura. Lo cual implica: crear el espacio y copiar la
estructura en el frame de la funcin:
void printfecha(Fecha f)
//paso por valor
{
printf(" Da = %d Mes = %d Ao = %d \n", f.dia, f.mes, f.agno); //lectura de campos
}
Es preferible pasar una referencia a la estructura, ya que esto ocupa menos espacio en el frame.
Slo es preciso copiar un puntero.
void printfecharef(pfecha p)
//paso por referencia.
{
printf(" Da = %d Mes = %d Ao = %d \n", p->dia, (*p).mes, p->agno);
}
Ejemplos de uso:
printfecha(fecha3);
printfecharef(pfecha3);
Tambin es til disponer de un constructor de la estructura.
Fecha setfecha (int dia, int mes, int agno)
//retorno de estructura
{
Fecha f;
f.dia=dia; f.mes=mes; f.agno= agno; //escritura en campos
return(f);
}
Ejemplo de uso:
fecha3 = setfecha(15, 6, 2005);
Tambin suele ser necesario desarrollar funciones para realizar operaciones de comparacin
entre estructuras. El siguiente prototipo ilustra un operador de comparacin mayor o igual
que, al cual se le pasan punteros a estructuras y devuelve un puntero a la estructura que es
mayor o igual que la otra, el diseo de la funcin se deja como tarea.
pFecha fechaGET(pFecha pf1, pFecha pf2);
20-01-2010
nodo2
nodo3
20-01-2010
10
ndice
Tabla
String0
0
1
2
.
B-1
String i
String j
String k
20-01-2010
11
Veremos que se pueden desarrollar algoritmos eficientes para buscar strings almacenados en la
tabla, cuando estudiemos tablas de hash.
2.5.2. Arreglo de estructuras.
El siguiente ejemplo de diseo de una estructura de datos, contempla un arreglo en el cual se
califica el estado de cada celda. Suponemos que se almacena un entero, y para describir
lgicamente el estado empleamos la definicin de un tipo enumerativo, que permite el mapeo de
nombres lgicos con enteros. Internamente se emplean enteros, pero el programador puede
referirse a ellos mediante sus nombres equivalentes.
typedef enum {vacio, ocupado, descartado} state;
typedef struct hcelda
{ int clave;
state estado;
} celda;
#define B 10 /* 10 celdas */
static celda hashtab[B]; /*arreglo de celdas */
static int ocupados;
//ocupados de la tabla
El programador puede escribir expresiones en trminos del tipo enumerativo:
(hashtab[i].estado != vacio && hashtab[i].estado != descartado)
2.5.3. Multirboles.
La descripcin de un nodo que pueda tener un nmero variable de punteros que apunten a sus
descendientes no es prctica. Ya que esto implica almacenar los vnculos en un arreglo, y si es
arreglo debe tener un tamao fijo. El cual debe escogerse considerando el mximo nmero de
descendientes que soportar la estructura; mal empleando los recursos en el caso de un nodo sin
hijos, o de nodos con un pequeo nmero de descendientes. Adems siempre estar el riesgo de
que aparezca un nodo con mayor nmero de descendientes que el tamao mximo escogido.
1
2
5
3
6
4
9
10
11
20-01-2010
12
13
12
El esquema anterior ilustra los vnculos. Este ejemplo refuerza el concepto que un vnculo puede
ser un cursor o un puntero.
El nmero variable de los vnculos asociados a un nodo pueden reemplazarse por slo dos
vnculos: uno que relaciona el nodo con el primer descendiente izquierdo, y otro que vincula a
cada nodo con su hermano derecho. Ntese que en cada nivel puede observarse una lista de
nodos que parte del nodo ubicado ms a la izquierda y termina en un vnculo nulo despus del
ltimo descendiente de un nodo.
20-01-2010
13
20-01-2010
14
1
4
2
5
10
11
12
20-01-2010
15
Problemas resueltos.
P2.1. Se tiene el siguiente programa:
#include <stdlib.h>
#include <stdio.h>
#define MAX 5
typedef struct nn
{ int i1;
int i2;
struct nn * next;
} nodo, * pnodo;
pnodo lista1=NULL;
pnodo lista2=NULL;
pnodo getnodo(void)
{ pnodo p;
if( (p=(pnodo)malloc(sizeof(nodo)))==NULL) return(NULL); else return(p);
}
void Push(pnodo *ref, int dato1, int dato2)
{ pnodo newnodo;
if ( (newnodo=getnodo( )) == NULL) exit(1);
newnodo->i1 = dato1; newnodo->i2 = dato2; newnodo->next = *ref;
Profesor Leopoldo Silva Bijit
20-01-2010
16
*ref = newnodo;
}
void crealista(void)
{ int i;
for(i=0; i<MAX; i++)
{ Push(&lista1, i, i+1); Push(&lista2, MAX-i, i-1); }
}
pnodo busca(pnodo pp)
{ pnodo qq=NULL;
while (pp !=NULL) {qq = pp; pp = pp->next;}
return (qq);
}
pnodo busca2(pnodo p, int j, pnodo q)
{
if(p !=NULL)
{ while( p->i1 != j ) p = p->next;
if (p != NULL)
while (q !=NULL) { if(p->i2 == q->i1) return(q); q = q->next; }
return (NULL);
}
return(NULL);
}
int main(void)
{ pnodo tt;
crealista();
printf(" %d \n", ( *(busca(lista1)) ).i1);
printf(" %d \n", busca(lista2)->i2);
if( (tt=busca2(lista1, 3, lista2)) !=NULL) printf(" %d \n", tt->i2);
return(0);
}
a) Explicar, empleando un diagrama, el paso por referencia de Push.
b) Diagrama de la estructura despus de ejecutar crealista();
c) Explicar accin realizada por busca.
d) Explicar accin realizada por busca2.
e) Determinar qu imprime el programa.
Solucin.
a) En la funcin crealista, se tiene un ejemplo de uso de Push.
Consideremos el llamado: Push(&lista1, 0, 1).
En la definicin de Push, el primer argumento es un puntero a puntero a nodo.
Profesor Leopoldo Silva Bijit
20-01-2010
17
Stack
Lista1
newnodo
ref
dato1 = 0
dato2 = 1
Figura P2.1.
Ntese que los argumentos son variables almacenadas en el stack, iniciadas con los valores de
los parmetros de la invocacin. La variable local newnodo, al no estar inicializada en su
definicin apunta a cualquier lado. Razn por la cual, conviene definirlas e inicializarlas
simultneamente.
Despus de un llamado exitoso a getnodo(); es decir, malloc asign una estructura en el heap, un
diagrama de la situacin es el siguiente:
Datos
Stack
heap
Lista1
newnodo
i1 = ?
ref
i2 = ?
dato1 = 0
next = ?
dato2 = 1
Figura P2.2.
El resto de la funcin, escribe en los campos de la estructura creada en el heap. Y adems, en
ltimo trmino, sobreescribe en la variable global lista1(en el ejemplo que se analiza).
20-01-2010
18
Datos
Stack
heap
Lista1
newnodo
i1 = 0
ref
i2 = 1
dato1 = 0
next
dato2 = 1
Figura P2.3
Al salir de Push, desaparecen las variables automticas, ubicadas en el stack, y la situacin
queda:
Datos
Stack
heap
Lista1
i1 = 0
i2 = 1
next
Figura P2.4
Si se hubiera pasado solamente un puntero a nodo como referencia, se tendra el diseo:
20-01-2010
19
Lista2
heap
i1=4
i1 = 3
i1 = 2
i1 = 1
i1 = 0
i2 = 5
i2 = 4
i2 = 3
i2 = 2
i2 = 1
next
next
next
next
next
i1 =1
i1 = 2
i1 = 3
i1 = 4
i1 = 5
i2 = 3
i2 = 2
i2 = 1
i2 = 0
next
next
next
next
i2 = -1
next
Figura P2.5.
c) A la funcin busca, se le pasa la direccin del primer nodo de la lista. Si la lista es vaca,
retorna un puntero nulo. Si no es vaca, con pp recorre la lista, dejando qq apuntado al nodo
corriente y con pp al prximo. Cuando se llega con pp, al final de la lista, qq apunta al ltimo
nodo de la lista.
d) La funcin busca2 intenta encontrar el valor j en el campo i1 del nodo apuntado por el
argumento p. Si la lista es vaca retorna un puntero nulo; en caso de encontrar el valor j, busca a
partir del nodo apuntado por q, el valor del campo i1 que sea igual al valor del campo i2 del
nodo donde qued apuntando p.
Si lo encuentra, retorna un puntero al nodo que cumple la condicin anterior; en caso contrario,
retorna un puntero nulo.
La invocacin: busca2(lista1, 3, lista2), despus del primer while, deja p apuntando al segundo
nodo de la lista1, el segundo while deja q apuntando al cuarto nodo de la lista2; ya que busca en
sta el valor 4 en el campo i1.
El diseo de la funcin incurre en un error frecuente, en este tipo de problemas. Qu ocurre si
el valor j no se encuentra en ningn campo i1 de la lista apuntada por p?.
Cuando p tome valor nulo, intentar leer p->i1 en las primeras direcciones de memoria, las
cuales suelen pertenecer a un segmento del sistema operativo. Lo ms seguro que la ejecucin
del proceso aborte debido a un error de segmentacin.
Se podra corregir, cambiando:
while( p->i1 != j ) p = p->next;
por:
20-01-2010
20
20-01-2010
21
20-01-2010
22
clave
p1
p2
p3
20-01-2010
23
pn=creanodo(5);
pn->p3=pn;
pn->p1=creanodo(3);
pn->p1->p3=pn;
pn->p2=creanodo(8);
pn->p2->p3=pn->p1;
4
p1
6
p2
p3
p1
p2
p3
Figura P2.6.
Solucin.
a)
typedef struct moldenodo
{ int clave;
struct moldenodo *p1;
struct moldenodo *p2;
struct moldenodo *p3;
} nodo , *pnodo;
b)
pnodo creanodo(int clave)
{ pnodo p;
if ((p = (pnodo) malloc(sizeof(nodo))) == NULL) {
printf ("Memoria insuficiente para crear nodo\n");
exit(1);
}
p->clave=clave;p->p2=NULL;p->p1=NULL;p->p3=NULL;
return(p);
}
c) Los diagramas se ilustran despus de ejecutada la instruccin.
Profesor Leopoldo Silva Bijit
20-01-2010
24
Figura P2.7.
pn->p3=pn;
pn
5
Figura P2.8.
pn->p1=creanodo(3);
pn
5
Figura P2.9.
pn->p1->p3=pn;
pn
5
Figura P2.10.
20-01-2010
25
pn->p2=creanodo(8);
pn
5
Figura P2.11.
pn->p2->p3=pn->p1;
pn
5
Figura P2.12.
c)
pn= creanodo(6); pn->p2=pn; pn->p3=pn;
pn->p1=creanodo(4); pn->p1->p1=pn->p1;
pn->p1->p3=pn; pn->p1->p2=pn;
20-01-2010
26
pn
4
p1
6
p2
p3
p1
p2
p3
Figura P2.13.
P2.6. Se tiene el siguiente programa.
#include <stdlib.h>
typedef struct nn
{ int x;
struct nn * p;
struct nn * q;
int y;
} t, *pt;
t w, z;
pt px=&w;
void main(void)
{ px->p=&z;
w.q = px->p;
px->q->q=px;
z.p = w.p;
w.x = z.x = 2;
(*px).y = 8;
(*(w.q)).y =9;
px=(pt) malloc(sizeof(t));
px->p=px->q = (pt ) 0;
px->x=px->y=12;
}
Efectuar un diagrama de los datos despus de ejecutar las instrucciones de main.
Solucin.
Profesor Leopoldo Silva Bijit
20-01-2010
27
px
w
z
x
p
p
q
Figura P2.13.
px
w
x
p
px->p =&z
w.q=px->p;
z
x
p
Figura P2.14.
20-01-2010
28
px
w
x
p
px->q->q=px
z
x
z.p=w.p
Figura P2.15.
px
w
x
w.x=z.x=2
(*px).y=8;
z
x 2
p
(*(w.q)).y=9
y
Figura P2.16.
20-01-2010
29
px
px =(pt)malloc(sizeof(t));
w
x
p
x
12
p
y
q
8
q
z
12
x 2
px ->p=px->q=(pt)0;
p
y
q
9
px ->x=px->y=12;
Figura P2.17.
Ejercicios propuestos.
E1. Determinar qu imprimen los siguientes segmentos:
a ) printf(\n%o %x %d, 17, 017, 0x17) ;
b) n = 3 ; printf(-05d %5d, n, n) ;
c) x = 1234E-2 ; printf(%6.3f, x) ;
d) j =2; if ( ( '1' -1 ) == --j ) printf("verdad"); else printf("falso");
E2. Colocar parntesis y evaluar las expresiones siguientes:
Si es preciso puede indicar los resultados de expresiones intermedias.
a) a != b && c + 1 == ! c + 2
con a1) a=2 ; b=3 ; c = 1;
a2) a=3 ; b=2 ; c=2 ;
b) 1 + 2 * ( n += 8) / 4
con n=3 ;
c) a < b ? a < b ? a+1 : a+2 : a+3 con a=2 ; b= 3 ;
20-01-2010
30
20-01-2010
31
20-01-2010
32
{ int k, m =1;
k = f1(m,5); printf(%d \n %d , k, m);
k = 2; m = 3;
m= f2(&m, m); printf(%d \n, m );
k = 4; m = 6;
k = f1( m, f1(m,3)+5 ); printf(%d \n %d \n, k, m);
}
int f1(int&i , int j)
{ j = j+i ; i = i+j; return(i+j); }
int f2(int *i, int j)
{ *i = j+2+*i; return(j+*i); }
E9. Indicar qu escribe el programa.
#include <stdio.h>
struct punto{
int x;
int y;
};
struct molde{
int a[2];
char c;
punto p; };
void main()
{
molde m1={{2,4},'p',{3,5}}, m2={{5,6},'q',{7,1}};
molde *pm=&m2;
int *pi=&(m1.p.y);
printf(%d \n, *pi ) ;
printf(%d \n, cout << m2.a[1] + m1.p.x );
printf(%d \n, pm->a[1] + pm->p.x );
printf(%d \n , *(pi-1)) ;
pi = &m2.a[0];
printf(%d \n , *(pi+1));
}
E10. Determinar la salida.
#include <stdio.h>
int f2(int x, int y, int z)
{int i;
for(i=0; i<x; i++) y+=z;
Profesor Leopoldo Silva Bijit
20-01-2010
33
return(y);
}
int main(void)
{
printf("%d ", f2(5, 3, 2));
return(0);
}
E11. Determinar la salida.
#include <stdio.h>
int arr[10];
void f1(int x, int *y)
{ int i;
for(i=0; i<x; i++) *(y+i) = i;
}
void f2(int x, int *y)
{ int i;
for(i=0; i<x; i++) printf("%d, ", *(y+i));
putchar('\n');
}
int main(void)
{
f1(5, arr); f2(5, arr);
return(0);
}
E12. Determinar la salida.
#include <stdio.h>
int arr[10];
int *pi;
#define NULL ( (char *) 0)
void f1(int x, int *y)
{int i;
for(i=0; i<x; i++) *(y+i)=i;
}
int *f2(int x, int *y, int z)
{ int i;
for(i=0; i<x; i++) if(*(y+i)== z ) return(y+i);
return((int *) NULL);
}
Profesor Leopoldo Silva Bijit
20-01-2010
34
int main(void)
{
f1(5, arr); pi=f2(5, arr, 8);
if(pi!=((int *) NULL)) printf("%d ", *pi); else printf("no se encuentra\n");
return(0);
}
#include <stdio.h>
E13. Explicar que realizan las funciones.
void prtlong(unsigned long int i)
{ int j; unsigned long int k; k=1L;
for (j=31; j>=0; j--) if((k<<j)&i) putchar(1); else putchar(0);
}
void prtint(int i)
{ int j, k=1;
for (j=15; j>=0; j--) if( (k<<j)&i ) putchar(1); else putchar(0);
}
void sp(int i) { int j; for(j=i; j>0;j--) putchar( ); }
void lrs(int *p, int *q)
{
int k,m;
k=(*p)&0x0001; m=(*p)&0x8000;
(*p)>>=1; if(m) *p=(*p)&0x7fff;
(*q)>>=1; if(k) *q=(*q)|0x8000;else *q=(*q)&0x7fff;
}
void ars(int *p, int *q)
{ int k,m;
extern int s;
k=(*p)&0x0001; m=(*q)&0x0001;
(*p)>>=1;(*q)>>=1;if(k) *q=(*q)|0x8000; else *q=(*q)&0x7fff; s=m;
}
E14. Describir un multirbol
Mediante un arreglo de listas de los hijos de cada nodo. El arreglo debe tener una entrada por
cada nodo, adems considerar que la raz pueda se cualquier nodo.
20-01-2010
35
ndice general.
CAPTULO 2. ............................................................................................................................................ 1
DEFINICIN DE ESTRUCTURAS DE DATOS EN C......................................................................... 1
2.1. TIPOS PRIMITIVOS. ............................................................................................................................. 1
2.2. MECANISMOS DE ESTRUCTURACIN. ................................................................................................. 1
2.2.1. Grupos bsicos. ......................................................................................................................... 1
2.2.2. Vnculos. .................................................................................................................................... 2
2.3. EJEMPLOS BASADOS EN ARREGLOS. ................................................................................................... 3
2.3.1. Acceso a componentes del arreglo. ........................................................................................... 3
Definicin de matrices. .................................................................................................................................... 4
Definicin de arreglo de arreglos. .................................................................................................................... 5
Arreglo de punteros a renglones. ..................................................................................................................... 5
Arreglo de punteros a caracteres. ..................................................................................................................... 6
20-01-2010
36
ndice de figuras.
FIGURA 2.1. AGRUPACIONES DE DATOS. ........................................................................................................2
FIGURA 2.2. VNCULOS ENTRE COMPONENTES DE DATOS. ............................................................................2
FIGURA 2.2.A. MATRIZ DE CARACTERES ......................................................................................................4
FIGURA 2.2.B. ARREGLO DE PUNTEROS A ARREGLOS DE CARACTERES ........................................................5
FIGURA 2.3. LISTA SIMPLEMENTE ENLAZADA................................................................................................7
FIGURA 2.4. LISTA SIMPLEMENTE ENLAZADA, MEDIANTE PUNTEROS. ...........................................................9
FIGURA 2.5. ARREGLO DE LISTAS. ...............................................................................................................10
FIGURA 2.6. MULTIRBOL. ..........................................................................................................................11
FIGURA 2.7. PRIMER DESCENDIENTE IZQUIERDO, HERMANO DERECHO. .......................................................12
FIGURA 2.8. MULTIRBOL MEDIANTE ARREGLO DE CURSORES. ..................................................................13
FIGURA 2.9. MULTIRBOL MEDIANTE ARREGLO DE PADRES........................................................................14
FIGURA 2.10 ARREGLO DE PADRES. .............................................................................................................14
FIGURA P2.1. ...............................................................................................................................................17
FIGURA P2.2. ...............................................................................................................................................17
FIGURA P2.3 ................................................................................................................................................18
FIGURA P2.4 ................................................................................................................................................18
FIGURA P2.5. ...............................................................................................................................................19
FIGURA P2.6. ...............................................................................................................................................23
FIGURA P2.7. ...............................................................................................................................................24
FIGURA P2.8. ...............................................................................................................................................24
FIGURA P2.9. ...............................................................................................................................................24
FIGURA P2.10. .............................................................................................................................................24
FIGURA P2.11. .............................................................................................................................................25
FIGURA P2.12. .............................................................................................................................................25
FIGURA P2.13. .............................................................................................................................................26
FIGURA P2.13. .............................................................................................................................................27
FIGURA P2.14. .............................................................................................................................................27
FIGURA P2.15. .............................................................................................................................................28
FIGURA P2.16. .............................................................................................................................................28
FIGURA P2.17. .............................................................................................................................................29
20-01-2010