Está en la página 1de 55

Programacin Avanzada

III.2.2 Clasificacin por insercin


........
III.2.3 Clasificacin por seleccin directa
........
III.3 Mtodos de clasificacin avanzados
.......................
III.3.1 Clasificacin por particin
.......................
III.4 Bsqueda lineal
.......................
III.5 Bsqueda Binaria
.......................

INDICE
CAPITULO I
Introduccin a la Programacin Orientada a Objetos
I.1 Introduccin
....................... 2
I.2 Introduccin al lenguaje de programacin
.......................
I.3 conceptos bsicos
.......................
Objeto
.......................
Clases
.......................
Funciones miembro
.......................
Funciones en lnea
.......................
Constructores y Destructores
.......................
Herencia
.......................
Mensajes
.......................
Encapsulamiento
.......................
Polimorfismo
.......................

4
5
5
5
6
6
9
10
11
11
12

CAPITULO II
Recursividad
II.1 Introduccin
II.2 Escritura de funciones recursivas
II.3. Mtodo de las tres preguntas
II.3.1 Aplicacin
II.4 Tipos de recursin
II.5 Recusividad vs. Iteracin

.......................
.......................
.......................
.......................
.......................
.......................

17
18
19
19
20
22

II.6 La pila de recursin

....................... 23

II.7 Ventajas e inconvenientes

....................... 23

CAPITULO III
Mtodos de Ordenamiento y Bsqueda
III.1. Introduccin
....................... 24
III.2 Clasificacin interna
....................... 24
III.2.1 Clasificacin por intercambio directo
........ 25

28
29
29
30
31
31

CAPITULO IV
Estructuras de Datos
IV.1. Introduccin
.......................
IV.2 Pilas
.......................
IV.2.1 Representacin
.......................
IV.2.2 Operaciones PUSH
.......................
IV.2.3 Operaciones POP
.......................
IV.3 Colas
.......................
IV.3.1 Representacin
.......................
IV.3.2 Operaciones
.......................
IV.3.3 Comportamiento de los apuntadores
........
IV.3.4 Operacin de insercin
.......................
IV.3.5 Operacin de eliminacin
.......................
IV.4 Cola Circular
.......................
IV.5 Listas
.......................
IV.5.1 Operaciones
.......................
IV.5.2 Notacin
.......................
IV.5.3 Listas sencillamente ligadas
.......................
IV.5.3.1 Operacin de Insercin
.......................
IV.5.3.1 Operacin de Eliminacin
.......................

Bibliografa

32
32
33
34
34
37
37
38
38
38
39
40
42
42
42
43
44
46

....................... 52

Programacin Avanzada

,ntroduccin a la
3rogramacin
2rientada a 2bjetos
Capitulo I

I.1 INTRODUCCIN

Aunque ya han pasado algunos aos la Orientacin a Objetos sigue


siendo un trmino de moda. En 1967 fue desarrollado SIMULA, un
lenguaje para aplicaciones de simulacin, considerado por muchos el
precursor en la introduccin del concepto de objeto.
Lamentablemente este nacimiento en Noruega pas inadvertido para
gran parte de la familia de los programadores. Resulta que ahora
tenemos un nio de ms de 25 aos que muchos se apuran en
querer rebautizar.
Por aquel entonces se hablaba de la crisis del software que
provocara el surgimiento de la Programacin Estructurada. Las
grandes brigadas de programadores que programaban los
grandes sistemas para las grandes mquinas enfrentaban serios
problemas de organizacin y productividad. La respuesta fue una
metodologa que promova una solucin jerrquica, disciplinada,
organizada y planificada! para desarrollar el software. Algunas
mejoras fueron introducidas en los lenguajes de programacin para
facilitar esto: mejores estructuras de control para obviar el goto,
algunos recursos de modularidad y de organizacin de bibliotecas de
programas.
Esto pareci ser suficiente durante los 70s. No obstante, pocos
sistemas lograban terminarse, pocos se terminaban cumpliendo los
requerimientos iniciales y no todos los que se terminaban cumpliendo
los requisitos iniciales se usaban segn lo planificado. El problema
(mal llamado de mantenimiento) consista en cmo adaptar el
software a nuevos requerimientos imposibles de haber sido
planificados inicialmente. La estructuracin facilitaba en todo caso
la zambullida de los programadores de mantenimiento en los mares
de lneas de programa fuente, pero no la impeda.
Este alto grado de planificacin y previsin es contrario a la propia
realidad. El hombre aprende y crea a travs de la experimentacin, no
de la planificacin. Se necesitan medios que faciliten la

Programacin Avanzada

experimentacin y no que exijan que tenga que ser planificado un


proyecto entero antes de poder escribir una lnea de programa para
que luego este proyecto se convierta en una camisa de fuerza en el
desarrollo y evolucin del sistema. El desarrollo de SMALLTALK a
finales de los 70s fue una respuesta a este problema.
El desarrollo tcnico del hardware, su disminucin de precios y la
explosin de las computadoras personales fue el detonante final.
La Programacin Orientada a Objetos (P00), que por todo lo
anterior algunos han dado en la Programacin Estructurada de los
90s, encuentra aqu un terreno frtil. Es la POO un mejor paradigma
que otros? En cierto sentido s lo es. Es una cura de todos nuestros
problemas? No lo es. Significa que la arriba mencionada crisis del
software desaparecer? Probablemente no. Pero entonces, qu es lo
grande de la Programacin Orientada a Objetos?.
En lugar de tratar de modelar un problema en algo familiar a la
computadora se trata ahora de acercar la computadora al problema.
Es decir, modelar la realidad del problema a travs de entidades
independientes pero que interactan entre s y cuyas fronteras no
estn determinadas por su instrumentacin computacional sino por la
naturaleza del problema. Estas entidades sern denominadas objetos,
por analoga con el concepto de objeto en el mundo real.
Resolver problemas consiste en definir objetos y sus acciones y
entonces invocar las acciones enviando mensajes a los objetos que
ocultan las caractersticas internas d como llevan a cabo estas
acciones. Esta forma de resolver problemas luce familiar y lgica y
ha sido utilizada por otras disciplinas cientficas ya que en nuestra
experiencia diaria nosotros manipulamos objetos.
Programar en un lenguaje de programacin orientado a objetos es
definir clases (nuevos tipos de datos) que expresan una

determinada funcionalidad la cual es comn a todos los individuos de


una clase. A travs de esta funcionalidad los objetos o instancias
concretas de una clase dan respuesta a las solicitudes (mensajes) que
les envan otros objetos. Las clases deben ser lo suficientemente
CERRADAS como para
que cada objeto pueda ocultar la
informacin (datos) que lo caracteriza como individuo. Es un
problema interno del objeto cmo llevar a cabo la funcionalidad
descrita en la clase.
Visto en la ptica de las arquitecturas convencionales de
computadoras, en la POO los datos no circulan abiertamente por todo
el sistema como en la programacin tradicional. Los programas no se
dividen en declaraciones pasivas de estructuras de datos y funciones
(que tal vez acten sobre algunas de las estructuras de datos). Los
datos estn ahora encerrados dentro de cada objeto y ste es quien
decide internamente cmo trabajar con ellos para dar respuesta a una
solicitud de otro objeto.
Por otra parte estas clases deben ser lo suficientemente ABIERTAS
para permitir la reutilizacin, adaptacin y extensin de las mismas a
nuevas funcionalidades, sin correr el riesgo de afectar el
funcionamiento de lo que ya est correcto.
Esta aparente contradiccin, de lo que se conoce como principio
ABIERTO CERRADO, es la piedra angular de la POO.
En ausencia de una definicin formal de qu es la POO, algunos
prefieren identificarla por sus objetivos. Tres objetivos
fundamentales persigue la POO para facilitar la experimentacin:

La robustez de las partes que garanticen su integridad y


funcionamiento propio (lo cual a su vez facilita arrinconar
las fallas). Esto se facilita en los lenguajes orientado a

Programacin Avanzada

objetos (LOO) a travs de recursos como el encapsulamiento


y el manejo de excepciones.
La reusabilidad y la extensibilidad. Que se pueda derivar
(ms que definir) nuevas clases de objetos a partir de las ya
existentes, facilitndole con ello al programador el desarrollo
de prototipos y una rpida exploracin en las nuevas ideas.
Esto se facilita en los LOO mediante la redefinicin de
operadores y funciones, la generalidad, la herencia y el
polimorfismo.

Smalltalk, Eiffel y Actor principalmente, mientras que los lenguajes


OO hbridos son aquellos que aaden las propiedades OO a las
propiedades intrnsecas de tipo procedimental. Entre los lenguajes
orientados a objetos hbridos se destacan Objetive-C, Object-Pascal,
Turbo Pascal (versiones 5.0, 6.0 y 7.0) y C++ (versiones Turbo C++,
Microsoft C/C++ 7.0, Borland C++ 3.1, Zortech C++ 3.1, Visual
C++, Symantec C++ 6.0, etc.).

I.2 INTRODUCCION AL LENGUAJE DE PROGRAMACION


Esta bsqueda de la comunidad, de aprovechar lo existente, es una de
las caractersticas bsicas de la POO. Algunos de estos recursos
como el polimorfismo y la jerarqua de clases a travs de la herencia
nos dotan de recursos para clasificar lgicamente a los objetos,
evitando las redundancias y obviando restricciones que otros
paradigmas de programacin nos imponen.

I.1 LOS LENGUAJES DE PROGRAMACIN ORIENTADOS


A OBJETOS

C++ se deriva del lenguaje C. Estrictamente hablando es un


superconjunto de C. El grfico 1.1 muestra los conjuntos C++.

Caractersticas
de C++ que no
residen en C.

Otras
caractersticas
tiles
Lenguaje C++
Lenguaje C

Un gran nmero de lenguajes ha contribuido a la proliferacin de las


tcnicas orientadas a objetos. Las versiones iniciales de Lisp en la
dcada de los cincuenta y Simula en la dcada de los sesenta,
sentaron las bases para el nacimiento de Smalltalk que al principio
de los setenta supuso el asentamiento definitivo de la filosofa
orientada a objetos. Smalltalk-80, la versin ms popular de
Smalltalk, y la aparicin de extensiones orientada a objetos de dos
lenguajes populares, C y Pascal (recientemente se ha incorporado
Visual Basic), han acelerado rpidamente la implantacin de la POO
dentro de lo que hoy se conoce ingeniera del software.
Los lenguajes orientados a objetos (LOO) se dividen en dos grandes
grupos: puros e hbridos. Los lenguajes OO puros incluyen

Caractersticas de C
no utilizadas
normalmente en C++
Caractersticas
comunes a C y C++

Programacin Avanzada

Figura 1.1. C++ es un superconjunto de C.


