Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Manual de Estructura de Datos PDF
Manual de Estructura de Datos PDF
2. Ordenamientos y bsquedas
Arreglos
Ordenamiento
Burbuja y Burbuja Mejorado (Bubble Sort)
Ordenamiento por Insercin Directa (InsertSort)
Ordenamiento por seleccin (SelectSort)
Ordenamiento Shell (ShellSort)
Ordenamiento Mezcla (MergeSort)
Bsquedas
Bsqueda Secuencial
Bsqueda Binaria
Pag 1
Pilas
Colas
6. Grafos.
Tipos de datos.
Los diferentes objetos de informacin con los que un programa C trabaja se conocen
colectivamente como datos. Todos los datos tienen un tipo asociado con ellos
El tipo de un dato determina la naturaleza del conjunto de valores que puede tomar una variable.
Tipos predefinidos
Tipo Largo Rango
unsigned char 8 bits 0 to 255
Char 8 bits -128 to 127
enum 16 bits -32,768 to 32,767
unsigned int 16 bits 0 to 65,535
short int 16 bits -32,768 to 32,767
int 16 bits -32,768 to 32,767
unsigned long 32 bits 0 to 4,294,967,295
long 32 bits -2,147,483,648 to 2,147,483,647
float 32 bits 3.4 * (10**-38) to 3.4 * (10**+38)
double 64 bits 1.7 * (10**-308) to 1.7 * (10**+308)
long double 80 bits 3.4 * (10**-4932) to 1.1 * (10**+4932)
Constantes
Las constantes se presentan en expresiones como
c= Y
2* (x + 7) 33
kilmetros = 1.609344 * millas
Adems de tener un valor, una constante tambin tiene un tipo de dato inherente. Los tipos de
datos posibles en las constantes dependen de la mquina. Lo normal es que no existan constantes
de los tipos short, unsigned y float. Aunque esto puede ser distinto en mquinas pequeas, se
supondr que la situacin normal prevalece.
Pag 2
El tipo de dato asociado a una constante depende de la forma en que sta se escribe. La siguiente
lista contiene todos los tipos de datos que admiten constantes, asi como algunos ejemplos:
int 0 77 5013
long 0L 77L 5013L
double 0.003 1.0|| 0.5013e-2
char a b c
cadena est es una constante de cadena
Una expresin constante slo contiene constantes, y el compilador C las evaluar en el momento
de la compilacin, en lugar de hacerlo en la ejecucin. Por ejemplo, en la proposicin:
Segundos = 60 * 60 * 24 * das;
Segundos = 86400 * das;
se encuentran en un archivo que se est compilando el preprocesador cambia primero todos los
identificadores LIMITE por 100 y todos los PI por 3.14159, excepto los que estn en cadenas entre
comillas. Una lnea #define puede estar en cualquier lugar del programa, pero debe empezar en la
columna 1 y solo tendr efecto en las lneas de archivo que le sigue. El preprocesador solo
cambiar los identificadores que se escriben con maysculas.
Si en un programa hay una lnea como:
#include mi_archivo
Se trata tambin de una orden al procesador. Una linea #include puede presentarse en cualquier
parte de un archivo, pero debe empezar en la columna uno. Las comillas que encierran el nombre
de archivo son necesarias. El efecto de esta lnea es incluir en ese punto de la codificacin una
copia del contenido del archivo mi_archivo
Cadena_de_control y lista_de_argumentos
printf(ABC);
printf(%s,ABC);
Pag 3
El formato %s hace que el argumento ABC se imprima en el formato de una cadena de
caracteres. Esto mismo puede realizarse tambin con la proposicin:
printf(%c%c%c,A,B,C);
Los apstrofos que encierran cada letra se emplean para designar constantes de caracteres de
acuerdo con esto, A es la constante de carcter que corresponde a la letra A mayscula. El
formato %c imprime el valor de una expresin como un carcter.
printf()
Carcter
de
conversi Cmo se describe el argumento correspondiente
n
C Como carcter
D Como un entero decimal
E Como nmero de punto flotante en notacin
cientfica
F Como un nmero de punto flotante
G En el formato-e o el formato-f el que sea ms corto
S Como una cadena de caracteres
La funcin scanf() es anloga a la funcin printf(), pero se usa para la entrada. Su primer
argumento es una cadena de control con formatos que corresponden a las diferentes formas en
que pueden interpretarse los caracteres de la entrada como valores para los diferentes tipos de
variables. La lista de argumentos est formada por direcciones de variables. El smbolo &
representa el operador de direccin; por ejemplo, la proposicin
scanf(%d,&x);
Contiene el formato %d, el cual provoca que scanf() interprete los caracteres de entrada como
un entero decimal y que coloque el valor en la direccin x.
Carcter
de
conversi Los caracteres de la entrada se convierten en
n
c Un carcter
d Un entero decimal
f Un nmero de punto flotante (float)
lf Un nmero de punto flotante (double)
s Una cadena
Funciones
La definicin de una funcin consiste en un encabezamiento y un cuerpo. De manera explicita,
podramos decir que es un bloque o una proposicin compuesta. Si hay declaraciones deben
aparecer al inicio del bloque antes de cualquier proposicin ejecutable. El encabezamiento puede
ser tan slo un identificador y unos parntesis. Un ejemplo sencillo es :
escr_direcc() /* encabezamiento*/
/* el cuerpo es cuanto est entre llaves */
{
Pag 4
printf(\n\n%s\n%s\n%s\n%s\n%s\n\n,
********************,
** SAN NICOLAS *,
** El POLO NORTE *,
** LA TIERRA *,
*******************);
}
Donde quiera que un programa identifique a esta funcin, la expresin har que se invoque la
funcin.
Una definicin de funcin tiene un nombre y unos parntesis que contienen cero o ms
parmetros y un cuerpo. Para cada parmetro debe de haber una declaracin correspondiente
antes del cuerpo, cualquier parmetro que no se declar se considera un int por omisin, a estos
parmetros se les llama parmetros formales de funcin. El cuerpo de la funcin es un bloque o
una proposicin compuesta, y tambin puede contener declaraciones, todas las variables
declaradas en el cuerpo de una funcin se dice que son variables locales. Otras variables no
declaradas ni como argumentos ni en el cuerpo de la funcin se consideran como globales a la
funcin y deben definirse en forma externa.
La proposicin return
La proposicin return puede incluir u omitir una expresin.
return;
return (377);
return (a * b);
return (++x);
return ++x;
Las funciones se invocan al escribir su nombre y una lista adecuada de argumentos entre
parntesis. Todos los argumentos pasan con una llamada por valor. Se evala cada argumento y
su valor se utiliza de forma local en lugar del parmetro formal.
Para indicar que un parmetro de funcin es pasado por referencia, slo coloque ampersand (&)
despus del tipo del parmetro en el prototipo de funcin.
Pag 5
int ordena(int &lista)
Estructura de un programa
La base de la programacin en C es la funcin, pues constituye una parte fundamental de la
codificacin en el proceso de solucin de problemas. Todas las funciones estn en el mismo nivel
externo; no se pueden anidar unas en otras. Un programa contiene una o ms funciones en uno o
ms archivos. Una de las funciones es main() donde se inicia la ejecucin del programa. El resto
de las funciones se llaman desde main() y desde el interior de otras
main()
Todo programa tiene una funcin main donde inicia la ejecucin; los parntesis que van
despus de main indican al compilador que se trata de una funcin
{
Las llaves encierran al cuerpo de la funcin; tambin se usan para agrupar varias
proposiciones.
printf()
El sistema contiene una biblioteca estndar con funciones que pueden usarse en
programas; est es una funcin de la biblioteca estndar que imprime en pantalla.
En C una constante de cadena es una serie de caracteres entre comillas. Esta cadena es un
argumento de la funcin printf() y controla lo que se escribir los dos caracteres \n al final
de esta cadena representan un carcter sencillo llamado nuevalnea; ste es un carcter
que no se imprime, su efecto es hacer que el cursor avance hacia una lnea nueva.
}
La llave derecha hace pareja con la llave de una funcin y da por terminada la funcin main
Pag 6
Identificadores.
Los identificadores representan objetos de un programa ( constantes, variables, tipos de datos
procedimientos, funciones, unidades, programas y campos de registros). Un identificador es una
secuencia de caracteres que pueden ser de cualquier longitud, pero slo los primeros 63
caracteres son significativos.
Palabras reservadas.
Las palabras reservadas en C tienen un significado especial y no se pueden utilizar para otros
propositos
Operadores aritmticos
Los operadores aritmticos (+,-,*) pueden ser utilizados con tipos enteros o reales, si ambos son
enteros el resultado es entero si uno es real el resultado es real.
2+3 =5
2 +3.0 = 5.0
2.0 + 3 = 5.0
2.0 + 3.0 = 5.0
Operadores de asignacin
+= C += 7 c = c +7
-= D -= 4 d=d-4
*= e*=5 e = e* 5
/= F /= 3 f=f/3
%= g %= 9 g=g%9
Prioridad de operadores
Cuando una expresin aritmtica se evala, el resultado es siempre un nmero. Cuando en una
expresin aparecen dos o ms operadores, qu operacin se realiza primero?.
Reglas de evaluacin de expresiones.
1. Todas las subexpresiones entre parntesis se evalan primero. Las subexpresiones con
parntesis anidados se evalan de dentro a afuera; el parntesis ms interno se evala
primero.
2. Prioridad de operaciones. Dentro de una misma expresin o subexpresin, los
operadores se evalan en el siguiente orden:
*,/,% primero
+,- ltimo
3. Regla asociativa izquierda. Los operadores en una misma expresin o subexpresin con
igual nivel de prioridad (tal como * y /) se evalan de izquierda a derecha.
%
*
Pag 8
Escritura de formulas matemticas en C.
En C las formulas matemticas se deben escribir en formato lineal. Esto obliga al uso frecuente de
parntesis que indiquen el orden de evaluacin correcto de los operadores.
Operadores de relacin
Se utilizan para expresar condiciones y describen una relacin entre dos valores.
Los operadores de relacin se utilizan en condiciones cuyo formato tiene una de las siguientes
formas:
Expresin valor
6.7315 < 6.7342 0
-124.2 < 0.003 1
8 == 8.0 1
A < B 1
Z < H 1
Operadores lgicos
Las expresiones lgicas pueden combinarse para formar expresiones ms complejas utilizando los
operadores lgicos: &&, || y !. Estos operadores se utilizan con constantes lgicas de forma
similar al modo en que los operadores aritmticos se utilizan con las constantes numricas, estos
operadores trabajan con operandos que son expresiones lgicas.
Pag 9
Operador Prioridad
! Mas alta (se evala primero)
*,/,%,&& -
+,-,|| -
< , <= , == , <> , >= , > Mas baja se evala al ultimo
Si existen parntesis las expresiones de Interior se evalan primero
su
* - -
||
&&
Pag 10
Operador &&
1 1 1
1 0 0
0 1 0
0 0 0
Operador ||
Operando1 Operando2 Operando1 || Operando2
1 1 1
1 0 1
0 1 1
0 0 0
Operador !
Operando1 ! Operando1
1 0
Pag 11
Estructuras de control
Selectivas.
La sentencia if.
Sentencia de control que dirige a la computadora para ejecutar una sentencia si la expresin es
verdadera, y otra en caso de ser falsa.
Formato
if (expresin lgica)
proposicion1
else
proposicin2
proposicin siguiente
En muchos casos se desea que una determinada accin slo ejecute si una cierta condicin es
verdadera y no realizar ninguna accin si la condicin es falsa.
if (condicin)
sentencia
Sentencia compuesta.
{
sentencia 1;
sentencia 2;
sentencia 3;
-
-
sentencia n;
}
Ejemplo:
#include <stdio.h>
main()
{
if (grado >=90)
Printf(A\n);
else if (grado >=80)
Printf(B\n);
else if (grado >=70)
Printf(C\n);
else if (grado >=60)
Printf(D\n);
else if (grado >=50)
Printf(F\n);
}
La sentencia switch
La sentencia switch se utiliza para elegir entre diferentes alternativas.
Pag 12
switch (expresion_entera){
case 1 : sentencia1;break;
case 2 : sentencia2;break;
case 3 : sentencia3;break;
-
-
case n : sentencian;break;
[default :sentencia x]
} {case}
El siguiente ejemplo utiliza switch para contar el nmero de cada distinta letra de calificacin
que los estudiantes alcanzarn en un examen.
/*Contando calificaciones*/
#include <stdio.h>
main()
{
int Letra;
int acontador = 0, bcontador =0, contador = 0,
dcontador =0, fcontador = 0;
Pag 13
printf(D: %d\n, dcontador);
printf(F: %d\n, fcontador);
return 0;
}
Mete la letra de su c
Mete el carcer EOF para finalizar las entradas
A
B
C
C
A
D
F
C
E
Letra de entrada incorrecta meta una nueva calificacin
D
A
B
Totales de cada calificacin
A: 3
B: 2
C: 3
D: 2
F: 1
La sentencia while.
La estructura repetitiva while (mientras) es aquella en la que el nmero de iteraciones no se
conoce por anticipado y el cuerpo del bucle se repite mientras se cumple una determinada
condicin.
1. La condicin (expresin lgica) se evala antes y despus de cada ejecucin del bucle. Si
la condicin es verdadera se ejecuta el bucle y si es falsa el control pasa a la sentencia
siguiente al bucle.
2. Si la condicin se evala falso cuando se ejecuta el bucle por primera vez el cuerpo del
bucle no se ejecutar nunca.
3. Mientras la condicin sea verdadera el bucle se ejecutar, esto significa que el bucle se
ejecutar indefinidamente a menos que algo en el interior del bucle modifique la condicin
haciendo que su valor pase a falso.
Pag 14
Ejemplo: El promedio de la clase es igual a la suma de calificaciones dividida por el nmero de
alumnos. El algoritmo para resolver este problema en una computadora, debe introducir cada una
de las calificaciones, ejecutar el clculo de promedio e imprimir el resultado.
#include <stdio.h>
main()
{
int, contador, grado, total, promedio;
total = 0; /*inicializacion*/
counter = 1;
/*procesamiento*/
while (counter <=10) {
printf (Mete grado:);
scanf(%d,&grado);
total = total +grado;
counter++;
}
promedio = total / 10;
printf(El promedio de la clase es %d\n, promdio);
return 0;
}
La sentencia do while.
Una variante de la sentencia while es la sentencia do while, esta sentencia especifica un bucle
condicional que se repite hasta que la condicin se hace falsa.
do
Sentencia 1
-
-
-
sentencia n
while (expresin lgica);
1. La condicin se evala al final del bucle, despus de ejecutarse todas las sentencias
2. Si la expresin lgica es verdadera, se vuelve a repetir el bucle y se ejecutan todas las
sentencias.
3. Si la expresin lgica es verdadera, se sale del bucle y se ejecuta la siguiente sentencia a
while.
4. La sintaxis no requiere {}.
El siguiente ejemplo utiliza una estructura do while para imprimir los nmeros del 1 al 10.
#include <stdio.h>
main()
{
int contador = 1;
do {
printf (%d , contador);
}
while (++contador <= 10);
return 0;
}
Pag 15
La sentencia for.
Esta sentencia requiere que sepamos por anticipado el nmero de veces que se ejecutan las
sentencias del interior del bucle.
#include <stdio.h>
main()
{
int contador;
/*inicializacin, condicin de repeticin, e incremento*/
for (contador=1; contador <=10; contador++)
printf(%d\n,contador);
return 0;
}
ejemplo utillizando la estructura for
main()
{
int sum = 0, number;
for (number = 2; number <=100; number +=2)
sum += number;
printf(Sum es %d\n,sum);
return 0;
}
Sum es 2550
Pag 16
Ordenamientos y bsquedas
Arreglos
Un arreglo es una estructura de datos en la que se almacena una coleccin de datos del mismo
tipo, es una lista de un nmero finito n de elementos del mismo tipo que se caracteriza por:
1. Almacenar los elementos del arreglo en memoria continua.
2. Tener un nico nombre de variable que representa todos los elementos y estos a sus vez
se diferencian por un ndice o subndice.
3. Acceso directo o aleatorio a los elementos individuales del arreglo.
Para referirse a una posicin en particular o elemento dentro del arreglo, especificamos el nombre
del arreglo y el nmero de posicin del elemento particular dentro del mismo.
float x[8];
El nmero de posicin que aparece dentro de los corchetes se conoce ms formalmente como
subndice. Un subndice debe de ser un entero o una expresin entera. Si un programa utiliza una
expresin como subndice, entonces la expresin se evala para determinar el subndice. Por
ejemplo, si a = 3 y b = 4, entonces el enunciado
C[a + b] +=2;
Aade 2 al elemento del arreglo c[11]. Note que un nombre de arreglo con subndice es un Ivalue
que puede ser utilizado al lado izquierdo de una asignacin.
Examinaremos el arreglo x. Sus 8 elementos se conocen como x[0], x[1], x[2],....,x[7]. El valor
de x[0] es 45.21, el valor de c[1] es 12.0, el valor de c[2] es 3.45, el valor de x[6] es de 2.65 y el
valor de x[7] es 13.04.
Para imprimir la suma de los valores contenidos en los primeros tres elementos del arreglo x,
escribiramos
C= x[6] / 2;
Pag 17
Como declarar arreglos
Los arreglos ocupan espacio en memora. El programador especifca el tipo de cada elemento y el
nmero de elementos requerido por cada arreglo, de tal forma que la computadora pueda
reservar la cantidad apropiada de memora. Para indicarle a la computadora que reserve 12
elementos para el arreglo entero c, la declaracin
int c[12];
es utilizada. La memoria puede ser reservada para varios arreglos dentro de una sola declaracin,
Para reservar 100 elementos para el arreglo entero b y 27 elementos para el arreglo entero x, se
puede utilizar la siguiente declaracin
/* inicializa el arreglo*/
#include <stdio.h>
main()
{
int n[10], i;
for (i = 0; i <= 9; i++) /*inicializa el arreglo*/
n[i] = 0;
printf(%s%13s\n, Elemento, Value);
for(i= 0; i <= 9; i++) /*imprime arreglo*/
printf(%7d%13d\n,i, n[i]);
return 0;
}
Elemento Value
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
Pag 18
El programa siguiente suma los valores contenidos en un arreglo entero a de doce elementos. El
enunciado en el cuerpo del ciclo for se ocupa de la totalizacin.
main()
{
int a [SIZE] = {1, 3, 5, 4, 7, 2, 99, 16, 45, 67, 89, 45}
i, total =0;
for (i=0; i <=SIZE 1;i++)
total += a[i]
printf(El total del valor de los elementos del arreglo es %d\n,total);
return 0;
}
El siguiente ejemplo utiliza arreglos para resumir los resultados de datos recopilados en una
investigacin. Deseamos resumir el nmero de respuestas de cada tipo (es decir del 1 hasta el
10). El arreglo respuestas es un arreglo de 40 elementos correspondiente a las respuestas de los
alumnos. Utilizamos un arreglo de 11 elementos, frecuencia para contar el nmero de ocurrencias
de cada respuesta. Ignoramos el primer elemento frecuencia[0], por que es ms lgico tener un
incremento de respuesta 1 frecuencia[1] que frecuencia[0]. Esto nos permite utilizar cada
respuesta directa como subndice en el arreglo frecuencia.
El primer ciclo for toma las respuestas del arreglo respuestas una por una e incrementa uno de
los diez contadores (frecuencia[1] hasta frecuencia [10] ) en el arreglo frecuencia. El enunciado
clave es
++frecuencia[respuestas[pregunta]
Este enunciado incrementa el contador frecuencia apropiado, dependiendo del valor de
respuestas[pregunta]. Por ejemplo cuando la variable del contador pregunta es 0,
respuestas[pregunta] es 1 y por lo tanto, ++frecuencia [respuesta[pregunta]]; se interpreta en
realidad como
++frecuencia[1];
#include <stdio.h>
#define RESPUESTAS_SIZE 40
#define FRECUENCIA_SIZE 11
main()
{
int answer, rating;
int respuestas[RESPUESTAS_SIZE] = {1, 2, 6, 4, 8, 5, 9, 7, 8, 10, 1, 6, 3, 8, 6, 10, 3, 8,
2, 7, 6, 5, 7, 6, 8, 6, 7, 5, 6, 6, 5, 6, 7, 5, 6, 4, 8, 6, 8, 10);
int frecuencia[FRECUENCIA_SIZE] = {0};
for (pregunta = 0; pregunta <= RESPUESTA_SIZE 1; answer++)
++frecuencia[respuestas[pregunta]];
printf (%s%17s\n,Rating, Frecuencia);
Pag 19
Rating Frecuencia
1 2
2 2
3 2
4 2
5 5
6 11
7 5
8 7
9 1
10 3
int Temperaturas[24];
C pasa de forma automtica los arreglos a las funciones utilizando simulacin de llamadas por
referencia las funciones llamadas pueden modificar los valores de los elementos en los arreglos
originales de los llamadores. El nombre del arreglo de hecho es la direccin del primer elemento
de dicho arreglo. Dado que ha sido pasada la direccin inicial del arreglo, la funcin llamada sabe
precisamente dnde est el arreglo almacenado. Por lo tanto, cuando en su cuerpo de funcin, la
funcin llamada modifica los elementos del arreglo, est modificando los elementos reales del
arreglo, en sus localizaciones de memoria originales.
#include <stdio.h>
main()
{
char array[5];
printf ( array = %p\n&array[0] = %p\n, array, &array[0]);
return 0;
}
array = FFF0
&array = FFF0
Arreglos multidimensionales
Aunque los elementos de los arreglos se almacenan en forma contigua, con frecuencia resulta til
imaginar que un arreglo bidimensional es un conjunto rectangular de elementos con filas y
columnas. Por ejemplo si se declara:
Pag 20
Puede imaginarse que los elementos del arreglo estn ordenados de la manera siguiente:
Col 1 Col 2 Col 3 Col 4 Col 5
Fila 1 B[0] [0] B[0] [1] B[0] [2] B[0] [3] B[0] [4]
Fila 2 B[1] [0] B[1] [1] B[1] [2] B[1] [3] B[1] [4]
Fila 3 B[2] [0] B[2] [1] B[2} [2] B[2] [3] B[2] [4]
Los arreglos de doble subndice se referencian con los subndice dentro de un mismo par de
corchetes separando por comas los subndices.
t[x,y];
y no
t[x] [y];
Los arreglos de doble subndice pueden ser declarados e inicializados de la siguiente manera
int b[2][2] = {{1,2},{3,4}};
Muchas manipulaciones comunes con arreglos utilizan estructuras de repeticin for. Por ejemplo,
la siguiente estructura define todos los elementos en el tercer rengln del arreglo a
int a[4][4];
for (column = 0;column 3; column++)
A[2] [column] =0
Especificamos el tercer rengln, por lo tanto, sabemos que el primer subndice ser siempre 2 (o
es el primer rengln y 1 el segndo). El ciclo for vara slo en el segundo subndice (es decir, el
subndice de columnas). La estructura for anterior es equivalente a los enunciados de asignacin
siguientes:
a[2][0] = 0;
a[2][1] = 0;
a[2][2] = 0;
a[2][3] = 0;
En el arreglo a, la siguiente estructura for anidada determina el total de todos los elementos.
Total = 0;
for (renglon =0; renglon <=3; renglon++)
for (column = 0;column <=3; column++)
total +=[renglon] [column];
Cadenas
Una cadena es una secuencia de caracteres encerrada entre comillas . Obsrvese que el smbolo
es un solo carcter, no dos. Si el carcter ha de aparecer en una cadena, debe ir precedido del
carcter \. A continuacin se presentan varios ejemplos de cadenas.
Pag 21
Las cadenas son arreglos unidimensionales de tipo char que tinen varas caractersticas nicas.
Un arreglo de caracteres puede ser inicializado utilizando una literal de cadena. Por ejemplo, la
declaracin
Dado que la cadena es un arreglo de caracteres podemos tener acceso directo a los caracteres
individuales de una cadena, utilizando la notacin de subndices de arreglos. Por ejemplo,
string1[0], es el carcter f y string[3] es el carcter s.
char string2[20];
Crea un arreglo de caracteres capaz de almacenar una cadena de 19 caracteres y un carcter nulo
de terminacin. El enunciado
La funcin scanf lee caracteres del teclado hasta que se encuentra con el primer carcter de
espacio en blanco sin impotarle que tan grande es el arreglo. Por lo tanto, scanf podra escribir
ms all del final del arreglo.
Un arreglo de caracteres que represente una cadena puede ser sacado utilizando printf y el
especificador de convesin %s. El arreglo string2 se imprime utilizando el enunciado
#include <stdio.h>
main()
{
char string1[20], string2[] = string literal;
int i;
printf(Mete un string: );
scanf(%s,string1);
printf(string1 es: %s\nstring2 es %s\n
string1 con espacios entre caracteres es: \n,
string1, string2);
Pag 22
for (i = 0; string1[i] != \0; I++)
printf(%c , string1[i]);
printf(\n);
return 0;
}
Uniones
Una union es un tipo de datos derivado como lo es una estructura- cuyos miembros comparten
el mismo espacio de almacenamiento. Para distintas situaciones en un programa, algunas
variables pudieran no ser de importancia, pero otras variables lo son por lo que una union
comparte el espcacio, en vez de desperdiciar almacenamiento en variables que no esten siendo
utilizadas. Los miembros de la union pueden ser de cualquier tipo el nmero de bytes utilizados
para almacenar una unin, deben ser por lo menos suficientes para contener al miembro mas
grande. En la mayor parte de casos las uniones contienen dos o ms tipos de datos. Unicamente
un miembro y, por lo tanto, nicamente un tipo de datos, puede ser referenciado en un momento
dado
union number{
int x;
float y;
}
indica que number es un tipo union con miembros int x y float. En un programa normalmente la
definicin de unin antecede a main, por lo que esta puede ser utilizada para declarar variables en
todo el programa.
Las operaciones que pueden ser ejecutadas en una unin son: asignar una unin a otra unin del
mismo tipo, tomar la direccin (&) de una unin, y tener acceso a los miembros de una union
utilizando el operador de miembro de estructura y el operador de apuntador de estructura.
En una declaracin, una union puede ser inicializada nicamente con un valor del mismo tipo que
el primer miembro de la union. Por ejemplo, en la union anterior, la declaracin
Es una inicializacin valida de la variable de union value, porque la union esta inicializada con un
int, pero la siguiente declaracin no sera valida:
Constantes de enumeracin
C proporciona un tipo final, definido por el usuario, conocido como una enumeracin. Una
enumeracin, introducida por la palabra reservada enum, es un conjunto de constantes enteras
representadas por identificadores. Estas constantes de enumeracin son, en efecto, constantes
simblicas, cuyos valores pueden ser definidos automticamente. Los valores de un enum se
inician con 0, a menos de que se defina de otra manera, y se incrementan en 1. Por ejemplo
enum months {JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC};
Pag 23
Crea un nuevo tipo en enum months, en el cual los identificadores son definidos automticamente
a los enteros 0 a 11. Para numerar los meses 1 a 12, utilice la enumeracin siguiente
enum monts {JAN =1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV,
DEC};
Dado que el primer valor de la enumeracin se define explcitamente en 1, los valores
subsiguientes se incrementan en 1dando como resultado los valores 1hasta 12
Los identificadores en una enumeracin deben de ser unicos. En una enumeracin el valor de cada
constante en la enumeracin puede ser establecido explcitamente en la definicin, mediante la
asignacin de un valor al identificador. Varios miembros pueden tener el mismo valor entero.
#include <stdio.h>
enum months {JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC};
main ()
{
enum months month;
char *monthName[] = {, January,February,March,April,May,
June,July,August, September, October,November, December};
return 0
}
1 January
2 February
3 March
4 Apr
5 May
6 June
7 July
8 Aug
9 Sep
10 Oct
11 Nov
12 Dec
Apuntadores
Los apuntadores le permiten a los programas simular llamadas por referencia, crear y manipular
estructuras de datos es decir, estructuras de datos que pueden crecer o encongerse como son
listas enlazadas, colas de espera, pilas y rboles.
Los apuntadores son variables que contienen direcciones de memoria como sus valores. Por lo
regular una variable contiene directamente un valor especifico, un apuntador por otra parte,
contiene la direccin de una variable que contiene un valor especifico. En este sentido un nombre
de variable se refiere directamente a un valor y un apuntador se refiere indirectamente a un valor,
el referirse a un valor a travs de un apuntador se conoce como indireccin.
Los apuntadores como cualquier otra variable deben ser declarados antes de que puedan ser
utilizados.
Pag 24
int *contadorAptr, contador;
contador Contador se refiere
7 directamente a la
variable cuyo valor es
7.
contadorAptr contador
7 ContadorAptr se
refiere en forma
indirecta a la
variable cuyo
valor es 7
La declaracin declar la variable contadorAptr siendo del tipo int*, se lee, contadorAptr es un
apuntador a int, o bien contadorAptr apunta a un objeto de tipo entero. Tambin, la variable
contador se declara como un entero, no un apuntador a un entero. El *solo se aplica a
contadorAptr en la declaracin.
Los apuntadores deben ser inicializados cuando son declarados o en un enunciado de asignacin.
Un apuntador puede ser inicializado a 0, NULL, o una direccin. Un apuntador con el valor NULL
apunta a nada. NULL es una constante simblica, definida en el archivo de cabecera<stdio.h>.
Cuando se inicializa 0 es equivalente a inicializar un apuntador a NULL. El valor 0 es el nico valor
entero que puede ser directamente asignado a una variable de apuntador
Operadores de apuntador
El &, u operador de direccin, es un operador unario que regresa la direccin de su operando. Por
ejemplo, suponiendo las declaraciones
int y= 5;
int *yPtr;
el enunciado
yPtr = &y;
asigna la direccin de la variable y a la variable de apuntador yPtr. La variable yPtr se dice que
apunta a
yPtr
Pag 25
yPtr y
500000 600000 600000 5
La direccin de a y el valor de aPtr son idnticos en la salida, confirmando asi que de hecho la
direccin de a ha sido asignada a la variable de apuntador aPtr. Los operadores & * son
complementos el uno del otro.
En C se utilizan los apuntadores y el operador de indireccin para simular llamadas por referencia.
Cuando se pasan direcciones de los argumentos que deban ser modificados, se pasan las
direcciones de los argumentos. Esto se lleva a cabo aplicando el operador de direccin (&), a la
variable cuyo valor deber ser modificado. Cuando se pasa a una funcin la direccin de una
variable, el operador de indireccin (*), puede ser utilizado en la funcin para modificar el valor
de esa posicin en la memoria de ese llamador
#include <stdio.h>
CuboPorReferencia(int *);
main()
{
int numero = 5;
Suponga que han sido declarados el arreglo entero b[5] y la variable de apuntador entera bPtr.
Dado que el nombre del arreglo (sin subndice) es un apuntador al primer elemento del arreglo,
podemos definir bPtr igual a la direccin del primer elemento en el arreglo b mediante el
enunciado.
bPtr = b;
Este enunciado es equivalente a tomar la direccin del primer elemento del arreglo, como sigue
bPtr = &b[0]
Alternativamente el elemento del arreglo b[3] puede ser referenciado con la expresin de
apuntador
Pag 26
*(bPtr + 3)
El 3 en la expresin arriba citada es el desplazamiento del apuntador. Cuando el apuntador
apunta al principio del arreglo, el desplazamiento indica que el elemento del arreglo debe ser
referenciado, y el valor del desplazamiento es idntico al subndice del arreglo, la notacin
anterior se conoce como notacin apuntador/desplazamiento.Al igual que el elemento del arreglo
puede ser referenciado con una expresin de apuntador, la direccin
&[3]
puede ser escrita con la expresin de apuntador
bPtr + 3
El arreglo mismo puede ser tratado como un apuntador, y utilizado en aritmtica de un
apuntador.
Por ejemplo la expresin
*(b + 3)
tambin se refiere al elemento del arreglo b[3]. En general, todas las expresiones de arreglos son
subndice pueden ser escritas mediante un apuntador y un desplazamiento.
Arreglos de apuntadores
Los arreglos pueden contener apuntadores. Un uso comn para una estructura de datos como
sta, es formar un arreglo de cadenas. Cada entrada del arreglo es una cadena pero en C una
cadena es esencial un apuntador a su primer carcter. Por lo que en un arreglo de cadenas cada
entrada es de hecho un apuntador al primer carcter.
Cada apuntador seala al primer carcter de su cadena correspondiente. Por lo tanto, aunque el
arreglo suit es de tamao fijo, permite el acceso a cadenas de caarcter de cualquier longitud.
Suit[0] C o r a z o n e s \0
Suit[1]
D i a m a n t e s \0
Suit[2]
T r e b o l e s \0
Suit[3]
E s p a d a s \0
Un ejemplo grfico de un arreglo suit
TypeName *ptr;
Pag 27
Donde typeName es cualquier tipo (como int, float, char, etctera). En ANSI C, el enunciado
siguiente asigna en forma dinmica un objeto typeName, regresa un apuntador void al objeto, y
asigna dicho apuntador a ptr
En C++, el enunciado
Para liberar en C++ el espacio para este objeto se utiliza el siguiente enunciado:
delete ptr
En C, se invoca la funcin free con el argumento ptr, a fin de desasignar memoria. El operador
delete slo puede ser utilizado para desasignar memoria ya asignada por new. Aplicar delete a
un apuntador previamente desasignado puede llevar a errores, inesperados durante la ejecucin
del programa. Aplicar delete a un apuntador nulo no tiene efecto en la ejecucin del programa.
int *arrayPtr;
ArrayPtr = new int[100]; //creando arreglo dinmico
Para desasignar la memoria asignada dinmicamente para arrayPtr por new, utilice el enunciado
delete [] arrayPtr;
Ordenamiento
La ordenacin o clasificacin de datos (sort) es una operacin consistente en disponer un conjunto
estructura- de datos, en algn determinado orden con respecto a uno de los campos elementos
del conjunto. Los elementos numricos se pueden ordenar en orden creciente o decreciente de
acuerdo al valor numrico del elemento. En terminologa de ordenacin, el elemento por el cual
esta ordenado un conjunto de datos se denomina clave.
Una coleccin de datos puede ser almacenada en un archivo, un arreglo (vector o tabla), un
arreglo de registros, una lista enlazada o un rbol. Cuando los datos estn almacenados en un
arreglo, una lista enlazada o un rbol, se denomina ordenacin interna. Si los datos estn
almacenados en un archivo el proceso de ordenacin se llama ordenacin externa.
Pag 28
Los mtodos (algoritmos) de ordenacin son numerosos, por ello se debe prestar especial
atencin en su eleccin Cmo se sabe cual es el mejor algoritmo? La eficiencia es el factor que
mide la calidad y rendimiento de un algoritmo.
1. tiempo menor de ejecucin en computadora
2. menor nmero de instrucciones
Este mtodo es clsico y muy sencillo, aunque por desgracia poco eficiente. La ordenacin por
burbuja se basa en la comparacin de elementos adyacentes de la lista (vector) e intercambiar
sus valores si estn desordenados. De este modo se dice que los valores ms pequeos burbujean
hacia la parte superior de la lista, mientras que los valores ms grandes se hunden haca el fondo
de la lista.
A[1] 23 15
A[2] 19 19
A[3] 45 23
A[4] 31 31
A[5] 15 44
Lista sin ordenar Lista ordenada
Pag 29
Pasada 1: i=1
A[1] 23 19 19 19 19
A[2] 19 23 23 23 23
A[3] 45 45 45 31 31
A[4] 31 31 31 45 15 elemento
ordenado
A[5] 15 15 15 15 45
j=1 j=2 j=3 j=4
Se han realizado cuatro comparaciones (5-1 o bien n-1 en el caso de n elementos) y tres
intercambios.
Pasada 2: i = 2
A[1] 19 19 19 19 19
A[2] 23 23 23 23 23
A[3] 31 31 31 15 15
elemento
A[4] 15 15 15 31 31 ordenado
A[5] 45 45 45 45 45
J=1 j=2 j=3 j=4
Pasada 3: i = 3
A[1] 19 19 19 19 19
A[2] 23 23 15 15 15
A[3] 15 15 23 23 23
elemento
A[4] 31 31 31 31 31 ordenado
A[5] 45 45 45 45 45
Pag 30
Pasada 4: i =4
A[1] 19 15 15 15 15
A[2] 15 19 19 19 19
A[3] 23 23 23 23 23
elemento
A[4] 31 31 31 31 31 ordenado
A[5] 45 45 45 45 45
j=1 j=2 j=3 j=4 j=5
Se observa que se necesitan cuatro pasadas para ordenar una lista de nmeros de cinco
elementos, por lo que una lista de n elementos necesitar n-1 pasadas.
El nmero de pasadas se puede controlar con un bucle for y cada secuencia de comparaciones se
puede controlar con un bucle for anidado al bucle de pasadas, en el que j vara desde 1 hasta 5
menos el valor especifico de i.
Algoritmo (Pseudocdigo)
Burbuja mejorado
El algoritmo burbuja se puede mejorar si disponemos de algn tipo de indicador que registre si se
han producido intercambios en la pasada. Cuando se explor la lista y el indicador no refleje
intercambios, la lista estar ya ocupada y se terminarn las comparaciones.
El intercambio ser una variable lgica NoIntercambio (o bien ordenado) que se inicializa a 1
(significa que la lista a priori est desordenada). Si dos elementos se intercambian en una pasada.
No Intercambio se pone en 0. Al principio de cada pasada NoIntercambio se fija a 1 y a 0 si se
produce a intercambios. El bucle externo for se sustituye por un bucle do while o bien while y
un contenido i se necesitara para contar el nmero de pasadas.
Pag 31
i =1
Repetir
NoIntercambio = true
Desde j = i hasta n i hacer
Si A[j] > A[J+1]
Entonces Intercambio (A[j], A[j+1])
NoIntercambio = false
Fin si
Fin_desde
i = i+1
Hasta que NoIntercambio = true
Tres cartas 2 6 10
Cuatro 2 6 //////// 9 10
cartas ////////
El mtodo se basa en considerar una parte de la lista ya ordenada y situar cada uno de los
elementos restantes insertndolo en el lugar que le corresponde por su valor.
1 4 10 15
A[N]
Pag 32
1 4 6 10 15
Algoritmo
Fin_desde
La operacin de desplazamiento se realiza con un procedimiento Desplazar, que mueve todos los
elementos de la lista mayores que Aux, comenzando con el elemento de la lista de posicin Aux-1.
Si Aux es el valor ms pequeo hasta aqu, la operacin de desplazamiento termina despus que
todos los elementos de la lista se han desplazado. Si Aux no es el valor ms pequeo, la
operacin de desplazamiento termina cuando un valor menor o igual a Aux se alcanza. Aux se
inserta en la posicin que ocupaba el ltimo valor que se desplaz.
Algoritmo de desplazamiento
Mientras el primer elemento no se desplaza y el valor del elemento > Aux hacer
o Desplazar elemento una posicin.
o Comprobar valor del siguiente elemento.
o Definir NuevaPos como posicin original del ltimo elemento desplazado.
Fin_mientras
for(k=2;k<=n;k++){
aux = lista[k]; /*obtener siguiente elemento a insertar*/
Lista[nueva_pos(Lista,k,aux)]=aux; /*insertar aux en posicin nueva*/
}
return 0;
}
Lista A[1] 5 5 5 -2
desordenada
A[2] 14 2 2 2
A[3] -2 -2 -2 5
A[4] 10 10 10 10
A[5] 2 14 14 14
El algoritmo de PosMayor debe guardar j como la posicin del elemento mayor y luego poder
intercambiar.
Pag 34
/*encontrar el elemento mayor de 1..J*/
Mayor = PosMayor (J, Lista);
/*Intercambio con el elemento Tabla [J]*/
Aux = Lista[Mayor];
Lista[Mayor] = Lista[J];
Lista [J] = Aux;
}
}
Ordenamiento Shell
La ordenacin Shell debe el nombre a su inventor, D. L. Shell. Se suele denominar tambin
ordenacin por disminucin de incremento (gap). La idea general del mtodo (algoritmo) es la
siguiente:
Lista original
504 88 513 62 908 171 898 277 654 427 150 510 612 675 750 704
1. Se divide la lista original (16 elementos, en este ejemplo) en ocho grupos de dos
(consideramos un incremento o intervalo de 16/2 = 8).
2. Se clasifica cada grupo por separado (se comparan las parejas de elementos y si no estan
ordenados se intercambian entre si de posiciones).
3. Se divide ahora la lista en cuatro grupos de cuatro (intervalo o salto de 8/2 = 4) y
nuevamente se clasifica cada grupo por separado.
4. Un tercer paso clasifica dos grupos de ocho registros y luego un cuarto paso completa el
trabajo clasificando todos los 16 registros.
504 88 513 62 908 171 898 277 654 427 150 510 612 675 750 704
Pag 35
Segundo paso (divisin/ordenacin por 4)
504 88 150 62 612 171 760 277 654 427 513 510 908 675 898 704
504 88 150 62 612 171 513 277 654 427 760 510 908 675 898 704
154 62 504 88 513 171 612 277 654 427 760 510 898 675 908 704
62 88 154 171 277 427 504 510 513 612 654 675 704 760 898 908
Algoritmo
Intervalo = n div 2
Mientras (intervalo > 0 ) hacer
Desde i = (intervalo + 1) hasta n hacer
Pag 36
J = i intervalo
Mientras (j >0 ) hacer
K = j + intervalo
Si ( a [j] <= a[k])
Entonces
J=0
Si no
Intercambio (a[j], a[k]
Fin si
j = j intervalo
Fin mientras
Fin desde
Intervalo = intervalo div 2
Fin mientras
Cdigo
Aux = X;
X = Y;
Y =Aux;
}
Pag 37
Ordenamiento Mezcla (MergeSort)
El proceso de mezcla, fusin o intercalacin (merge) consiste en tomar dos vectores ordenados
(a, b) y obtener un nuevo vector tambin ordenado.
1. Seleccionar el elemento de valor o clave mas pequeo con cualquiera de dos vectores y
situarlo en el nuevo vector c.
2. Comparar a(i) y b(i) y poner el elemento de vector ms pequeo en c(k).
3. Seguir esta secuencia de comparaciones hasta que los elementos de un vector se hayan
agotado en cuyo momento se copia el resto del otro vector en c.
Ejemplo:
Mezclar las dos listas de nmeros a y b.
2 4 78 97 lista A
-15 0 13 15 78 90 96 lista B
2 4 78 97 Lista A
j se ha incrementado
i junto con k
<
Lista C
Lista B
-15 0 13 15 78 90 94 96
k
-15 0 Lista C
Pag 38
2 4 78 97 Lista A
i
<
Lista B
-15 0 13 15 78 90 94 96
k
Pag 39
Bsquedas
Bsqueda secuencial
Un problema importante en el proceso de datos, como ya se ha comentado, es la bsqueda en un
conjunto de datos de un elemento especifico y la recuperacin de alguna informacin asociada al
mismo.
Mediante un bucle desde ir comparando el elemento t buscando con a[i], donde i vara, en el
ejemplo anterior, de 1 a 100. En caso de encontrarlo, almacenar la posicin (el indice arreglo) del
mismo dentro de la lista y finalmente se devolver al programa principal.
Pseudocdigo 1
Posicin = 0
{lista = vector a[i] de n elementos}
desde i = 1 hasta n hacer
si a[i] = t
entonces Posicin = i
fin si
fin desde
Este algoritmo tiene un inconveniente, sea cual sea el resultado se recorre el vector completo. El
algoritmo se puede mejorar con un bucle while o do_while, y utilizando unas banderas que
detecten cuando se encuentre el elemento. El bucle se terminar por dos causas:
Pseudocdigo 2
Pag 40
Encontrado = falso
Posicin = 0
i=1
mientras (i <= n) y (No Encontrado=verdadero) hacer
si a[i] = t
entonces Posicin = i
Encontrado = verdadero
Fin si
i=i+1
fin_mientras
int Encontrado=0,I=1,Posicion;
Bsqueda Binaria
La bsqueda lineal, por sus simplicidad es buena para listas de datos pequeas para listas
grandes es ineficiente, la bsqueda binaria es el mtodo idneo. Se basa en el conocido mtodo
divide y vencers.
Este mtodo tiene una clara expresin en la bsqueda de una palabra en un diccionario. Cuando
se busca una palabra no se comienza la bsqueda por la pgina 1 y se sigue secuencialmente sino
que se abre el diccionario por una pagina donde aproximadamente se piensa puede estar la
palabra, es decir se divide el diccionario en dos partes, al abrir la pgina se ve si se ha acertado o
en que parte se encuentra la palabra buscada. Se repite este proceso hasta que por divisiones o
aproximaciones sucesivas se encuentra la palabra.
Supongamos que la lista donde se busca es
1331
1373
1555
1850
1892
1898 Elemento central
1989
Elemento buscado
2002
2400
2670
3200
Pag 41
Y que se busca el nmero 1989
Se examina en primer lugar el elemento central de la lista (las divisiones se toman iguales) 1898.
Dado que 1989 es mayor que 1898, el elemento a buscar estar en la segunda mitad. Por
consiguiente, se sigue la bsqueda en esta mitad:
El elemento central en esta sublista es 2400, y como1989 es menor, la nueva sublista donde
buscar es
Pag 42
La bsqueda binaria requiere una ordenacin previa del vector o lista en el que se va ha efectuar
la bsqueda. Por consiguiente, las acciones tpicas (mdulos) en un algoritmo de bsqueda binaria
son:
Una estructura de datos es una coleccin de datos organizados de un modo particular, las
estructuras de datos pueden ser de dos tipos: estructuras de datos estticas y estructuras de
datos dinmicas.
Las estructuras de datos estticas son aquellas en las que se asigna una cantidad fija de memoria
cuando se declara la variable, en numerosas ocasiones se necesitan, colecciones de datos que
crezcan y reduzcan su tamao en memoria a medida que el programa progresa, a estas
estructuras de datos cuya ocupacin en memoria puede aumentar o disminuir en tiempo de
ejecucin se denominan estructuras dinmicas de datos.
Pag 43
(int), real (float), y carcter (char). Las reglas para construir tipos de datos compuestos a partir
de los bsicos tambin varan de un lenguaje a otro
Un tipo de datos abstracto (TDA) es un modelo matemtico, junto con varias operaciones
definidas sobre ese modelo. Para representar el modelo matemtico bsico de un TDA se emplean
estructuras de datos, que son conjuntos de variables quiza de tipos distintos, conectadas entre si
de diversas formas.
El componente bsico de una estructura de datos es la celda. Se puede representar una celda
como una caja capaz de almacenar un valor tomado de algn tipo de datos bsico o compuesto,
las estructuras de datos se crean dando nombres a agregados de celdas
Estructuras
Las estructuras son colecciones de variables relacionadas a veces denominados agregados bajo
un nombre. Las estructuras pueden contener variables de muchos tipos diferentes de datos a
diferencia de los arreglos, que contienen unicamente elemento de un mismo tipo de datos.
Generalmente las estructuras se utilizan para definir registros a almacenar en archivos.
Creacin de estructuras
Crear una estructura es definir un nuevo tipo de datos, denominado tipo estructura y declarar una
variable de este tipo. En la definicin del tipo estructura, y declarar una variable de este tipo. En
la definicin del tipo estructura, se especifican los elementos que la componen as como sus tipos.
Cada elemento de la estructura recibe el nombre de miembro (campo del registro). La sntaxis es
la siguiente:
struct tipo_estructura
{
declaraciones de los miembros
};
Despus de definir un tipo estructura, podemos declarar una variable de ese tipo, de la forma:
variable.miembro
Ejemplo:
La anterior definicin no reserva ningn espacio en memoria, ms bien genera un nuevo tipo de
datos, que se utiliza para declarar variables.
Pag 44
struct ficha var1, var2;
Este ejemplo define las variables var1 y var2, de tipo ficha, por lo que cada una de las variables
consta de los miembros: nombre, direccin y telfono.
Una variable que es un miembro de una estructura, puede utilizarse exactamente igual que
cualquier otra variable.
Ejemplo:
struct ficha
{
char nombre[40];
char direccion[40];
long telefono;
} var1, var2;
struct card {
char false[10];
char suit[10];
}a, deck[52];
La nicas operaciones vlidas que pueden ejecutarse sobre estructuras son : asignar variables de
estructura a variables de estructura del mismo tipo, tomando la direccin (&) de una variable de
estructura obteniendo acceso a los miembros de una varible de estructura, y utilizando el
operador sizeof, a fin de determinar el tamao de la variable de estructura.
Pag 45
Como tener acceso a los miembros de estructuras
Para tener acceso a miembros de estructuras se utilia el operador de miembro de estructura (.).
typedef
La palabra reservada typedef proporciona un mecanismo para la creacin de sinnimos (o
alias)para tipos de datos anteriormente definidos
typedef struct{
char false[10];
char suit[10];
}Card;
Card puede ser utilizado para declarar variables de tipo struct card. La declaracin
Card deck[52];
Al crear un nuevo nombre utilizando typedef no se crea un nuevo tipo; typedef simplemente crea
un nuevo nombre de tipo que puede ser utilizado como un seudnimo para un nombre de tipo
existente.
Ejemplo:
El siguiente programa lee una lista de alumnos y sus correspondientes notas de final de curso,
dando como resultado el tanto porciento de alumnos aprobados y suspendidos
#include <stdio.h>
#include <stdlib.h>
#define NA 10
main()
{
struct ficha
{
char nombre[60];
float nota;
};
/*Entrada de datos*/
printf(Finalizar la entrada con cont/Z\n\n);
printf(Nombre);
fin = gets(alumnos[n].nombre);
for (i =0;i<n>i++)
if (alumnos[i].nota >=5)
aprobados ++;
else
suspensos ++;
printf(Aprobados %.2g %%\n,aprobados /n*100);
printf(Suspensos %.2g %% \n,suspensos/n*100);
}
T.D.A. Lista
Modelo Matemtico
Las listas constituyen una estructura flexible en particular, por que pueden crecer y acortarse
segn se requiera, los elementos son accesibles y se pueden insertar y suprimir en cualquier
posicin de la lista, las listas tambin pueden concatenarse entre si o dividirse en sublistas; se
representan de manera rutinara en aplicaciones como manera de aplicacin.
Una propiedad importante de una lista es que sus elementos pueden estar ordenados en forma
lineal de acuerdo con sus posiciones en la misma. Se dice que ai precede a ai+1 para i = 1, 2,...n-
1 y que ai sucede a ai-1 para i = 2, 3,...n. Se dice que el elemento ai est en la posicin i. Es
conveniente postular tambin la existencia de una posicin que sucede al ltimo elemento de la
lista. La funcin FIN(L) devolver la posicin que sigue a la posicin que sigue a la posicin n en
una lista L de n elementos. Observese que la posicin FIN(L), con respecto al principio de la lista,
est en una distancia que vara conforme la lista crece o se reduce, mientras que las demas
posiciones guardan una distancia fija con respecto al principio de la lista.
Para formar un tipo de dato abstracto a partir de la nocin matemtica de la lista, se debe de
definir un conjunto de operaciones con objetos de tipo lista.
Pag 47
Operaciones
Se representar ahora un conjunto representativo de operaciones con listas. Ah, L es una lista de
objetos de tipo tipo_elemento, x es un objeto de ese tipo y p es de tipo posicin. Observese que
<<posicin>> es otro tipo de datos cuya implantacin cambiar con aquella que se haya elegido
para las listas. Aunque de manera informal se piensa en las posiciones como enteros, en la
practica pueden tener otra representacin.
En la realizacin de una lista mediante arreglos, los elementos de esta se almacenan en celdas
contiguas de un arreglo. Esta representacin permite recorrer con facilidad una lista y agregarle
elementos nuevos al final, pero insertar un elemento en la mitad de la lista obliga a desplazarse
una posicin dentro del arreglo a todos los elementos que siguen al nuevo elemento para
concederle espacio. De la misma forma la eliminacin de un elemento, excepto el ltimo, requiere
desplazamientos de elementos para llenar de nuevo el vacio formado.
Pag 48
1 primer elemento
2 segundo elemento
lista
lt ltimo elemento
vaco
Long_mx
En la realizacin con arreglos se define el tipo LISTA como un registro con dos campos, el primero
es un arreglo de elementos que tiene la longitud adecuada para contener la lista de mayor
tamao que se puede representar. El segundo campo es un entero lt que indica la posicin del
ltimo elemento de la lista en el arreglo. El i-simo elemento de la lista est en la i-sima
posicin, mediante el entero i. La funcin FIN(L) slo tiene que devolver lt +1. Las declaraciones
importantes son:
#include <stdio.h>
#include <conio.h>
# define TAM 10
# define TRUE 1
# define FALSE 0
struct LISTA
{
dato elem[TAM];
posicion ult;
};
for(i=0;i<9;i++)
{
printf("Dame el numero");
scanf("%d",&x);
Insertar(x,Primero(L),L);
}
Imprime(L);
printf("La posicion el numero");
scanf("%d",&p);
Suprimir(p,L);
clrscr();
Imprime(L);
x=Recupera(1,L);
printf("%d",x);
x=Anterior(3,L);
printf("%d",x);
x=Siguiente(5,L);
printf("%d",x);
getch();
}
Una ventaja es que como es bien sabido, los arreglos son estructuras de acceso directo, por lo
que las dems operaciones son triviales, as que una representacin con arreglos en un momento
dado pudiera ser de utilidad.
Pag 52
El tipo de Dato Abstracto PILA
Una pila es un tipo especial de Lista en la que todas las inserciones y supresiones tienen lugar en
un extremo denominado tope. Son estructuras LIFO (Last In First Out) o ltimo en entrar, primero
en salir en las que solo es posible quitar el elemento que se encuentra en la parte superior de la
pila (tope), son muy tiles en muchos aspectos de la programacin, tales como evaluacin de
expresiones, anidacin de parentisis, asi como en la implementacin de rutinas recursivas, entre
muchas otras aplicaciones. Una estructura de este tipo generalmente incluye las Operaciones
siguientes:
Para representar una Pila con arreglos es posible hacerlo de manera similar como se hizo con las
Listas con arreglos, establecemos la Pila como un registro don dos campos, el primero un arreglo
para contener los datos de la Pila y un campo para almacenar la posicin del elemento superior de
la pila (que en lo sucesivo llamaremos tope).
#define TAM 38
typedef char tipo_elem;
typedef int logico;
struct Pila{
Tipo_elem elemento[TAM];
Int tope;
};
1
2
3
4
.
tope .
.
TAM
Pag 53
void ANULA(Pila &P){
P.tope =TAM +1; {Creamos una Pila Vaca}
}
Notacin Polaca
Las expresiones se componen de operandos, operadores y delimitadores. Los operandos son
valores numricos que se utilizan para calcular la expresin. Los operadores indican las
operaciones matemticas que van hacerse sobre los operandos respectivos. Tambin determinan
la cantidad de operandos necesarios para cada tipo de operacin (binarios y unarios).
Es evidente que el orden en que se calculan las operaciones puede ser muy importante, como en
la expresin 6 + 4/2. Si la resolvemos como (6+4)/2, la respuesta es 5, si lo hacemos como 6 +
(4/2), el resultado es 8.
Pag 54
Operador Valor
3
x,/ 2
+,- 1
Para cambiar el orden de clculo de una expresin, pueden utilizarse parntisis pero en su
ausencia las operaciones de mayor precedencia se resuelven primero. Cuando una expresin
incluye operaciones de igual precedencia, se calculan de izquierda a derecha.
La forma ms usual de representar una expresin es la forma infija, es decir, colocamos los
operadores entre sus operandos.
A + B (infija)
A B + (posfija o polaca)
La segunda forma con el operador despus del operando se conoce como notacin posfija
(polaca).
a + (bXc)
Despus se colocan los operadores en orden de precedencia, as el primero que debemos mover
es el signo de multiplicacin, X, para que la expresin resultante sea de este modo:
a + (bcX)
Los dos operandos del operador X son b y c, por lo que es fcil determinar la posicin posfija de
ese signo, pero cuales son los dos operandos del operador +?, la respuesta es a y el resultado de
la subexpresin (bXc). Y ponemos el operador + despus del parentisis de cierre:
a(bcX)+
El paso final es quitar el parntesis
abcX+
Ahora, usando parntesis, vamos a cambiar el orden del clculo de los operandos y a convertir la
expresin (a + b) X c en notacin polaca:
(a + b) X c expresin infija
(a + b) X c se aaden parntesis sin cambio
(ab +)X c se convirti el +
(ab +) c X se convirti el X
ab + c X se elimin el parntesis
Pag 55
Recursividad
Un subprograma (procedimiento o funcin) recursivo es aquel que se llama as mismo. La
recursividad es una alternativa a la iteracin o repeticin, y aunque en tiempo de computadora y
en ocupacin de memoria es la solucin recursiva menos eficiente que la solucin iterativa,
existen numerosas situaciones en las que la recursividad es una solucin simple y natural a un
problema que en caso contrario sera difcil de resolver.
Es uno de los mtodos ms rpidos y frecuentemente utilizados en ordenacin (Quick Sort) Fue
inventado por C.H. Hoare, y la cantidad de cdigo necesario es sorprendentemente pequeo
comparando con la excelente velocidad que proporciona.
La idea bsica de la ordenacin rpida es:
Elegir un elemento de la lista denominado pivote.
Dividir o partir la lista original en dos sublistas o mitades, de modo que en una de ellas
estn todos los elementos menores que el pivote;
Las sublistas deben ser ordenadas, independientemente, del mismo modo, lo que conduce
a un algoritmo recursivo.
La eleccin del pivote es arbitraria aunque por comodidad es usual utilizar el termino central de la
lista original, o bien el primero o el ltimo elemento de la misma.
9 23 31 17 21 19 13 15 26
9 23 31 17 // 19 13 15 26
21//
pivote
2. A continuacin se establecen dos punteros en la lista I o J. El primer puntero apunta al
primer elemento. Por consiguiente, I =1. El segundo puntero apunta al ltimo elemento y,
por lo tanto, J=9 (noveno elemento).
9 23 31 17 // 19 13 15 26
21//
I= 1 J=9
Pag 56
3. Mientras I apunte a un elemento que sea menor que 20, se incrementa el valor de I en 1,
hasta que se encuentre un elemento mayor que el pivote. A continuacin se realiza la
misma tarea con el puntero J, buscando un elemento menor que 21, y mientras no lo
encuentra se decrementa J en 1.
9 23 31 17 // 19 13 15 26
21//
I J
4. Se intercambian los elementos apuntados por I y J y a continucacin se incrementan en
uno los contadores I, J.
9 15 31 17 // 19 13 23 26
21//
I J
5. El proceso se repite
9 15 13 17 // 19 31 23 26
21//
I J
9 15 13 17 // 19 31 23 26
21//
I J
9 15 13 17 // 21 31 23 26
19//
J I
Pag 57
Sublista Izquierda Sublista Derecha
9 15 13 17 19 21 31 23 26
I J I J
9 15 13 17 19 21 31 23 26
I J I J
9 15 13 17 19 21 23 31 26
I J J I
9 13 15 17 19 31 26
J I I J
9 13 15 17 19 31 26
J I J I
9 13 15 17 19
9 13 15 17 19
Lista Ordenada
9 13 15 17 // 21 23 26 31
19//
Pag 58
Algoritmo de Ordenacin Rpida:
Se dispone de tres postes (1,2,3) con soportes de madera (varillas de alambre o similar) y un
juego de discos de diferentes tamaos (el nmero de ellos se leer en el programa principal) que
se situan en el primer poste, el disco de mayor tamao (dimetro) se sita en el fondo y el ms
pequeo en la parte superior. El juego consiste en mover los discos del poste 1 al poste 3 de
acuerdo a las siguientes reglas:
Anlisis
El problema a primera vista parece sencillo, pero su solucin es francamente difcil y slo la
solucin recursiva facilita la resolucin. Tres, cuatro discos son imaginables, 64 (las leyendas citan
esta cifra como la propuesta de un rey tibetano a sus subditos, al estilo del tambin famoso
problema del tiempo necesario para llenar un tablero de ajedrez en progresin geomtrica) es
prcticamente inimaginable y casi imposible, sin solucin recursiva.
Algoritmo (3 discos)
Algoritmo (n discos)
Mover n-1 discos desde 1 hasta el 2 utilizando el poste 3.
Mover el disco restante desde 1 hasta el 3.
Mover la torre de n-1 discos desde el poste 3 utilizando el poste 1.
Situacin
inicial
Pag 60
Poste 1 Poste 2 Poste 3
Pos NumDiscos;
main(){
printf (Introduzca nmero de discos en juego\n);
scanf(%d,&NumDiscos);
printf(Para %d discos, NumDiscos);
printf (Los movimientos sucesivos son :\n);
MoverTorre(NumDiscos, 1, 2, 3);
}
Para una torre de 4 discos los movimientos son 15 y para una torre de 64 discos los movimientos
son inimaginables 2 E(64) 1.
Colas
Una cola es otro tipo especial de lista en el cual los elementos se insertan en un extremo (el
posterior ) y se suprimen en el otro (el anterior o frente). Las colas se conocen tambin como
listas <<FIFO>> (first-in, first out) o listas <<primero en entrar, primero en salir>>. Las
operaciones para una cola son anlogas a las de las pilas, las diferencias sustanciales consisten en
que las inserciones se hacen al final de la lista, y no al principio, y en que la terminologa
tradicional para colas y listas no es la misma. Se usarn las siguientes operaciones con colas.
Operaciones
#define TAM 20
#define TRUE 1
#define FALSO 0
typedef int tipo_elem,logico;
typedef struct{
Tipo_elem elemento [TAM];
Int final, frente;
}Cola;
Pag 62
Final Frente
En la figura se representa una cola vaca, esto sucede si anterior est en la posicin que sigue a la
posicin del posterior.
Concepto de apuntador
En una computadora cada posicin de memora tiene una direccin y un valor especifico
almacenado en esa posicin. Se han utilizado nombres de variables en lugar de direcciones. Para
almacenar un nuevo valor a la memoria se asigna a una variable, y la computadora enva una
direccin a la memoria seguida por el valor a almacenar en esa posicin. Con los apuntadores se
puede hacer referencia a variables por sus direcciones.
Considerese un programa que procese registros de empleados [es comn que los registros de
empleados sean muy largos; para nuestro ejemplo, supondremos que su tamao es de 2048
bytes. Supongamos que ya hemos escrito una funcin para la nmina que procesa estos registros
e imprime recibos. Una forma de suministrarle datos a nuestra funcin es pasarle cada uno de los
registros de empleados como argumento.
Estructuras autoreferenciadas
Una estructura autoreferenciada contiene un miembro de apuntador que apunta a una estructura
del mismo tipo de estructura. Por ejemplo, la definicin
struct nodo {
int dato;
struct nodo *proxPtr;
};
Define un tipo struct nodo. Una estructura del tipo struct nodo tiene dos miembros el miembro
entero dato y el miembro de apuntador proxPtr. El miembro nextPtr apunga a una estructura de
tipo struct nodo Una estructura del mismo tipo que la que se est declarando aqu, de ah el
termino estructura autorreferenciada. El miembro proxPtr se conoce como un enlace o vnculo
es decir proxPtr puede ser utilizada para vincular una estructura del tipo struct nodo con otra
estructura del mismo tipo. Las estructuras autorreferenciadas pueden ser enlazadas juntas para
formar tiles estructuras de datos como son las listas, las colas de esperas, las pilas y los rboles.
15 10
Pag 64
elementos cuyo tipo es tipo_elemento; cada registro contiene un elemento y un entero que se usa
como curso Es decir, se define
#define TAM 10
typedef int Tipo_elem;
struct ESPACIO{
Tipo_elem Elemento;
int sig;
}Lista[TAM];
int dis,Prim;
Para la realizacin de este tipo de listas nos podemos auxiliar de una variable llamada Disponible,
que nos da la posicin del arreglo del primer disponible o vaca y en el caso de saber donde inicia
la lista hacemos uso de una variable entera que llamaremos Primero.
ESPACIO
1 D 8
2 4
Prim
3 C 1
4 6
5 A 9
6 7
7 0
8 E 5
9 B 0
Disponible
10 10
11 2
Elemento sig
Pag 65
Listas con encabezado
Lista simplemente ligada
En esta representacin, una lista est formada por celdas; cada celda contiene un elemento de la
lista y un apuntador a la siguiente celda. Si la lista a1, a2, a3,...,an, la celda que contiene ai tiene
un apuntador a la celda que contiene a ai+1, para i=1,2,...,n 1. La celda que contiene an posee
un apuntador a NULL. Existe tambin una celda de encabezamiento que apunta a la celda que
contiene a1; esta celda de encabezamiento no tiene ningn elemento. En este caso hablamos de
una lista simplemente ligada con nodo de encabezamiento vaco, en la que el empleo de una celda
completa para el encabezado simplifica la implementacin de las operaciones para manipular la
lista, aunque tambin se puede utilizar el encabezado para almacenar el primer elemento y a este
tipo de representacin se le conoce como lista simplemente ligada con nodo de encabezamiento
no vaco, en la que las inserciones y supresiones al principio de la lista se manejan de manera
especial.
En el caso de una lista con encabezado vacio, el apuntador al siguiente nodo es NULL ya que no
se tienen ms celdas. La estructura de datos que emplearemos para representar una lista con
apuntadores ser un registro con dos campos, uno para guardar el elemento de la lista y otro
para mantener la direccin del siguiente nodo.
A continuacin se muestra la figura de una lista simplemente ligada lineal con nodo de
encabezamiento vaco y longitud n.
A1 A2 An
encabezado Lista
typedef tipo_elemento:
struct nodo{
tipo_elemento elemento;
nodo *sig;
}
encabezado
Pag 66
void INSERTA (tipo_elemento x, Nodo p ){
//Coloca el elemento x delante de la celda que apuntada por p
Nodo aux;
aux= new(nodo); //Se reserva memoria para el nuevo nodo
aux-> elemento=x; //Se almacena el elemento
aux->sig =p->sig; //Se enlaza con el siguiente nodo de p
p->sig=aux; //p se enlaza con el nuevo nodo
}
A1 A2 An
encabezado p x
aux
A1 x A2 An
encabezado p aux
La estructura de datos que se emplea para representar este tipo de lista es la misma que para
una lista ligada lineal, y al igual que estas tambin el nodo de encabezado puede contener
informacin.
A1 A2 An
encabezado Lista
Una desventaja de las listas lineales es que dado un apuntador p a un nodo de la lista, no se
puede tener acceso a cualquier otro nodo anterior a p. Si se recorre una lista, el apuntador al
encabezado no debe ser modificado a fin de poder hacer referencia a esta lista. Si hacemos un
pequeo cambio en la estructura de tal manera que el ltimo nodo en lugar de tener en el campo
siguiente un apuntador nulo (nil) tenga la direccin al inicio de la lista, entonces desde cualquier
otro punto de la lista es posible llegar a cualquier otro punto. En este caso la lista se llama lista
circular.
encabezado
Pag 69
int VACIA(Nodo p){
VACIA=p->sig==p //Si el que sigue del nodo de encabezado, es l mismo
} entonces no hay datos
Aun cuando una Lista Circular tiene ventajas sobre una Lista Lineal, sta todava tiene algunas
deficiencias, uno no puede recorrer esta lista en direccin contraria, ni tampoco se puede eliminar
un nodo de una lista simplemente ligada circular simplemente un apuntador a ese nodo. En el
caso de que se requieran tener estas flexibilidades la estructura de datos para representar una
lista con apuntadores es la lista doblemente ligada.
Como se mencion anteriormente, cada nodo en esta lista contiene dos apuntadores, uno es
predecesor y el otro a su sucesor. Este tipo de lista puede ser tanto lineal como circular y puede
contener o no un nodo de encabezado.
Pag 70
La estructura de datos para representar este tipo de Lista sera un nodo com un registro con tres
campos, uno para almacenar al elemento de la lista, y dos para almacenar las direcciones de los
nodos siguiente y anterior a uno dado.
Para insertar un dato hay que saber si se quiere insertar a la derecha o a la izquierda, adems de
que la insercin al principio y al final son diferentes, y sucede lo mismo para suprimir.
Encabezado
nil
Pag 72
Lista doblemente ligada circular
Como se puede apreciar, este tipo de lista es similar a una lista Doblemente Ligada Lineal, pero
en esta, el primer nodo (el encabezado) en su campo anterior contiene un apuntador al ltimo
nodo de la lista, mientras que el ltimo nodo en su campo siguiente contiene la direccin del
primer nodo es decir del encabezado.
Encabezado
struct Cola{
Nodo Fondo,Frente;
}
rboles binarios
rbol Binario
Un rbol binario es un conjunto finito de elementos que puede estar vaco o contener un elemento
denominado la raiz del rbol, esta raz contiene cuando mucho un subrbol izquierdo y ubrbol
derecho; los cuales a su vez tambin son rboles binarios. A cada elemento de un rbol binario se
le denomina Nodo del rbol.
Pag 78
Formalmente, un rbol se puede definir de manera recursiva como sigue:
1. Un nodo es, por si mismo, un rbol. Ese nodo es tambin la raz de dicho rbol.
2. Supongamos que n es un nodo y que A1, A2,...Ak son rboles con races n1,n2,...nk,
respectivamente. Se puede construir un nuevo rbol haciendo que n se convierta en el
padre de los nodos n1,n2,..., nk. En dicho rbol, n es la ras y A1,A2,..,Ak son los
subrboles de la raz. Los nodos n1,n2,....nk reciben el nombre de hijos del nodo n.
raz
Subrbol
izquierdo
Subrbol
derecho
Una forma de visualizar un rbol binario es considerar cada nodo conformado por tres campos
fundamentales, uno para almacenar la informacin que contiene el nodo, y dos para almacenar la
direccin del subrbol izquierdo y derecho. Si el subrbol izquierdo o derecho est vaco, contiene
un apuntador nulo o nil.
Pag 79
Representacin ligada
typedef int tipo_elemento;
struct nodo{
Tipo_elemento Info;
Nodo *Izq, *Der
}
Struct Nodo{
int Hijo_izq;
int Hijo_der;
}Espacio_celdas[TAM_NODOS];
La idea es que espacio_celdas[i]. Hijo_izq sea el hijo izquierdo del nodo i, y que suceda lo mismo
con hijo_der. Un valor 0 en cualquiera de esos campos indicar la ausencia de un hijo
void PREORDEN(Nodo R)
if (R!=NULL){
printf(%d,R->info); //Visitamos la raz
PREORDEN(R->izq); //Recorremos el subrbol izquierdo
PREORDEN(R->der); //Recorremos el subrbol derecho
}
}
Grafos
Grafo dirigido
Un grafo dirigido G consiste en un conjunto de vrtices V y un conjunto de arcos A. Los vrtices se
denominan tambin nodos o puntos; los arcos pueden llamarse arcos dirigidos o lineas dirigidas.
Un arco es un par ordenado de vrtces (v, w); y es la cola y w la cabeza del arco. El arco (v, w)
se expresa a menudo como v w va de v a w, y que w es adyacente a v.
Los vrtices de un grafo dirido pueden usarse para representar objetos, y los arcos relacionados
ente los objetos. Por ejemplo, los vrtices pueden representar ciudades y los arcos, vuelos areos
de de una ciudad a otra. Un grafo dirigo puede emplearse para representar el flujo de control en
un programa de computador. Los vrtces representan bloques bsicos, y los arcos posibles
tranasferencias del flujo de control.
Un camino en un grafo dirigo es una secuencia de vrtices v1, v2, ...vn, tal que v1 v2,
v2 v3,.....vn-1 vn.son arcos. Este camino va del vrtices v1 al vrtice vn, pasa por los vrtices
v2, v3,...vn-1 y termina en el vrtice vn. La longitud de un camino es el nmero de arcos en ese
camino, en este caso n-1. Como caso especial, un vrtice sencillo, v, por si mismo denota un
camino de longitud cero de v a v. En la figura la secuencia 1, 2, 4, es un camino de longitud 2 que
va del vrtice 1 al vrtice 4.
1 2
3 4
Grafo dirigido
Pag 82
Un camino es simple si todos los vrtices, excepto tal vez el primero y el ltimo, son distintos. Un
ciclo simple es un camino simple de longitud por lo menos uno, que empieza y termina en el
mismo vrtice. En la figura, el camino 3, 2, 4, 3 es un ciclo de longitud 3.
En muchas aplicaciones es til asociar informacin a los vrtices y arcos de un grafo dirigido. Para
este propsito es posible usar un grafo dirigido etiquetado, en el cual cada arco, cada vrtice o
ambos pueden tener una etiqueta asociada. Una etiqueta puede ser un nombre, un costo o un
valor de cualquier tipo de datos dado.
La siguiente figura muestra un grafo dirigido etiquetado en el que cada arco esta etiquetado con
una letra que causa una transicin de un vrtice a otro. Este grafo dirigido etiquetado tiene la
interesante propiedad de que las etiquetas de los arcos de cualquier ciclo que sale del vrtice 1 y
vuelve e l producen una cadena de caminos a y b en el cual los nmeros de a y de b son pares.
Un grafo dirido etiquetado, un vrtice puede tener a la vez un nombre y una etiqueta. A menudo
se emplear la etiqueta del vrtice como si fuera el nombre. As, los nmeros de la figura pueden
interpretarse como nombres o como etiquetas de vrtices.
a
1 2
a
b b b b
a
3 4
a
Algo muy relacionado con esto es la representacin con matriz de adyacencia etiquetada de un
grafo dirido, donde a[i,j] es la etiqueta del arco que va del vrtice i al vrtice j. Si no existe un
arco de i a j, debe emplearse como entrada para A[i,j] un valor que no pueda ser una etiqueta
vlida.
Pag 83
1 2 3 4
1 a B
2 a b
3 b A
4 b a
La principal desventaja de usar una matriz de adyacencia para representar un grafo dirido es que
requiere un espacio (n) aun si el grafo dirido tiene menos de n arcos. Slo leer o examinar la
matriz puede llevar un tiempo O(n), lo cual invalidara los algoritmos O(n) para la manipulacin
de grafos dirigidos con O(n) arcos.
Para evitar esta desventaja se puede utilizar otra representacin comn para un grafo dirigido
G=(V,A) llamada representacin con lista de adyacencia. La lista de adyacencia para un vrtice i
es una lista, en algn orden, de todos los vrtices adyacentes a i. Se puede representar G por
medio de un arreglo CABEZA, donde CABEZA[i] es un apuntador a la lista de adyacencia del
vrtice i. La representacin con lista de adyacencia de un grafo dirigido requiere un espacio
proporcional a la suma del nmero de vrtices ms el nmero de arcos; se usa bastante cuando el
nmero de arcos es mucho menor que n . Sin embargo, una desventaja potencial de la
representacin con lista de adyacencia es que puede llaeva un tiempo O(n) determinar si existe
un arco del vrtice i al vrtice j, ya que puede haber O(n) vrtices en la lista de adyacencia para
el vrtice i.
La figura muestra una representacin con lista de adyacencia para el grafo dirigido de la primera
figura, donde se usan listas enlazadas sencillas. Si los arcos tienen etiquetas, stas podran
incluirse en las celdas e la lista ligada.
1 2 3
2 4
3 2
4 3
Si hubo inserciones y supresiones en las listas de adyacencias, sera preferible tener el arreglo
CABEZA apuntando a celdas de encabezamiento que no contienen vrtices adyacentes. Por otra
parte, si se espera que el grafo permanezca fijo, sin cambios (o con muy pocos) en las listas de
adyacencia, sera preferible que CABEZA[i] fuera un cursor a un arreglo ADY, donde
ADY[CABEZAA[i]], ADY[CABEZA[i]+1], ..., y as sucesivamente, contuvieran los vrtices
adyacentes al vrtice i, hasta el punto en ADY donde se encuentra por primera vez un cero, el
cual marca el fin de la lista de vrtices adyacentes a i.
Pag 84
Grafos no dirigidos
Un grafo no dirigido G =(V,A) consta de un conjunto finito de vrtices V y de un conjunto de
aristas A. Se diferencia de un grafo dirigido en que cada arista en A es un par no ordenado de
vrtices. Si (v,w) es una arista no dirigida, entonces (v,w) =(w,v).
Los grafos se emplean en distintas disciplinas para modelar relaciones simtricas entre objetos.
Los objetos se representan por los vrtices del grafo, y dos objetos estn conectados por una
arista si estn relacionados entre s.
#include <stdio.h>
struct card {
char *face;
char *suit;
};
main()
{
struct card a;
struct card *aPtr;
a.face = Ace;
a.suit = Spades;
aPtr = &a;
Ace of Spades
Ace of Spades
Ace of Spades
Pag 85