C++ fue desarrollado por Bjarne Stroustrup en Bell Laboratories.
Comenz su trabajo a principios de los ochenta en respuesta a la
necesidad de disear un lenguaje de simulacin que tuviera las
caractersticas de programacin orientada a objetos; por aquel
entonces un relativamente nuevo paradigma de programacin. En
lugar de disear un nuevo lenguaje, decidi aadir las caractersticas
deseadas al lenguaje C, que ya estaba bien definido.
Tras desarrollar C con clases (as se llamo la primera versin de
C++) tom una decisin histrica: desarrollar el compilador C++
como un programa traductor que procesa lenguaje fuente C++ en un
lenguaje fuente C. El cdigo fuente C traducido se compilaba
entonces en cualquier computadora que soportase C. Llamo a este
programa traductor Cfront . El cdigo fuente de C++ ha pertenecido
a AT&T, as como las versiones posteriores.

I.3 CONCEPTOS BSICOS


POO (Programacin orientada a objetos)
POO es un importante conjunto de tcnicas que se pueden utilizar
para hacer el desarrollo de programas ms eficiente mientras se
mejora la fiabilidad de los programas resultantes. En esencia, POO es
un nuevo, medio de enfocar el trabajo de programacin.

OBJETO
Un objeto es, primero que todo, una abstraccin del mundo real.

Un objeto es, en trminos computacionales, la representacin en


memoria de la abstraccin mencionada, y como tal, un ente
encapsulado que contiene datos y mtodos, y que es capaz de recibir
mensajes del exterior.

CLASES
A pesar de que los trminos Clase y Objeto se mezclan entre s en la
literatura dedicada, a la programacin Orientada a Objetos, para
nuestros propsitos habr una semntica definida y diferenciada de
cada uno de ellos.
Una clase es un tipo definido por el usuario. Generaliza el concepto
de estructura y lo reemplaza con ventaja.
En otras palabras, una clase es un prototipo que define los mtodos y
datos que sern incluidos en un tipo de objeto particular. Esta ltima
definicin, seala ya la distincin entre Clases y Objetos, pues los
ltimos no son ms que instancias de los primeros.
Las clases son estructuras que contienen no slo declaraciones de
datos, sino tambin declaraciones de funciones. Las funciones se
conocen como funciones miembro, e indican qu tipos de cosas
puede hacer una clase.
Para usar una clase, primero tiene que declararla, como se hace en el
caso de estructuras. La declaracin completa de una clase puede
aparecer slo una vez en un programa, tal y como en las estructuras.
Esta es la sintaxis de una declaracin de una clase :

class nombre_de_la_Clase
{
funciones y datos privados

Programacin Avanzada

public:
mtodos(funciones) y
datos pblicos
} lista_de_objetos;

(::) Operador de resolucin de alcance quien le indica al compilador


que la versin de la funcin cuyo identificador precede al
mencionado operador, es la de la Clase en s.

La lista_de_objetos, puede no aparecer si lo nico que se


desea es declarar una determinada Clase.
Ejemplo de una clase es:
class persona {
public:
char nombre[25];
char apellidos[30];
char ciudad[20];
char provincia[20];
char codpostal[10];
char leer_infor( );
char visualizar( );
Muestra_Infor( );
};
y un objeto, una variable o una instancia de la clase Persona:
Persona comprador;

FUNCIONES MIEMBRO
Los mtodos de la clase tambin se denominan funciones miembros
si son la nica forma de accesar a los datos privados de la clase.

FUNCIONES EN LINEA
Una funcin en lnea (inline), es una funcin que es expandida en
lnea cuando es llamada, en lugar de realizar el proceso de construir
un llamado a funcin.
La razn para usar funciones en lnea es la eficiencia y existen dos
formas de declarar una funcin en lnea: La forma explicita y la
forma implcita.

include <iostream.h>
class Vector
{
int c[10];
int e; public:
// definimos la funcin inicia en linea
// en forma implicita
void inicia(void) {e=0;}
void pon_dato(int i); void suma(Vector x, Vector y ); void
Visualizar(void);};
/* Cdigo en linea para la funcin inicia de la clase vector, forma
explicita */
Inline void Vector::inicia (void)
{
e=0;
}

Programacin Avanzada

public:
void leer datos();

//interfaz pblico

Control del acceso a una clase

};

La tarea de una clase consiste en ocultar la mayor cantidad de


informacin posible. Por lo tanto es necesario imponer ciertas
restricciones a la forma en que se puede manipular una clase, y la
forma en que se pueden utilizar los datos y el cdigo contenidos en la
misma.

El especificador private es opcional y no es necesario ponerlo en la


sintaxis de la clase.

Existen tres tipos de usuarios de una clase:


1. La clase misma
2. Usuarios genricos
3. Clases derivadas
Cada tipo de usuario tiene diferentes privilegios de acceso. Cada
nivel de privilegio de acceso est asociado con una palabra clave.
Como existen tres niveles, hay tres palabras clave:
1. private
2. public
3. protected

Miembros de Clase private


//Ejemplo Programacin orientada a objetos
//Clase Private

Cada declaracin contenida en el cuerpo de una clase define de


manera implcita un privilegio de acceso apareciendo en una seccin
precedida de una de estas tres palabras clave. Si no se utiliza ninguna
de esas palabras, todo es private por omisin.
class test
{
private:
int datos;

class articulo
{
float precio;
//privado por defecto
char nombre;
//privado por defecto
public:
void leer indicar();
};

#include<stdio.h>
//Definicin de una clase
class PublicExample
{
int variable;
void function();
};
void PrivateExample::function() {}

//datos privados

void main()

Programacin Avanzada

{
PrivateExample object;
object.variable = 1;
//variable no accesible
int i = object.variable; //variable no accesible
object.function();
printf(" i=%d ",i);
}

//variable no accesible

Miembros de Clase protected


Cuando se define una clase que se utiliza subsiguientemente como
clase de base para otras clases, se puede hacer que los miembros
estn accesibles slo para funciones de las clases derivadas mediante
el uso de la palabra clave protected. Considere una jerarqua de
objetos, como se ilustra en la figura 1.2.

Miembros de Clase public


//Ejemplo Programacin orientada a objetos
//Clase Public
#include <stdio.h>
class PublicExample
{
public:
int variable;
void function();
};
void PublicExample::function() { }
void main()
{
PublicExample object;
object.variable = 1;
int i = object.variable;
object.function();
printf(" i=%d ",i);
}

class A:
protected:
int value_a;
class B: public A
public:
void FB();
class C: public B
public:
void FC();
Figura 1.2. Jerarqua de clases.
La jerarqua de la figura 1.2 se puede expresar con cdigo de esta
manera:
class A{
protected:
int value_a;
};

Programacin Avanzada

class B: public A{
public:
void FB();
};
class C: public B{
public:
void FC();
};
La propiedad de ser protected se extiende indefinidamente hacia
abajo en un rbol de herencia, en tanto que se declare que las clases
derivadas tengan clases de base public. Con este hecho en mente,
cualquier funcin miembro de la clase C o B puede tener acceso al
miembro de datos protected, value_a, de su clase de base A; pero
slo a travs del apuntador this.

Por ejemplo, el cdigo siguiente es aceptable:


void B: :FB
{
value_a =0;
// se accede a travs de este apuntador
}
void C::FC(){
value_a=0
// tambin se accede a travs de este apuntador
}

Operador this
Nunca se puede llamar a una funcin miembro de una clase a menos
que se asocie con un objeto (una instancia de la clase). En ANSI C

10

cada vez que se utiliza un puntero para acceder a los miembros de


una estructura, debe utilizarse el operador de puntero (->) para
acceder a los objetos de datos. Cmo sabe una funcin miembro
cul es la instancia de una clase (el objeto especfico) asociada con
ella?
El mtodo utilizado por C++ es aadir un argumento extra oculto a
las funciones miembro. Este argumento es un puntero al objeto de la
clase que lo enlaza con la funcin asociada y recibe un nombre
especial denominado this.

CONSTRUCTORES
Y DESTRUCTORES
C++ permite a los Objetos inicializarse por s mismos en el momento
de su creacin. Esta inicializacin automtica se lleva a cabo a travs
del uso de las funciones Constructores.
Un Constructor, es una funcin especial que es miembro de la Clase
y que lleva el mismo nombre que ella.
Un Constructor no debe regresar ningn tipo.
Un Destructor es similar al constrictor pero se le antepone el smbolo

#include <iostream.h>
// Clase pila_car para modelar una Pila de caracteres
class pila_car
{
int size; char* tope, s; public:
pila_car(int sz) {tope = s = new char[size = sz];}
//CONSTRUCTOR

Programacin Avanzada

~pila_car() {delete s;} //DESTRICTOR


void push(char c) { *tope++ = c;}
char pop() { return *--tope;}
};

11

bsicas. C++ es diferente de algunos lenguajes orientados por


objetos, ya que no slo admite la herencia individual, sino tambin la
herencia mltiple, la cual permite la derivacin de una clase de ms
de una clase del mismo tipo, heredando comportamientos de todos
sus ancestros.

CREACIN DE UNA CLASE DERIVADA

HERENCIA
Es un mecanismo por el cual, una clase de Objetos puede expresarse
como un caso especial de una Clase ms general, con lo cual incluye
automticamente toda la definicin de datos y mtodos de la clase
general.

Cada clase derivada se debe referir a una clase base declarada


anteriormente. Esta clase base puede ser precompilada o puede ser
definida en el mismo programa en que la clase derivada se crea. Si no
se define la clase antes que la clase derivada, se debe, al menos,
declarar el nombre de la clase base primero como una referencia
anticipada. De hecho, sintcticamente la clase base es como cualquier
otra clase, y por consiguiente, cualquier clase puede servir como
base.
La declaracin de una clase derivada tiene la siguiente sintaxis:
class tipo clase_derivada : <especificadores_acceso> clase base

La herencia es probablemente la caracterstica de C++ que da mayor


poder al concepto de clase. En C++, el trmino herencia se aplica
slo a clases y sus caractersticas. Las variables no se pueden heredar
de otras variables, y las funciones tampoco pueden heredar de otras
funciones. La herencia le permite construir y extender continuamente
clases desarrolladas por usted o por alguien ms, bsicamente sin
lmite. Partiendo de la clase ms simple, se pueden derivar clases
cada vez ms complejas que no slo son fciles de depurar, sino que
tambin son simples por si solas.
Cada vez que se deriva una nueva clase partiendo de la anterior, se
pueden heredar algunas o todas las caractersticas de las clases
primarias o progenitoras, agregando nuevas segn necesiten. Un
proyecto completo puede tener clasificaciones o cientos de clases

{
declaraciones de miembros
};
Los especificadores de acceso pueden ser los ya conocidos public,
protected o private.
Una clase derivada de la clase base comida es la clase hamburguesa:
class hamburguesa : public comida
{
declaraciones de miembros

Programacin Avanzada

Atributos
public clase base:

private clase base:

protected clase base:

Descripcin
Los miembros pblicos de la clase base
son miembros pblicos de la clase
derivada. Los miembros protegidos de la
clase base son miembros protegidos de la
clase derivada. Los miembros privados de
la clase base permanecen privados a la
clase derivada.
Todos los miembros pblicos y protegidos
de la clase base son miembros privados de
la clase derivada. Los miembros privados
de la clase base son privados en la clase
derivada.
Los miembros public y protected de la
clase base son miembros protegidos de la
clase derivada. Los miembros privados de
la clase base son privados de la clase
derivada.

12

derivada. Se pueden especificar tres modificadores de una clase:


public, private, protected.
Colocando la palabra reservada public delante del nombre de la clase
base, significa que todos los miembros public y protected de la clase
base sern miembros public y protected de la clase derivada.
Se puede especificar tambin una palabra reservada private delante
del nombre de la clase base. En este caso, todos los miembros public
y protected de la clase base se convierten en miembros privados de la
clase derivada. Por ltimo cuando la palabra reservada protected se
sita antes del nombre de la clase, todos los miembros public y
protected se convierten en miembros protegidos de la clase derivada.
La siguiente tabla resume todos los especificadores del acceso.
Especificadores de acceso

};
En este caso la etiqueta de la clase derivada es hamburguesa. La
clase padre o base tiene visibilidad pblica y su etiqueta (nombre) es
comida.
Es especificador public significa que todos los miembros pblicos de
la clase base (alfa) son tambin miembros pblicos de beta.

ACCESO A LA CLASE BASE


Cuando una clase hereda de otra, la clase derivada hereda todos los
datos y funciones pblicos de la clase base. Por consiguiente, slo
tiene que especificar los datos y funciones adicionales a la clase

MENSAJES
La forma en que los Objetos interactan entre si, es envindose
mensajes pidiendo que se active (ejecute) un Mtodo especfico.
Un mensaje consiste simplemente del nombre del Objeto a quien va
dirigido, seguido del nombre del Mtodo que el receptor sabe como
ejecutar. Si el mtodo requiere informacin adicional, el mensaje
incluye parmetros.
Conceptos tales como Transmisor y Receptor, identifican a los
Objetos que envan y reciben los mensajes.

Programacin Avanzada

Un mensaje, en trminos conocidos, es una llamada a un


procedimiento inmerso en un Objeto.

ENCAPSULAMIENTO

13

El polimorfismo es soportado en tiempo de compilacin por algunos


lenguajes, en tiempo de ejecucin por otros, y en mbos, por otros
ms. El polimorfismo en tiempo de compilacin, identifica a
trminos tales como: Sobrecarga de Operadores, Sobrecarga de
funciones y Sobrecarga de Constructores. Por su parte, el
polimorfismo de Herencia, y las Funciones Virtuales.

Mecanismo por medio del cual, un Objeto esconde sus Datos y


Mtodos al mundo exterior.

SOBRECARGA DE FUNCIONES

El encapsulamiento permite proteger los Datos de transformaciones


no deseadas y solo bajo autorizacin del propio objeto, los mtodos
propios y los procedimientos externos, pueden alterar valores de los
datos de un objeto.

El primer mecanismo de Polimorfismo en un lenguaje de


programacin, lo constituye la sobrecarga de funciones. En C++, dos
o ms funciones pueden tener el mismo nombre, difiriendo solamente
en los parmetros de su declaracin.

Los paquetes del lenguaje ADA son un buen ejemplo de


encapsulamiento, y mucha de la facilidad para la reusabilidad del
cdigo carta de presentacin de ADA- , se debe al encapsulamiento
donde no es necesario saber como est construido para sacar
provecho de l.
Es claro que una de las tcnicas del empaquetamiento del software,
las bibliotecas de funciones, salen beneficiadas con la posibilidad de
obtener reusabilidad del cdigo ya elaborado.

Las funciones que comparten nombre, pero que declaran parmetros


diferentes, se dicen que estn Sobrecargadas, y al proceso de
construir estas funciones se le denomina Sobrecarga de Funciones.

POLIMORFISMO
La posibilidad de que un nombre (identificador), pueda ser usado con
diferentes propsitos, aunque relacionados semnticamente, se
denomina polimorfismo.
Polimorfismo es el trmino usado para describir el proceso por el
cual, diferentes implementaciones de una funcin, pueden ser
accesadas usando el mismo nombre. La frase una interfaz, mltiples
mtodos, caracterizan este proceso.

Por lo general, casi todos los lenguajes contienen sobrecarga de


funciones (en realidad como veremos despus, sobrecarga de
operadores), pues por ejemplo, en Pascal, la funcin (operador)
suma, est sobrecargado y soporta diferentes parmetros, como se
observa en los ejemplos siguientes:
integer + integer
real + real
string + string
Pero no slo los operadores intrnsecos de un lenguaje estn
sobrecargados, el usuario de C++ puede crear sus propias funciones
sobrecargadas, como se ilustra con la funcin pow(x,y) definida
como xy , a la que sobrecargaremos para los siguientes tipos:
int pow (int, int);
double pow(double, double);

// existe en <math.h>

Programacin Avanzada

complex pow(double, complex); // existe en <complex.h>


complex pow(complex, int);
complex pow(complex, double);
complex pow(complex, complex);
Una funcin k que invoque algunos de los casos anteriores, se
presenta a continuacin, en ella se sealarn las funciones asociadas.

void k (complex z)
{
int i = pow (2,2);
// invoca a pow (int, int)
double d = pow (2.0,2);
// invoca a pow (double, double)
complex z1 = pow (2,z); // invoca a pow (double, complex)
complex z2 = pow (z,2); // invoca a pow (complex, int)
complex z3 = pow (z,z); // invoca a pow (complex, complex)
}

SOBRECARGA DE CONSTRUCTORES
Siendo
los
constructores
por
naturaleza
funciones,
independientemente del servicio nico que presentan a los Objetos,
tambin pueden ser sobrecargados.

14

Como en el caso de las variables, Inicializacin Dinmica significa


asignar un valor a un parmetro que slo es conocido en tiempo de
ejecucin y por lo tanto, desconocido al momento de la compilacin.
# include <iostream.h>
# include <stdlib.h>
# include <time.h>
class timer
{
int segundos;
public:
// Segundos especificados como una cadena
timer (char *t) { segundos = atoi (t); }
// Segundos especificados como una entero
timer (int t) { segundos = (t); }
// Tiempo especificado en minutos y segundos
timer (int min, int seg) { segundos = min * 60 + seg; }
void run (void);
};
void timer::run (void)
{
clock_t t1,t2;
t1 = t2 =clock ( )/ CLK_TCK;
while (segundos)
{ if (t1 / CLK_TCK + 1 <= (t2 = clock ( )/ CLK_TCK))

Para sobrecargar el constructor de una Clase, simplemente debemos


declarar las diferentes formas que debern tomar, y definir su accin
relativa a cada una de ellas.

{ segundos --;
t1 = t2;
}
}

El siguiente ejemplo muestra la sobrecarga de los constructores de


una Clase timer donde mostraremos adems, una caracterstica
importante del lenguaje C++ denominada inicializacin dinmica.

cout << \a ; // Cdigo ASCII de la campana


}

Programacin Avanzada

main (void)
{ timer a (10);
a.run ( );
cout << Dar nmero de segundos: ;
char str [80]; // Especificacin de variable
cin >> str;
timer b (str); // Inicializacin Dinmica
b.run( );
cout << Dar tiempo en minutos y segundos: ;
int min,seg; // Especificacin de variables
cin >> min >> seg;
timer c (min,seg); // Inicializacin Dinmica
c.run( );
return ( );
}
Otra de las mejoras de C++ sobre C, se puede observar en el cdigo
anterior, donde se han sealado dos casos de especificaciones de
variables, en cualquier parte del cdigo, y no nicamente en el
encabezado como es tradicional.

15

Para sobrecargar un operador, debemos definir su significado,


relativo a la Clase sobre la cual se aplica. Es decir, la sobrecarga de
operadores redefinen la semntica de un operador relativo a una
Clase, en la que se encuentra definido.
La forma general de una funcin operador es:
tipo nombre_de_la_Clase :: operator# (lista de argumentos)
{
// operacin definida relativa a la Clase
}
Las funciones operadores, debern ser funciones miembros o
funciones amigas de la Clase en la que sern usadas.
Aunque similares, existen diferencias importantes entre la manera en
que es sobrecargado un operador, como funcin miembro y como
funcin amiga.
El siguiente ejemplo, muestra la Clase punto (en el plano) y tres
operadores asociados a ella: el operador suma (+), el operador de
igualdad (=) y el operador de autoincremento posterior (++).
Construiremos el cdigo, en cada caso, requerido para sobrecargar
estos operadores como funciones miembros y como funciones
amigas.

SOBRECARGA DE OPERADORES
La Sobrecarga de Operadores, es otro modo de implementar
sobrecarga de funciones (Polimorfismo), aunque por la sintaxis de los
operadores, debemos hacer algunas consideraciones adicionales.

# include <iostream.h>
// Clase punto con sobrecarga de operadores como funciones
//miembros
class punto
{

Programacin Avanzada

int x, y; // Coordenadas del punto


public:
punto operador+ (punto op2); //op1 esta implcito
punto operador= (punto op2); //op1 esta implcito
punto operador++ (void); // op1 esta implcito tambin
void muestra (void);
void asigna (int nx, int ny);
};

// Clase punto mostrando la sobrecarga del operador +


// como una funcin
# include <iostream.h>
class punto
{
int x, y; // Coordenadas del punto
public:
friend punto operador + (punto op1, punto op2);
//
(Igual que en el caso anterior)
};

La definicin de los operadores se presenta a continuacin:

// Operador + como una funcin miembro


punto punto:: operador + (punto op2);
{

16

punto temp;
temp.x = op1.x + op2.x;
temp.y = op1.y + op2.y;
return temp;
};
// Operador + como una funcin amiga
punto operador + (punto op1, punto op2);
{
punto temp;
temp.x = op1.x + op2.x;
temp.y = op1.y + op2.y;
return temp;
};

Los otros dos operadores se mantienen igual en los dos casos. Es


importante sealar que en el cdigo de ellos aparecer un apuntador
especial, denominado this.
Cada vez que una funcin miembro es invocada, se le pasa de manera
automtica un apuntador al Objeto que la invoca, el mencionado
apuntador est disponible a la funcin invocada usando el
identificador this. El apuntador this es, en esencia un apuntador
implcito a todas las funciones miembros.

// Operador = como una funcin miembro


punto punto::operador = (punto op2);

Programacin Avanzada

17

Para clarificar un poco ms los conceptos anteriores, analicemos, por


ejemplo, el significado de la proposicin:
a++

x = op2.x;
y = op2.y;
return *this;
};
// Sobrecarga de un operador unario (operador ++)
punto punto::operador ++ (void);
{
x ++;
y ++;
return *this;
};

Digamos que expresada en palabras, la semntica de la expresin


anterior se describe como: tome el valor de la variable a, e
incremntelo en uno, indique el nuevo valor.
Si asociamos ahora el operador autoincremento a un Objeto O, el
significado de la operacin O++, deber ser algo semejante al
siguiente: tome el objeto O e incremente sus datos en uno, indique
el nuevo valor del Objeto O.
Visto as, es ahora claro el significado de la proposicin return *this,
encontrada en el cdigo de los operadores de igualdad y de
autoincremento, para cada uno de los Objetos punto.

Si observamos el cdigo de los operadores anteriores (=,++),


notaremos en primer trmino expresiones de la forma:
x = op2.x
que en realidad corresponden a la notacin compacta de la expresin:

En forma similar, la expresin a = b, significa: tome el valor de la


variable b y almacnelo en la variable a, indique el valor de la
variable a. Expresada en dos Objetos O1 y O2, la proposicin O1 =
O2,significa: tome el valor del Objeto O1, almacnelo en el objeto
O2 e indique el valor del Objeto O1.

this -> x = op2.x


Por otro lado, el regreso de los operadores (=, ++), est especificado
por la proposicin:
return *this
Si asociamos los dos casos anteriores, veremos que en efecto, el
apuntador this es un apuntador al Objeto mismo, por lo que puede
usarse como apuntador al valor de regreso (en este caso el Objeto
mismo) de ambos operadores.

Otro detalle que hay que notar es que en realidad, el uso de un


operador (unario o binario), es prerrogativa de un Objeto, por lo que
O1 = O2 debers interpretarse como: El Objeto O1 llamar al
operador de igualdad (=)(que es una funcin), con el parmetro O2.
Anlogamente O1++ significar que el Objeto O1 llama al
operador de autoincremento para operar sobre si mismo.
Con las condiciones anteriores, es ahora simple entender el valor de
un apuntador al Objeto mismo y la importancia de poder contar con
l.

Programacin Avanzada

18








Dos detalles deben considerarse, conociendo el significado de la


op es un operador
expresin op
cualquiera, es claro que la expresin O = O + 10, para cualquier
Objeto O, es unja expresin que no tiene problema alguno, pero que
por su parte, si rescribimos la expresin anterior como O = 10 + O,
obtenemos una expresin que no funciona. La razn de la falla en la
expresin anterior, est en el significado de la operacin, en este
caso, la constante 10 no puede llamar al operador +.
La solucin al problema anteriormente planteado, est dada si
usamos funciones amigas para implementar el operador +, ya que una
implementacin de esa naturaleza, permite expresar los dos
parmetros con sus respectivos tipos.

Programacin Avanzada

19

II.1 INTRODUCCIN
La recursividad es una tcnica en la que una funcin se hace llamadas
as misma en el proceso de la realizacin de sus tareas.
La recursividad da al programador una herramienta potente para
resolver ciertos tipos de problemas reduciendo complejidad u
ocultando los detalles del problema.
Una funcin recursiva es una funcin que se llama as misma, ya sea
directa, o indirecta, por lo cual se puede considerar

5ecursividad
Capitulo II

Primero consideraremos la recursividad directa, que es cuando una


funcin se llama as misma la cual considera dos elementos: el Caso
Base ( fin de recursin ) y el Caso General (Parte puramente
recursiva).
Caso base: Es el caso ms simple de una funcin recursiva, y
simplemente devuelve un resultado. ( el caso base se puede
considerar como una salida no recursiva).
Caso general : Relaciona el resultado del algoritmo con resultados
de casos ms simples. Dado que cada caso de problema aparenta o se
ve similar al problema original, la funcin llama una copia nueva de
si misma, para que empiece a trabajar sobre el problema ms
pequeo y esto se conoce como una llamada recursiva y tambin se
llama el paso de recursin.
El paso de recursin tambin incluye la palabra reservada return,
porque su resultado ser combinado con la parte del problema que la
funcin resolvi, para formar un resultado que ser regresado al
llamado original, posiblemente main.
La recursividad se puede definir mejor mediante el clsico ejemplo
de la funcin factorial.

Programacin Avanzada

Ejemplo 1. Factorial
0! = 1, 1!=1 (Caso Base)
Sea n! = n * (n-1) * (n-2) *...... * 1, si n>O (Caso General)
Supongamos que buscamos el valor de 4!, como 4 >0 entonces
usamos la segunda parte de la definicin:
4! = 4 * 3 * 2 * 1 = 24
A continuacin se presentan las funciones en modo iterativo y
recursivo
ITERATIVO:
int Factorial( int n )
{
int i, res=1;
for(i=1; i<=n; i++ )
res = res*i;
return res;
}

RECURSIVO:
int Factorial( int n )
{
if(n==0) return(1);
return(n*Factorial(n-1));
}

20

Podemos observar que incluso la funcin recursiva utiliza menos


cdigo de programacin y no emplea ninguna estructura de
repeticin.
II.2 ESCRITURA DE FUNCIONES RECURSIVAS

MTODO
1. Primero, obtener una definicin exacta del
problema a resolver. (Esto, por supuesto, es el primer
paso en la resolucin de cualquier problema de
programacin)
2. A continuacin, determinar el tamao del
problema completo que hay que resolver. Este
tamao determinar los valores de los parmetros en
la llamada inicial a la funcin.
3. Tercero, resolver el caso base en el que el
problema puede expresarse no recursivamente. Por
ltimo, resolver el caso general correctamente en
trminos de un caso ms pequeo del mismo
problema, una llamada recursiva.
Ejemplo: Analizar la funcin factorial utilizando el mtodo anterior.
DEFINICIN : Obtener el factorial de un nmero entero, utilizando
la formula
TAMAO : Los enteros (rango mximo de los enteros)
CASO BASE:
1) Cuando n-- 0
nfact = retum (1)
CASO GENERAL: 2) Cuando se llama a la funcin con un
parmetro disminuido nfact (n-1)

Programacin Avanzada

21

3) nfact <- n * nfact( n-1)


una vez aclarado quien es el caso base y quien el caso general, la
codificacin ya es simple como se observa al realizar e programa:
//Programa que calcula el factorial de un entero en C++
#include < iostream.h>
int nfact(int n);
int main()
{
int n, factorial;
cout "Dame el nmero al cual deseas obtener su factorial ;
cout "\n\n"
factorial = nfact(n);
cout n "! Es igual a " factorial "\n";
retum 0;
}

int nfact(int n)

3! = 3*2 =
2!= 2 *1 =
1! = 1
(a)
a)Secuencia de llamadas recursivas
cada llamada recursiva.

(b)
b) Valores regresados de

II.3 MTODO DE LAS TRES PREGUNTAS

Utilizaremos este mtodo para verificar que una solucin recursiva


funciona, Para comprobar que la solucin funciona, debe ser capaz de
contestar "si' a las siguientes preguntas

1.
La pregunta Caso-Base: Hay una salida no
recursiva de la funcin, y la rutina funciona correctamente
para este caso base? .
2.
La pregunta llamador-Ms Pequeo : Cada llamada
recursiva se refiere a un caso ms pequeo del problema
original?

{
if (n==O)
retum(I);
caso base
else
retum(n * nfact(n-1); // caso general

3.
La pregunta Caso-General : Suponiendo que la(s)
llamada(s) recursiva(s) funcionan correctamente, funciona
correctamente toda la funcin?

}
La siguiente figura muestra, como la sucesin de llamadas van
regresando un valor al evaluar 4!
4! = 4* 3 =

6 es regresado
2 es regresado
1 es regresado

24 es regresado

II.3.1 APLICACIN

Programacin Avanzada

1.
La pregunta Caso Base: El caso base ocurre cuando
n=0 a nfact se le asigna el valor de 1. (respuesta es si)
2.
La pregunta Llamador-Ms Pequeo: La respuesta a
esta cuestin debe buscarse en los parmetros pasados en la
llamada recursiva. En la funcin nfact, la llamada recursiva
para n-1. Cada llamada recursiva posterior enva un valor
decrementado del parmetro, hasta que el valor enviado es
finalmente cero. En este punto hemos alcanzado el caso ms
pequeo, y no se hacen ms llamadas recursivas. (respuesta
es si)
3.
La pregunta Caso General : En el caso de la funcin
nfact, necesitamos verificar que la frmula que estamos
usando realmente obtiene una solucin correcta. Suponiendo
que la llamada recursiva nfact(n-1) nos da el valor correcto
de (n-I)!, hacemos la asignacin de n * (n-I)! a nfact. Esta es
la definicin de un factorial (formula (2), por lo tanto,
sabemos que la funcin va bien para todo entero positivo.
(Respuesta si)

22

Ejemplo:
La serie Fibonacci 0, 1, 1, 2, 3, 5, 8, 13, 21........ empieza con
los trminos 0 y 1 y tienen la propiedad de cada trmino siguiente es
la suma de los dos trminos precedentes. Escriba un programa que
calcule dichos serie realizando la funcin recursiva fibonacci(n) de
orden n.

Funcin:
int Fib( int n )
{
if (n<=1)
return(1);
return (Fib(n-1) + Fib(n-2));
}

b) Recursividad anidada: En algunos de los argumentos de la


llamada recursiva hay una nueva llamada a s misma.
II.4 TIPOS DE RECURSIN
a) Recursividad simple: Aquella en cuya definicin slo
aparece una llamada recursiva. Se puede transformar con
facilidad en algoritmos iterativos.
b) Recursividad mltiple: Se da cuando hay ms de una
llamada a s misma dentro del cuerpo de la funcin, resultando
ms difcil de hacer de forma iterativa.

Ejemplo de Ackerman
int Ack( int n, int m )
{
if(n==0 )
return(m+1);
else If (m==0)
return(Ack(n-1,1));
else
return(Ack(n-1, Ack(n,m-1)));
}

Programacin Avanzada

23

//Programa que escribe los nmeros del 1 al 1 0 1


//utilizando dos funciones que se llaman a si mismas
c) Recursividad cruzada o indirecta: Son algoritmos donde una
funcin provoca una llamada a s misma de forma indirecta, a
travs de otras funciones. Es decir es aquella en la que una
funcin es llamada a otra funcin y esta a su vez llama a la
funcin que la llam.

#include <iostream.h>
void paso1 (int i);
void paso2 (int i);

Ejemplo 1 : Par o Impar:

main ()
{
int i=l;
paso1 (i);
retum ();
}

int par( int nump )


{
if(nump==0)
return(1);
return( impar(nump-1));
}

void paso 1 (int i)


{
i++;
cout i "\n";
paso2(i);
}

int impar( int numi )


{
if(numi==0) return(0);
return( par(numi-1));
}

Ejemplo2:
Hacer un programa que escriba en pantalla los
nmeros del 1 al 101 utilizando recursividad indirecta.

void paso2(int i)
{
i++;
cout i "\n";
if (i < 100)
paso 1 (i);
}

Programacin Avanzada

II.5 RECUSIVIDAD VS. ITERACIN

Existen varios factores a considerar en la decisin de usar o no una


solucin recursiva a un problema. Las principales cuestiones son la
claridad y la eficiencia de la solucin.

22

Vamos a comparar la funcin factorial tanto recursiva como no


recursiva
// funcin recursiva

// funcin no recursiva

int factr (int n)

int facti(int n)

{
En general : Una solucin no recursiva es ms eficiente en trminos
de tiempo y espacio de computadora. La solucin recursiva puede
requerir gastos considerables, y deben guardarse copias de variables
locales y temporales. Aunque el gasto de una llamada a una funcin
recursiva no es peor, esta llamada original puede ocultar muchas
capas de llamadas recursivas internas. El sistema puede no tener
suficiente espacio para ejecutar una solucin recursiva de algunos
problemas.
Otro problema : Una solucin recursiva particular puede tener una
ineficiencia inherente. Tal ineficiencia no es debida a la eleccin de
la implementacin del algoritmo; ms bien, es un defecto del
algoritmo en si mismo.
Un problema inherente es que algunos valores son calculados una y
otra vez causando que la capacidad de la computadora se exceda
antes de obtener una respuesta.
La cuestin de la claridad en la solucin es, no obstante, un factor
importante. En algunos problemas una solucin recursiva es ms
simple y ms natural de escribir, como se observa en las siguientes
funciones.
En algunos casos una solucin recursiva es ms simple y ms natural
de escribir

{
if (n==O)
retum(I);
else return 1;
return(n * factr(n -1)

int i,factorial =1;


if (n==0)
else
for (i=1; i<=n; i++)
factorial*=i;
return(factorial);
}

Podemos observar que la funcin realizada con recursividad es ms


sencilla que la iterativa, en donde no es necesario utilizar el ciclo for
como en la funcin iterativa, por lo tanto en este caso es mejor
utilizar la recursividad que la iteracin.
Con la disminucin del costo de memoria y tiempo de computadora y
el crecimiento del costo de tiempo del programador, merece la pena
usar soluciones recursivas para tales programas como a acabarnos de
observar.
La recursividad es una herramienta que puede ayudar a reducir la
complejidad de un programa ocultando algunos detalles de la
implementacin.
Como una gua general, si la solucin no recursiva es ms
corta o no mucho ms larga que la funcin recursiva, no usar
recursividad.

Programacin Avanzada

23

Llamada a una funcin recursiva:


En el caso recursivo, cada llamada genera un nuevo ejemplar de la
funcin con sus correspondientes objetos locales:
II.6 LA PILA DE RECURSIN

La funcin se ejecutar normalmente hasta la llamada a s


misma. En ese momento se crean en la pila nuevos
parmetros y variables locales.

La memoria del ordenador se divide de manera lgica en varios


segmentos (4):

El nuevo ejemplar de funcin comieza a ejecutarse.

Se crean ms copias hasta llegar a los casos bases, donde se


resuelve directamente el valor, y se va saliendo liberando
memoria hasta llegar a la primera llamada (ltima en
cerrarse)

1. Segmento de cdigo: Parte de la memoria donde se guardan las


instrucciones del programa en cdigo Mquina.
2. Segmento de datos: Parte de la memoria destinada a almacenar
las variables estticas.
2. Montculo: Parte de la memoria destinada a las variables
dinmicas.
4. Pila del programa: Parte destinada a las variables locales y
parmetros de la funcin que est siendo ejecutada.
Llamada a una funcin:

Se reserva espacio en la pila para los parmetros de la


funcin y sus variables locales.

Se guarda en la pila la direccin de la lnea de cdigo desde


donde se ha llamado a la funcin.

Se almacenan los parmetros de la funcin y sus valores en


la pila.

Al terminar la funcin, se libera la memoria asignada en la


pila y se vuelve a la instruccin actual.

II.7 VENTAJAS E INCONVENIENTES

1. La principal ventaja es la simplicidad de comprensin y su


gran potencia, favoreciendo la resolucin de problemas de
manera natural, sencilla y elegante; y facilidad para
comprobar y convencerse de que la solucin del problema
es correcta.
2. El cdigo de una funcin recursiva es menor que el de una
funcin iterativa por lo cual es ms fcil su
implementacin.
3. El principal inconveniente es la ineficiencia tanto en
tiempo como en memoria, dado que para permitir su uso es
necesario transformar el programa recursivo en otro
iterativo, que utiliza pilas para almacenar las variables.

Programacin Avanzada

24

Programacin Avanzada

25

III.1 INTRODUCCIN
La clasificacin se define en general como el proceso de rearreglar
un conjunto de objetos en un orden especfico. Su finalidad es
facilitar la bsqueda posterior de los miembros pertenecientes al
conjunto clasificado. En todos los lugares donde se guardan objetos
que luego es necesario recuperar se lleva a cabo la clasificacin, por
ejemplo, en una biblioteca, en los diccionarios, en las bodegas, etc.

2rdenamiento y

Existe una gran dependencia entre el algoritmo a utilizar y la


estructura de los datos por procesar, de aqu que los mtodos de
clasificacin se dividen en: clasificacin de arreglos y clasificacin
de archivos.
La clasificacin de arreglos o interna se produce en la memoria de la
computadora. La clasificacin de archivos o externa es necesaria
cuando el nmero de objetos es demasiado grande que no cabe en la
memoria principal.

%squeda

III.2 CLASIFICACIN INTERNA

Capitulo III

Existen muchos mtodos de clasificacin interna, algunos directos y


otros ms refinados. En general los algoritmos ms simples
requieren ms movimientos de elementos y comparaciones que los
mtodos ms refinados, pero estos ltimos son ms complejos.
Vamos a suponer que los objetos a clasificar son registros que
contienen uno o ms campos. Uno de los campos, llamado clave, es
de un tipo para el cual est definida la relacin de ordenamiento
lineal . La clave puede ser entera, real y de tipo carcter o cualquier
otro tipo para la cual la relacion menos o igual que o menor que
este definida.

Programacin Avanzada

El problema de la clasificacin consisten en ordenar una secuencia de


registros de tal forma que los valores de sus claves formen una
secuencia no decreciente. Esto es, dados los registros r1, r2, ..., rn,
con valores de clave k1, k2, ..., kn, respectivamente, debe resultar la
misma secuencia de registros en orden ri1, ri2, ..., rin, tal que ki1
ki2 ... kin.

26

Si A[j].clave < A[j-1].clave entonces


Intercambia (A[j], A[j-1]).
Fin_si
Fin_para
Fin_para
Fin
El algoritmo intercambiar se presenta a continuacin:

Los mtodos de clasificacin interna pueden dividirse en tres


categoras principales segn el mtodo en el que se basan:
1. Clasificacin por insercin
2. Clasificacin por seleccin
3. Clasificacin por intercambio

III.2.1 CLASIFICACIN POR INTERCAMBIO DIRECTO


Uno de los mtodos de clasificacin ms simples que puede haber es
el llamado clasificacin de burbuja (bubblesort). La idea bsica
de este algoritmo es imaginar que los elementos estn como burbujas
en un tanque de agua con pesos correspondientes a sus claves, cada
pase sobre el arreglo produce el ascenso de una burbuja hasta su nivel
adecuado de peso.
Vamos a suponer que tenemos un arreglo de registros A, el nmero
de registros a ordenar es n, y que el campo clave contiene la clave del
registro. El algoritmo de burbuja en su versin ms sencilla se
presenta a continuacin:
Procedimiento burbuja
Inicio
Para i 1 a n-1 hacer
Para j n a i+1 hacer

Procedimiento intercambia (x, y)


Inicio
Temp. x
X y
Y Temp.
Fin
Si aplicamos el algoritmo a un arreglo de enteros como el siguiente,
los recorridos que se obtienen son:
Arreglo A={6, 9, 12, 67, 3, 0 ,2}, n=7. Obsrvese que en este caso
no es necesario declarar un arreglo de registros.
Recorridos
Resultados
i=1 0, 6, 9, 12, 67, 3, 2
i=2 0, 2, 6, 9, 12, 67, 3
i=3 0, 2, 3, 6, 9, 12, 67
i=4 0, 2, 3, 6, 9, 12, 67
i=5 0, 2, 3, 6, 9, 12, 67

Este algoritmo admite un poco de mejoramiento. En el ejemplo


anterior se puede observar que en las ltimas 3 iteraciones ya no hay
intercambio, tomando en cuenta esto, el algoritmo se puede mejorar.
El algoritmo por vibracin es una variante del algoritmo burbuja pero

Programacin Avanzada

27

mejorado. Este algoritmo consiste en recordar cul fue el ltimo


intercambio realizado y en qu momento.
El algoritmo de burbuja y shakesort en c++ podran quedar as:
Procedimiento shakesort
Inicio
L 2 r n k n
Repetir
Para j r a l hacer
Si A[j-1] > A[j] entonces
Intercambia (A[j-1], A[j])
K j
Fin_si
Fin_para
L k+1
Para j l a r hacer
Si A[j-1] > A[j] entonces
Intercambia(A[j-1], A[j])
K j
Fin_si
Fin_para
R k-1
Hasta l > r
Fin

#include <stdio.h>
#include <iostream.h>
class objeto {
int llave;
public:
objeto(int x=0){ llave=x; }
void leer_llave();
void ver_llave();
int obtenllave();
void ponerllave(int x);
};
void objeto::leer_llave() { cin >> llave; }
void objeto::ver_llave() { cout << llave; }
int objeto::obtenllave() { return llave; }
void objeto::ponerllave(int x) { llave=x; }

Programacin Avanzada

class ordena {
int num; /* No se pueden iniciar aqui variables pj num=0 */
short ban;
objeto elementos[100];
public:
ordena(int ne=0){
num=ne;
ban=0;
// objeto elementos[100] ;
/* inicia(); se supone que ya se iniciaron */
}
void lectura();
void burbuja();
void shakesort();
void despliega();
private:
int verifica();
void intercambia(objeto *a, objeto *b);
};

28

void ordena::lectura(){
ban=1;
for (int i=0; i<num; i++) {
cout << " * " << i <<"-->";
elementos[i].leer_llave();
cout << "\n";
}
}
int ordena::verifica(){
if ((ban ==0) || (num <= 0)) {
cout << "No existen elementos a ordenar\n";
return 0;
}
return 1;
}
void ordena::burbuja(){
if (verifica()!=0) {
for (int i=0; i<num-1; i++)
for (int j=num-1; j>=i+1; j--)
if (elementos[j].obtenllave() < elementos[j-1].obtenllave())
intercambia(&elementos[j], &elementos[j-1]);
}
}
void ordena::shakesort(){
int l, r, k, j;
l=1; r=num; k=num;
do{
for(j=r-1; j>=l; j--)
if(elementos[j-1].obtenllave() > elementos[j].obtenllave()){
intercambia(&elementos[j-1], &elementos[j]);
k=j;
}
l=k+1;

Programacin Avanzada

for(j=l; j<r; j++)


if(elementos[j-1].obtenllave() > elementos[j].obtenllave()) {
intercambia(&elementos[j-1], &elementos[j]);
k=j;
}
r=k-1;
}while (l<=r);
}
void ordena::despliega(){
for(int i=0; i<num; i++) {
cout << " i ", i;
elementos[i].ver_llave();
cout << "\n";
}
}
void ordena::intercambia(objeto *a, objeto *b){
int aux;
aux=a->obtenllave();
a->ponerllave(b->obtenllave());
b->ponerllave(aux);
}
void main(){
ordena ele(5), ele2(5);
ele.lectura();
ele.burbuja();
ele.despliega();
ele2.lectura();
ele2.shakesort();
ele2.despliega();
}

29

III.2.2 CLASIFICACIN POR INSERCIN


Este mtodo consiste en reubicar en el lugar correcto cada uno de los
elementos a ordenar, es decir, en el i-simo recorrido se inserta el isimo elemento A[i] en el lugar correcto, entre A[1], A[2], ..., A[i-1],
los cuales fueron ordenados previamente.
Existen dos condiciones distintas que podran dar terminado el
proceso de clasificacin:
1. Se encuentra un elemento A[j] que tiene una llave menor que
la de A[i]
2. El extremo izquierdo de la secuencia destino es alcanzado
Para facilitar el proceso de mover A[i], es til utilizar la tcnica del
centinela, en A[0], cuya clave es igual a la de A[i].
El algoritmo se muestra a continuacin:
Procedimiento inserciondirecta
Inicio
Para i 2 a n hacer
A[0] A[i] j i/* Los miembros de la clase por default son
privados */

Mientras A[j] < A[j-1] hacer


Intercambia (A[j], A[j-1])
J j-1
Fin_mientras
Fin_para

Programacin Avanzada

30

Fin inserciondirecta
Si notamos que la secuencia destino A[2]...A[i-1] donde se debe
insertar el elemento, ya est ordenada Este algoritmo puede ser
mejorado determinando rpidamente el punto de insercin. La
eleccin es una bsqueda binaria que prueba la secuencia destino en
la mitad y contina buscando hasta encontrar el punto de insercin.
Este algoritmo de insercin modificado recibe el nombre de insercin
binaria y se presenta a continuacin:
Procedimiento insercionbinaria
Inicio
Para i 2 a n hacer
X A[i] L 1 r i
Mientras L < r hacer
M (L+r) div 2
Si A[m] <= x entonces
L L+1
Sino r m
Fin_si
Para j i a r+1 (decremento en 1) hacer
A[j] A[j-1]
Fin_para
A[r] x
Fin_para
Fin insercionbinaria
En el algoritmo anterior se observa que a veces en lugar de mejorar el
algoritmo, este se deteriora, puesto que hay que realizar ms pasos
por la insercin de un elemento, esto implica mayor tiempo que el
utilizado por la clasificacin de insercin directa.

III.2.3 CLASIFICACIN POR SELECCIN DIRECTA


Este mtodo se basa en los siguientes principios:
1. Seleccionar el elemento que tenga la llave menor
2. Intercambiarlo con el primer elemento a1
3. Repetir despus estas operaciones con los n-1 elementos
restantes, luego con n-2 elementos hasta que no quede ms
que un elemento (el ms grande)
Procedimiento seleccindirecta
Inicio
Para i 1 a n-1 hacer
K i x a[i]
Para j i+1 a n hacer
If a[j] < x entonces
k j x a[k]
fin_si
fin_para
a[k] a[i] a[i] x
fin_para
fin selecciondirecta

III.3 MTODOS DE CLASIFICACIN AVANZADOS

Insercin por decremento decreciente

Programacin Avanzada

31

Un refinamiento de la insercin directa fue propuesto por D.L. Shell


en 1959.

Procedimiento shellsort
Inicio
H[1] 9 h[2] 5 h[3]
Para m 1 a t hacer
K h[m] s -k
Para I k+1 a n hacer
X a[i] j i-k
si s=0 entonces s -k
S s+1 a[s] x
Mientras x<a[j] hacer
A[j+k] a[j]
J j-k
Fin_mientras
Fin_para
Fin_para
Fin shellsort

3 h[4]

III.3.1 CLASIFICACIN POR PARTICIN


A este mtodo tambin se le conoce como clasificacin rpida y su
inventor fue C.A.R. Hoare. Este mtodo se basa en el hecho de que
los intercambios han de efectuarse en distancias largas para que
logren su mxima eficiencia. El procedimiento se activa a s mismo
recursivamente.

Procedimiento quicksort
Procedimiento sort(L,R)
Inicio
I indice_inicial
J indice_final
X a[(L+J) div 2]
Repetir
Mientras a[i] < x hacer i i+1
Mientras x < a[j] hacer j j-1
Si i <= j entonces
W a[i] a[i] a[j]
A[j] w i i+1 j j-1
Fin_si
Hasta I > j
Si L < J entonces quicksort(L,j)
Si i < R entonces quicksort(i,R
Fin sort
Inicio
Sort(1,n)
Fin quicksort

Programacin Avanzada

III.4 BSQUEDA LINEAL


La tarea de bsqueda es una de las ms frecuentes en programacin.
Para los siguientes algoritmos vamos a suponer que la coleccin de
los datos en donde vamos a buscar, es fija, y que es de tamao n.
Comnmente cada elemento de la coleccin es un registro con un
campo que acta como una clave. La tarea consiste en hallar un
elemento cuya clave sea igual al argumento de bsqueda.
Bsqueda lineal
Cuando los elementos no llevan un orden y no existe informacin
sobre ellos se utiliza la bsqueda lineal, es decir, comparar uno a uno
los elementos hasta encontrar el deseado. Existen dos condiciones
que ponen fin a la bsqueda.
1. Se encuentra el elemento
2. Se ha rastreado toda la coleccin y no se encuentra el
elemento
Procedimiento bsquedalineal (elemento)
Inicio
I 0
Mientras (i< N) y (a[i] <> elemento) hacer
I i+1
Fin bsquedalineal
Si i al final es N entonces el elemento no fue encontrado, pero sino
entonces quiere decir que el elemento esta en la posicin i-sima del
arreglo.

32

III.5. BSQUEDA BINARIA

Para utilizar este algoritmo es necesario que la coleccin este


ordenada, as se puede acelerar el proceso de bsqueda. La idea clave
consiste en inspeccionar un elemento elegido al azar, por ejemplo
a[m] y compararlo con el elemento de bsqueda x. Si es igual a x, la
bsqueda termina; si es menor que x, inferimos que todos los
elementos con ndices menores que o iguales a m pueden ser
eliminados, y nuestra bsqueda ahora se centra en los dems
elementos. Esto se repite mientras el ndice inicial sea menor o igual
que el final (L y R) y el elemento no sea encontrado. Generalmente el
elemento no se elige al azar, sino que se toma el elemento que se
encuentra a la mitad del arreglo.
Procedimiento bsquedabinaria(x)
Inicio
L 0
R N
Found false
Mientras L<R y not (found) hacer
M (L+R) div 2
7 Si a[m]=x entonces found true
Sino si a[m] < x entonces L m+1
Sino R m
Fin_si
Fin bsquedabinaria

Programacin Avanzada

33

IV.1 INTRODUCCIN
Una estructura de datos es un conjunto de variables, quiz de tipos
distintos, que se relacionan entre s y que se pueden operar como un
todo. stas son fundamentales para el manejo de informacin y el
desarrollo de sistemas.

(structuras

Las estructuras de datos varan en la forma como permiten el acceso


a los miembros del conjunto. Algunas imponen restricciones, tales
como permitir el acceso slo al elemento ms reciente o al menos
reciente insertado.

de

'atos

Aqu se tratan tres estructuras interesantes y tiles para diversas


aplicaciones: Pilas, Colas y Listas.

IV.2.

PILAS

Una pila es una lista de elementos en la cual los elementos se insertan


o se eliminan slo por uno de los extremos.

Capitulo IV

Una pila (stack) es una estructura tipo Lifo (Last In First Out), as
que el primero en entrar es el ltimo en salir.
Se dice que los elementos que se guardan en
una estructura de este tipo se apilan, as que
no es posible tomar el de hasta abajo sin antes
quitar los de encima.

Programacin Avanzada

34

IV.2.1. REPRESENTACIN

mueve sobre el arreglo, hacia arriba o hacia abajo, segn la pila


crezca o decrezca y se denomina: TOPE de la Pila.

Las pilas no estn definidas como tales en los lenguajes de


programacin, stas se representan mediante el uso de Arreglos o
Listas ligadas.

Debe recordarse que un arreglo es una estructura esttica, as, de


manera real el tope se movera de la siguiente manera sobre el
recipiente que contiene a la pila:

Se dice que un Arreglo es un buen recipiente para una pila.

1
1
2
2
3
3
.
.
.

Tope

max

.
.
.

T
O
P
E

Tope

max

IV.1.2. Operaciones
1

Los elementos de una pila permiten que la pila crezca (hacia arriba)
o decrezca (hacia abajo).

2
3
.
.
.
max

T
O
P
E

Tope

En una pila se pueden hacer dos operaciones:


Insertar: meter a la pila (PUSH)
Eliminar: sacar de la pila (POP)
Para el manejo de la pila se requiere de un apuntador (subndice del
arreglo) al ltimo elemento almacenado en la pila. Este apuntador se

Los elementos se insertan y se eliminan por un solo extremo.

Programacin Avanzada

35

COMPORTAMIENTO DEL TOPE


El estado inicial del tope es max+1 (cuando la pila esta vaca). Este
se decrementa cuando se inserta informacin en la pila y se
incrementa cuando se elimina informacin de la misma.
IV.2.2. OPERACIN PUSH
Esta operacin inserta elementos en la pila si sta an no esta llena.
La pila esta llena cuando no hay mas lugares en el arreglo para seguir
insertando informacin.

1
2
3
4
5

7
15

Tope

Entonces el Push quedara como sigue:

Por ejemplo: Suponga que max = 5, entonces

Push (Dato)
Inicio
Si Tope > 1 entonces
Tope Tope - 1
Pila[Tope] Dato
Sino
Escribir Pila llena
Fin_si

Estado inicial de la pila

1
2
3
4
5

Tope

IV.2.3. OPERACIN POP

Si se inserta un 15, es decir, push(15)

1
2
3
4
5

Si se inserta un 7, es decir, push(7)

Esta operacin elimina elementos en la pila si sta an no est


vaca . La pila esta vaca cuando no hay elementos en el arreglo
(como en el estado inicial).

15

Tope

Programacin Avanzada

36

Escribir Pila vaca


Fin_si
Retorna Dato
Fin

Por ejemplo: Suponga que max = 5 y que la pila ya tiene 2


elementos

1
2
3
4
5

7
15

Tope

15

El elemento se saca del tope de la pila (Dato


Tope se incrementa. Entonces Pop quedara:
Pop ( )
Inicio
Si TOPE <= max entonces
Dato Pila[Tope]
Tope Tope - 1
Sino

Programa para el manejo de una PILA estatica

Programacion Avanzada
Abril 2002*/
#include <iostream.h>
#include <stdio.h>
enum estados{VACIA,NORMAL,SIN_ESPACIO};

Si se elimina un elemento entonces :

1
2
3
4
max= 5

/*

Tope

Pila[Tope]) y el

class pila // Clase pila esttica


{
int stack[100];
int tope, max;
enum estados edo;
public :
pila(void) { tope =0; }
void tamanio(int t) { max=t;}
void push(int dato);
int pop(void);
void visualizar(void);
void ver_estado(void);
void pon_estado(void);
enum estados obten_estado(void) { return edo;}
};
/* Definicion de metodos */
void pila::push(int dato)
{

Programacin Avanzada

stack[tope++]=dato;
}
int pila::pop(void)
{
return(stack[--tope]);
}

void pila::visualizar(void)
{
cout <<" DATOS ";
for (short i=0; i<tope;i++)
cout <<": "<<stack[i];
cout <<" <-- Tope"<<endl;
}

37

short menu(void)
{
short opc;
cout <<"\n\t ***** OPERACIONES CON PILA *****\n";
cout <<"\t\t1. Insertar\n";
cout <<"\t\t2. Extraer\n";
cout <<"\t\t3. Visualizar\n";
cout <<"\t\t4. Estado de la pila \n";
cout <<"\t\t0. Salir \n\n";
cout <<"\t\tDigita tu opcion: ";
cin >> opc;
cout << endl;
return opc;
}
/* Programa para el manejo de una pila esttica */

void pila::pon_estado(void)
{
edo = NORMAL;
if (tope==max) edo=SIN_ESPACIO;
if (tope==0) edo=VACIA;
}
void pila::ver_estado(void)
{
switch (obten_estado())
{
case NORMAL : cout << " Pila NORMAL \n"; break;
case VACIA : cout << " Pila VACIA \n"; break;
case SIN_ESPACIO : cout << " Pila LLENA \n"; break;
}
}

int main()
{
pila pila1;
int x;
short op,tam;
cout << "\n\nDa el tamao de la pila: ";
cin>>tam;
pila1.tamanio(tam);
pila1.pon_estado();
do{
op=menu();
switch(op)

Programacin Avanzada

{
case 1 : if(pila1.obten_estado()!=SIN_ESPACIO)
{
cout <<"Da el elemento a insertar[100] : ";
cin >> x;
pila1.push(x);
pila1.pon_estado();
}
else pila1.ver_estado();
break;
case 2 : if (pila1.obten_estado()!=VACIA)
{
x = pila1.pop();
cout <<"El dato extraido es : "<<x<<endl;
pila1.pon_estado();
}
else cout << " NO HAY DATOS \n";
break;
case 3 : if (pila1.obten_estado()!=VACIA)
pila1.visualizar();
else cout << " NO HAY DATOS \n";
break;
case 4 : pila1.ver_estado();
}
}while (op!=0);
return 0;

38

IV.3. COLAS
Una cola es una lista de elementos en la cual los elementos se
insertan por un extremo y se eliminan por otro.
Una cola es una estructura tipo Fifo (First In First Out), as que el
primero en entrar es el primero en salir. Aqu los elementos salen en
el mismo orden en que entraron.
Se dice que los elementos que se guardan en
una estructura de este tipo se encolan uno
despus del otro, de la misma forma que
funcionan las colas en los bancos o en los
supermercados.

IV.3.1. REPRESENTACIN
Las colas no estn definidas como tales en los lenguajes de
programacin, stas se representan mediante el uso de Arreglos o
Listas ligadas.
Se dice que un Arreglo es un buen recipiente para una cola.

Para manejarla se requiere de dos apuntadores (subndices):


Uno que anote al ltimo elemento almacenado en la
cola. Denominado FONDO.
Otro que apunte al primer elemento almacenado en la

Programacin Avanzada

39

cola. Denominado FRENTE.

15
1

12
2

Frente

donde max es igual a la ltima posicin del arreglo y min es igual a


la primera posicin del arreglo, el estado inicial del fondo y del
frente es min-1, esto es:
21
3

1
min

Fondo

6
max

IV.3.2. OPERACIONES

Frente=Fondo
En una cola se pueden llevar a cabo dos operaciones:

As, el Fondo se incrementa en uno cada vez que un elemento se


inserta en la cola y el Frente se incrementa en uno cada vez que un
elemento se elimina de la cola.

Insertar: meter dato en la cola


Eliminar: sacar dato de la cola
Los elementos se insertan por un extremo y se eliminan por el otro.

IV.3.3. COMPORTAMIENTO DE LOS APUNTADORES

Esta operacin inserta un elemento al final de la cola, para lo cual


mueve el apuntador Fondo e inserta, siempre que exista espacio para
la insercin.
Inserta_cola (Dato)
Inicio
Si Fondo < max entonces
Fondo Fondo + 1
Cola[Fondo] Dato
Si Frente < min entonces
[con la primera insercin se mueve el
apuntador Frente

1
min

6
max

Si se supone el siguiente esquema:

IV.3.4. OPERACIN DE INSERCIN

Programacin Avanzada

para indicar que ya se ha insertado un


elemento en la cola ]
Frente Frente + 1
Fin_si

40

Escribir Cola Vaca


Fin_si
Fin

Ejemplo programa de cola esttica:

Sino
Escribir Cola llena
Fin_si
Fin

IV.3.5. OPERACIN DE ELIMINACIN

Esta operacin elimina un elemento del Frente de la cola siempre y


cuando la cola tenga elementos. Si el Frente es igual al Fondo
significa que se ha eliminado el ltimo elemento, de no ser asi, el
apuntador Frente se mueve para anotar al prximo elemento a ser
eliminado.

Elimina_cola( )
Inicio
Si Frente >= min entonces
Dato Cola[Frente]
Si Frente = Fondo entonces
[si se elimina el ltimo elemento entonces se
vuelve al estado
inicial (cola Vaca)]
Fondo min-1
Frente
Fondo
sino
Frente Frente + 1
Fin_si
Sino

// Manejo de una Cola estatica


// Programacion Avanzada
// BUAP- Marzo 2002
#include <iostream.h>
// Clase cola
class Cola
{
int c[100];
int e,s;
int tamanio;
public:
void inicia (void);
void pondato_cola (int i);
int sacadato_cola (void);
void pon_tamanio(int t){tamanio =t;}
};
/*Definicion de metodos */
void Cola::inicia(void)
{
e=s=0;
};
void Cola::pondato_cola(int i)
{
if (e == tamanio) {
cout << " La cola esta llena \n";
return;
}

Programacin Avanzada

41

c[e++]=i;
};

int Cola::sacadato_cola(void)
{
if (e == s) {
cout << " La cola esta vacia ";
return 0;
}
return c[s++];
};
/* Caracterizacin de la clase Cola */
int main(void)
{
Cola a,b; // Objetos de la clase Cola
a.inicia();
b.inicia();
a.pon_tamanio(5);
b.pon_tamanio(8);
a.pondato_cola(10);
a.pondato_cola(20);
b.pondato_cola(100);
b.pondato_cola(200);
cout << "COLA A : " << a.sacadato_cola() << "\n";
cout << "COLA A : " << a.sacadato_cola() << "\n";
cout << "COLA A : " << a.sacadato_cola() << "\n";
cout << "COLA B : " << b.sacadato_cola() << "\n";
cout << "COLA B : " << b.sacadato_cola() << "\n";
return 0;

IV.4. COLA CIRCULAR

Suponga que se tiene la siguiente cola :

15
1

12
2

21

13

17
5

42
6

Fondo

Frente
y que se realiza sobre ella dos operaciones de eliminacin:

21

13

17
5

Frente
Y ahora una operacin de insercin:
Segn
el
algoritmo
insercin_cola
anteriormente citado, la condicin para
insertar es : Fondo < max, la cual no se

42
6

Fondo

Programacin Avanzada

42

cumple an cuando existe espacio para la


insercin y entonces la insercin no se
efecta.

Inicio
Si (Fondo=max y Frente=min) o (Fondo+1=Frente)
entonces
Escribir Cola Llena

Se ha llegado a una situacin en la que se tiene espacio pero no se


puede insertar. Esto puede solucionarse manejando la cola como una
estructura circular, donde el elemento siguiente al de la ltima
posicin, es el primero.

sino
Si Fondo=max entonces
Fondo 1
Sino
Fondo
Fondo +1
Fin_si
Colacir[Fondo] Dato
Si Frente < min entonces
Frente min
Fin_si
Fin_si

De esta forma, bajo el esquema anterior, la insercin de 47, se


comportar de la siguiente manera:

Fin
47
1

Fondo

21

13

17
5

42
En cuanto a la eliminacin, esta tambin considera que al llegar a la
posicin max, la siguiente posicin es min. De esta manera el
algoritmo es el siguiente:

Elimina_cola_circular

Frente

Inicio
Y la condicin para la insercin ser:
si
(Fondo=max y Frente
(Fondo+1=Frente) entonces
escribir Cola Llena

min

As se tiene el siguiente algoritmo para la insercin en cola circular:


Inserta_cola_circular(Dato)

Si Frente < min entonces


Escribir Cola Vaca
Sino
Dato Colacir[Frente]
Si Frente = Fondo entonces
[Si solo hay un elemento]
Frente min-1
Fondo Frente
Sino
Si Frente = max entonces

Programacin Avanzada

43

Frente

Frente

Frente + 1

Sino

As, las listas se conocen como estructuras de datos dinmicas.

Fin_si
Fin_si
Fin_si
Fin

IV.5. LISTAS

IV.5.1. OPERACIONES

En el caso de las Pilas y Colas se emplean estructuras estticas en


dnde la manipulacin de datos es a travs de posiciones localizadas
secuencialmente. Para declarar estas estructuras se debe definir un
tamao determinado el cual no puede modificarse posteriormente.

En una lista ligada se pueden realizar bsicamente 4 operaciones:

En algunas ocasiones es ms conveniente utilizar estructuras


dinmicas, en las cuales se puede aumentar o disminuir de tamao de
la estructura de acuerdo a los requerimientos especficos de la
aplicacin.
Una lista ligada es un grupo de datos organizados secuencialmente,
pero a diferencia de los arreglos, la organizacin no esta dada
implcitamente por su posicin en el arreglo. En una lista ligada cada
elemento es un nodo que contiene el dato y adems una liga al
siguiente dato. Estas ligas son simplemente variables que contienen
la(s) direccin(es) de los datos contiguos o relacionados.
Para manejar una lista es necesario contar con un apuntador al primer
elemento de la lista denominado "cabeza" .
La ventaja de las listas ligadas es que:

Permiten que sus tamaos cambien durante la


ejecucin del programa

Recorrer: moverse sobre los elementos de la lista,


partiendo del inicio y llegando al final de la misma.

Insertar: aadir elementos a la lista.

Eliminar: quitar elementos de la lista.

Buscar: verificar la existencia de un elemento dado


dentro de la lista.

La insercin y la eliminacin se pueden llevar a cabo:

Al inicio de la lista

Al final de la lista

Entre dos elementos de la lista

Programacin Avanzada

44

As, para crear una lista de dos elementos, donde el primero es


apuntado por Cabeza, se tiene la siguiente secuencia:

IV.5.2. NOTACIN
Los nodos son almacenados en un espacio de memoria denominado
Memoria del Montn (Heap), esta memoria es asignada por el
procesador, a solicitud del programa, en tiempo de ejecucin. Cuando
la memoria es asignada se obtiene un apuntador (direccin) al
elemento, as, se usa Crea_nodo(P) para indicar la asignacin de
memoria dinmica que es apuntada por P, esto es:
info

Crea_nodo(P)

sig
Cabeza

Para referirse al dato almacenado en info o en sig se utiliza la


notacin:

Cabeza

Crea_nodo(P)

P^.info

P^.sig
Para indicar que el apuntador sig anota a nada se utiliza:
Info

sig

P^.sig

NULO

Cabeza

Cabeza^.sig
y se denota P^.sig

NULO

cabeza

Programacin Avanzada

45

P^.sig

IV.5.3. LISTAS SENCILLAMENTE LIGADAS

NULO

Si cabeza =NULO entonces


[Se coloca apuntador cabeza al primer elemento de la lista]

Una lista sencillamente ligada es un grupo de datos en dnde cada


dato contiene un apuntador hacia el siguiente dato en la lista, es
decir, una liga hacia el siguiente elemento.

cabeza

Sino
[Se recorre la lista para encontrar la ltima posicin]

Cabeza

recorre

cabeza

Mientras recorre^.sig <> NULO hacer


recorre

IV.5.3.1. OPERACIN DE INSERCIN

recorre^.sig

Fin_mientras
Para insertar un dato en una lista sencillamente ligada es necesario
crear un nuevo nodo, recorrer la lista nodo por nodo hasta encontrar
la posicin adecuada y actualizar las ligas para insertar el nuevo
nodo.

[Se liga el nuevo nodo en la ltima posicin]


recorre^.sig
Fin_si

Lista Desordenada
Supngase que se tiene una lista donde los datos se insertan siempre
al final de la misma sin importar el orden. En esta caso el algoritmo
de insercin es el siguiente:
Insercin_lista_sencilla_desordenada(dato)
Inicio
Crea_nodo(P)
P^.info

dato

Fin

Lista Ordenada
Si lo que se quiere es tener una lista donde los datos estn ordenados
ascendente o descendentemente, entonces el algoritmo cambia
ligeramente. Aqu, durante el recorrido se verifica que los nodos que
se recorren tengan datos menores o mayores (segn el caso) que el
dato que se va a insertar.

Programacin Avanzada

46

El algoritmo para una lista de datos ordenados de manera ascendente,


es el siguiente:
Insercin_lista_sencilla_ordenada(dato)

[Se verifica si la insercin es al inicio de la lista, al final o


entre dos nodos para realizar las operaciones pertinentes]

Inicio

Si recorre^.info < dato entonces


Crea_nodo(P)

[Se inserta al final]

P^.info

recorre^.sig

dato

[Si es el primer elemento de la lista]


Si cabeza =NULO entonces

p^.sig

NULO

Sino

[Se coloca apuntador cabeza al primer elemento de la lista]

Si recorre = cabeza entonces

cabeza

[insertar al inicio]

cabeza^.sig

NULO

cabeza

Sino

cabeza^.sib
sino

[Se recorre la lista para encontrar la posicin correcta


donde debe insertarse el nuevo nodo]
recorre

cabeza

anterior

recorre

[Se inserta entre dos nodos]


anterior^.sig
P^.sig

Mientras(recorre^.sig<>NULO) y (recorre^.info < dato)


hacer
anterior

recorre

recorre

recorre^.sig

Fin_mientras

recorre

Fin_si
Fin_si
Fin_si
Fin

recorre

Programacin Avanzada

47

Es importante notar el uso de dos apuntadores durante el recorrido:


anterior y recorre. Anterior siempre esta anotando al nodo que
precede al anotado por recorre, de tal forma que cuando se deba
insertar entre dos nodos, se tengan apuntadores a los dos nodos entre
los que se insertar, esto se ilustra a continuacin:

Cabeza

11

Suponga que se tiene la lista

anterior

Cabeza

11

y que se desea insertar 10, entonces el proceso es:

Cabeza

recorre

En este momento
la condicin
(recorre^.sig<>NULO) y
(recorre^.info < dato) ya no se cumple y termina el recorrido,
entonces se verifica si debe insertarse al inicio, al final o entre dos
nodos. No es al inicio (recorre <> cabeza), no es al final (recorre^.sig
= NULO , pero recorre^.info no es menor que dato), entonces es
entre dos nodos:

10

11
cabeza

anterior
5

recorre

11

Cabeza

anterior
5

anterior
recorre

11

recorre

IV.5.3.2. OPERACIN DE ELIMINACIN

Programacin Avanzada

48

anterior
Para eliminar un dato de una lista sencillamente ligada es necesario
recorrer la lista haciendo una bsqueda del elemento a eliminar:
Mientras(recorre^.sig<>NULO) y (recorre^.info <> dato)
hacer
anterior

recorre

recorre

recorre^.sig

recorre
Esto es:
Si recorre^.info = dato entonces
SI recorre = cabeza entonces [se elimina de la cabeza]
cabeza

Fin_mientras

recorre.sig

Suponga que desea eliminar 11 (final de la lista):

Cabeza
5

11

anterior

recorre

entonces recorre anota al ltimo nodo de la lista y la eliminacin se


realiza de la siguiente manera:

Aqu se pueden tener dos opciones:


A) Encontrar el elemento al inicio, al final o entre dos nodos.

Cabeza

11

Suponga que se desea eliminar 5 (inicio de la lista):

Entonces recorre se queda en la cabeza y la eliminacin se realiza de


la siguiente manera:
anterior

cabeza

recorre
5

11

Esto es:
Si recorre^.info = dato entonces

Programacin Avanzada

49

SI recorre = cabeza entonces [se elimina de la cabeza]


cabeza

recorre.sig

Cabeza

Sino

11

Si (recorre^.sig = NULO)) entonces [esta al final de la lista]


Anterior^.sig

NULO

Anterior
recorre

Esto es:
Si recorre^.info = dato entonces
SI recorre = cabeza entonces [se elimina de la cabeza]
cabeza

Suponga que desea eliminar 7 (entre dos nodos):

recorre.sig

Sino
Si (recorre^.sig = NULO)) entonces [esta al final de la lista]
anterior^.sig

Cabeza
5

11

NULO

Sino [Esta entre dos nodos]


anterior^.sig

recorre^.sig

anterior
recorre

pero como el ltimo elemento de la lista apunta a NULO, entonces se


puede reducir el algoritmo:
Si recorre^.info = dato entonces

Programacin Avanzada

50

SI recorre = cabeza entonces [se elimina de la cabeza]


cabeza

anterior^.sig

recorre.sig

Sino

recorre^.sig

Fin_si
Sino [llego al final sin encontrar el dato]
Escribir Dato no encontrado

[si esta al final o entre dos nodos, se recorren las


ligas]
Fin_si
anterior^.sig

recorre^.sig

Fin_si
Entonces el algoritmo completo queda de la siguiente manera:
Eliminacin_lista_sencilla(dato)
Inicio
Si cabeza <> NULO entonces
recorre

cabeza

Mientras(recorre^.sig<>NULO) y (recorre^.info <> dato)


hacer
B) Llegar al final de la lista sin encontrar el dato a eliminar .

anterior

recorre

recorre

recorre^.sig

Si recorre^.info = dato entonces


SI recorre = cabeza entonces [se elimina de la cabeza]
Fin_mientras
cabeza

recorre.sig
Si recorre^.info = dato entonces [lo encontro]

Sino
[si esta al final o entre dos nodos, se recorren las

SI recorre = cabeza entonces


cabeza]

ligas]
cabeza

recorre

[se elimina de la

Programacin Avanzada

51

libera_nodo(recorre)
Sino
[si esta al final o entre dos nodos, se recorren
las ligas]
anterior^.sig

recorre^.sig

libera_nodo(recorre)
Fin_si
Sino [no lo encontro]
Escribir Dato no encontrado
Fin_si
Sino
Escribir Lista Vacia
Fin

Programa ejemplo Lista Ligada simple


/* Programa para el manejo de una lista dinamica
Benemerita Universidad Autonoma de Puebla
Facultad de Ciencias de la Computacion
Abril 2002 */
#include <iostream.h>
#include <stdio.h>
/* Estructura de un nodo */

struct INFO
{
int dato;
struct INFO *sig;
};
/* Clase lista ligada */
class Listas
{
struct INFO *raiz;
public:
void Insertar(int);
void Mostrar(void);
void Eliminar_todo(void);
void Eliminar(int);
Listas() { raiz=NULL; }
};
/* Definicion de metodos */
void Listas::Insertar(int dato)
{
struct INFO *temp;
struct INFO *ant;
struct INFO *pos;
temp=new (struct INFO);
(*temp).dato=dato;
if(raiz==NULL)
{
raiz=temp;
(*raiz).sig=NULL;
}
else
{
if((*raiz).dato>dato) /* temp.dato */
{

Programacin Avanzada

(*temp).sig=raiz;
raiz=temp;
}
else
{
ant=raiz;
pos=(*raiz).sig;
while( ((*pos).dato<dato) && ((*ant).sig !=NULL) )
{
ant=pos;
pos=(*pos).sig;
}
(*ant).sig=temp;
(*temp).sig=pos;
} /*else*/
} /*else*/
}
void Listas::Mostrar(void)
{
struct INFO *aux;
if(raiz==NULL)
cout<< "No hay elementos a mostrar";
else
{
aux=raiz;
while(aux!=NULL)
{
cout<< (*aux).dato;
cout << " ";
aux=(*aux).sig;
}
}
}

52

void Listas::Eliminar_todo(void)
{
struct INFO *aux;
if(raiz==NULL)
cout<<"Lista vacia";
else
while(raiz!=NULL)
{
aux=raiz;
raiz=(*raiz).sig;
delete(aux);
}
}
void Listas::Eliminar(int dato)
{
struct INFO *aux;
struct INFO *ant;
struct INFO *pos;
if(raiz==NULL)
cout<<"Lista vacia";
else
{
if((*raiz).dato==dato)
{
aux=raiz;
raiz=(*raiz).sig;
delete(aux);
}
else
{
ant=raiz;
pos=(*raiz).sig;
while( ((*ant).sig != NULL) && ( (*pos).dato != dato))

Programacin Avanzada

{
ant=pos;
pos=(*pos).sig;
}
if(pos!=NULL)
{
(*ant).sig=(*pos).sig;
delete(pos);
}
else
cout<<"Dato no encontrado";
}
}
}
int main()
{
Listas a; // objeto lista ligada
a.Insertar(7);
a.Insertar(5);
a.Insertar(20);
a.Insertar(17);
a.Mostrar();
a.Eliminar(17);
a.Mostrar();
cout << "\nEliminar todo\n";
a.Eliminar_todo();
a.Mostrar();
getchar();
return 0;

53

BIBLIOGRAFA
[1]

Aho, A.V., Hopcroft, J. E., Ullman, J. D.,


Estructuras de datos y Algoritmos
Adison Wesley Iberoamerica. 1998.

[2]

Wirth, N.
Algoritms + Data Structures=Programas
Prentice Hall, 1976

[3]

Wirth, N.
Algoritmos + Estructuras de Datos
Prentice Hall,

[4]

Deitel y Deitel
Como programar en C y C++
Prentice Hall, 1999.

[5]

Deitel y Deitel
Como programar en C++ 4 Edicion
Prentice Hall, 2001

[6]

Garcia Fernndez J.
Estructuras de Datos
Notas (BUAP)

[7]

Katrib Mora Miguel


Programacin Orientada a Objetos en C++
X view, sa de cv. 1997

También podría gustarte