Está en la página 1de 16

Algoritmos de bsqueda y

ordenacin con C++.


Informtica II
Fundamentos de Programacin

Escuela Superior de Ingenieros de San Sebastin - Tecnun

Concepto de algoritmo
Sentido amplio: Secuencia de pasos o etapas que conducen a la
realizacin de una tarea.
Ejemplos de campos de aplicacin de los algoritmos:

Instrucciones de un lavavajillas
Programacin de un vdeo para grabar una pelcula
Construccin de un edificio
Resolucin de un problema matemtico
Realizacin de un programa de computador

Los primeros algoritmos nacieron para resolver problemas matemticos


(ver ejemplo en la siguiente transparencia).
Antes de escribir un programa de ordenador, hay que tener nuy claro el
algoritmo.
Es importante desarrollar buenos algoritmos (correctos y eficientes).
Una vez que el algoritmo est desarrollado, el problema se puede
programar incluso sin entenderlo.
Escuela Superior de Ingenieros de San Sebastin - Tecnun

Concepto de algoritmo (cont.)


Ejemplo: Algoritmo de Euclides para calcular el mximo comn divisor (m.c.d.) de 2
nmeros enteros A y B (A > B):
1.Asignar a M el valor de A, y a N el
valor de B.
2.Dividir M por N, y llamar R al
resto.
3.Si R distinto de 0,
asignar a M el valor de N
asignar a N el valor de R
volver a comenzar la etapa 2.
4.Si R = 0, N es el m.c.d. de los
nmeros originales

#include <iostream.h>
void Permutar(long &x, long &y){
long tmp;
tmp = x;
x = y;
y = tmp;
}
void main(void)
{
long a, b, m, n, r;
cout << "\nTeclee 2 #s enteros: ";
cin >> a >> b;
m=a; n=b;
if (m<n) Permutar(m,n);
while ((r=m%n) != 0) {
//r=resto de m/n
m=n;
n=r;
}
cout << "\nEl m.c.d. de " << a ;
cout << " y "<< b << " es: " << n << endl;

Es fcil pasar a C++ este algoritmo:


}

Escuela Superior de Ingenieros de San Sebastin - Tecnun

Algoritmos en Informtica
Un algoritmo es un conjunto ordenado, finito y bien definido de etapas, que conducen
a la obtencin de un resultado.
Se considerarn slo algoritmos secuenciales (una operacin a continuacin de otra).
Si son necesarios, deben existir criterios de terminacin claros (por ejemplo, para calcular
seno(x) por desarrollo en serie).
No puede haber etapas imposibles, como "imprimir el conjunto de todos los nmeros enteros".

Representacin de algoritmos:
Detallada: el algoritmo escrito en un determinado lenguaje de programacin (lenguaje de
mquina, ensamblador, fortran, basic, pascal, C++, Java ...).
Simblica: las etapas son descritas con lenguaje prximo al natural, con el grado de detalle
adecuado a la etapa de desarrollo del programa.
La sintaxis (el modo de escribir) debe representar correctamente la semntica (el
contenido). La sintaxis debe ser clara, sencilla y accesible.

Primitivas
"Una estructura semntica bien definida, junto con una sintaxis clara que la represente".
Un lenguaje es una coleccin de primitivas y unas reglas para combinarlas.

Pseudocdigo
Sintaxis intuitiva y menos formal que la de un lenguaje.
Se puede obtener relajando las normas de un lenguaje.
Se utiliza en las etapas iniciales de la programacin.
Escuela Superior de Ingenieros de San Sebastin - Tecnun

Primitivas para escribir


pseudocdigo

Bifurcaciones:
If (condicin) then (actividad)
If (condicin) then (actividad_1)
else (actividad_2)

Bucles:
while (condicin) do (actividad)
repeat (actividad) until (condicin)

Funciones:
procedure

nombre(argumentos)

Diseo modular:

El programa se divide en mdulos con una finalidad bien definida.


Cada uno de estos mdulos se puede descomponer en otros mdulos ms simples.
Se puede llegar al grado de detalle que se desee.
Se puede utilizar niveles de detalle distintos, en las distintas fases del desarrollo.
Unas primitivas pueden ir dentro de otras, utilizando parntesis y corchetes si es
necesario. Conviene indentar.

Escuela Superior de Ingenieros de San Sebastin - Tecnun

Ejemplos de algoritmos

Pago de impuestos:
if (el artculo paga IVA)
then [if (precio > lmite)
then (pagar x)
else (pagar y)]
else (pagar z)

ms fcil de entender que:

if (el artculo paga IVA) then [if (precio > lmite)


then (pagar x) else (pagar y)] else (pagar z)

Mximo elemento de un conjunto:


leer datos
valor_maximo = primer elemento
posicin = 1
contador = 2
while (contador <= n)
do [ if (valor_maximo < acontador)
then (valor_maximo = acontador
posicin = contador)
incrementar contador]
escribir resultados
Escuela Superior de Ingenieros de San Sebastin - Tecnun

Ejemplos de algoritmos (cont.)


Ordenar un conjunto de mayor a menor:
leer datos
i = 1
while (i < n)
do [dar valor a j desde i+1 hasta n,
if (ai < aj) then (permutar(ai,aj))
incrementar i]
escribir resultados

Comparar dos cadenas de caracteres s[ ] y t[ ] :


leer datos
i = 1
while ( si = ti )
do [ if (si = '\0') then (son iguales)
else (incrementar i)]
if ( si < ti ) then (s menor que t)
else (s mayor que t)
escribir resultados
Escuela Superior de Ingenieros de San Sebastin - Tecnun

Algoritmos de bsqueda
Bsqueda lineal:
Se puede utilizar con vectores y con listas vinculadas.
Se recorre el vector o la lista desde el principio, comparando cada elemento con el elemento
buscado. Si se llega al final del vector o de la lista sin encontrarlo, se supone que el elemento
buscado no pertenece al vector o la lista.
No es necesario que el vector o la lista estn ordenados. Ejemplo: Buscar un nombre en un
peridico o en un libro.
Si el vector o la lista estn ordenados, la bsqueda puede detenerse en cuanto se llega a un
elemento posterior al elemento buscado.

Bsqueda binaria:
Slo se puede utilizar con vectores ordenados. Ejemplo: Buscar un nombre en la lista telefnica
Dado el vector de elementos, se determina el elemento central (si el nmero de elementos es
par, el elemento central es el primer elemento de la segunda mitad).
Se compara el elemento buscado con el elemento central

Si coinciden, la bsqueda termina con xito.


Si el elemento buscado es anterior al elemento central, la bsqueda prosigue en el vector primera mitad.
Si el elemento buscado es posterior al elem. central, la bsqueda prosigue en el vector segunda mitad.
Si al ir reduciendo el tamao del sub-vector en el que prosigue la bsqueda se llega a un conjunto vaco
o a un conjunto de un elemento que no coincide con el elemento buscado, la bsqueda termina sin xito.
La bsqueda binaria es mucho ms eficiente que la bsqueda lineal.

La bsqueda binaria se puede implementar de modo iterativo y de modo recursivo.


Escuela Superior de Ingenieros de San Sebastin - Tecnun

Bsqueda binaria
Versin iterativa y recursiva (la correspondiente al algoritmo mostrado):

first

middle

last

procedure bsearch(lista, value)


if (lista vaca)
then
(la bsqueda ha fracasado)
else
[calcular el elemento middle
if (value = lista(middle))
then
(la bsqueda ha tenido xito)
else (value < lista(middle))
(lista = elementos de 1 a middle-1
bsearch(lista, value)
if (la bsqueda ha tenido xito)
then (declarar xito)
else (declarar fallo)
else (value > lista(middle))
(lista = elementos de middle+1 a n
bsearch(lista, value)
if (la bsqueda ha tenido xito)
then (declarar xito)
else (declarar fallo)]

Escuela Superior de Ingenieros de San Sebastin - Tecnun

Algoritmos de ordenacin

Bubble sort
Es el mtodo utilizado en las clases y prcticas anteriores.
Cada elemento se compara con todos los posteriores.
Cuando se encuentra un elemento
que debe ser anterior a l,
se permutan.
i
Grficamente:

Si a[i]>a[j], se permutan
j

Elementos ya
El elemento se compara con los siguientes
ordenados

Buble sort (2)


Se busca el i-simo
elemento ms pequeo.
El elemento j se compara
con el elemento j-1.
Si no estn ordenados,
se permutan

Si a[j-1]>a[j], se permutan

i
Elementos ya
ordenados

Se busca el i-simo elemento ms


pequeo j vara desde n-1 hasta i+1

Mtodos Mergesort y Quicksort


Se vern en las prximas transparencias.
Son mucho ms eficientes (necesitan del orden de NlnN
comparaciones, frente a N2 el mtodo anterior).
Escuela Superior de Ingenieros de San Sebastin - Tecnun

10

Algoritmo Mergesort
Mergesort: Est basado en la funcin merge(), que une dos ficheros ya ordenados en uno

tambin ordenado.

1 4 6 9 12 13 16
=

2 3 8 11 14 =

1 2 3 4 6 8 9 11 12 13 14 16

Se parte de un vector desordenado, cuyo nmero de elementos es potencia de 2


12 8 10 14 6 3 9 11 5 13 4 16 1 15 2 7

Se prosigue con procesos sucesivos de agrupacin y ordenacin:


12 8 10 14 6 3 9 11 5 13 4 16 1 15 2 7
k=1
ordenar:

8 12 10 14 3 6 9 11 5 13 4 16 1 15 2 7
agrupar:

k=2

8 12 10 14 3 6 9 11 5 13 4 16 1 15 2 7
ordenar:
8 10 12 14 3 6 9 11 4 5 13 16 1 2 7 15
agrupar:

k=4

8 10 12 14 3 6 9 11 4 5 13 16 1 2 7 15
ordenar:
3 6 8 9 10 11 12 14 1 2 4 5 7 13 15 16
agrupar:

k=8

3 6 8 9 10 11 12 14 1 2 4 5 7 13 15 16
ordenar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Escuela Superior de Ingenieros de San Sebastin - Tecnun

11

Algoritmo Mergesort (cont.)

En realidad, Mergesort no requiere que el nmero de elementos sea potencia


de 2
La funcin merge() puede unir dos
vectores de dimensin cualquiera.
La primera vez se unen conjuntos
de k=1 elementos, aunque el ltimo
conjunto puede ser de cero
elementos.
La segunda vez se unen conjuntos
de k=2 elementos, aunque el ltimo
conjunto puede ser de cero o
un elementos.
La tercera vez se unen conjuntos
de k=4 elementos, aunque el ltimo
conjunto puede ser de menos
elementos.
La cuarta vez se unen conjuntos
de k=8 elementos, aunque el ltimo
conjunto puede ser de menos
elementos.

k=1 12 8 10 6 3 9 11 5 13 4 1 2 7
k=2 8 12 6 10 3 9 5 11 4 13 1 2 7
k=4 6 8 10 12 3 5 9 11 1 2 4 13 7
k=8 3 5 6 8 9 10 11 12 1 2 4 7 13

1 2 3 4 5 6 7 8 9 10 11 12 13

En cada llamada a merge() hay que pasarle la posicin en la que empieza cada
sub-vector a unir y su nmero de elementos
Escuela Superior de Ingenieros de San Sebastin - Tecnun

12

Algoritmo Mergesort (cont.)


Implementacin del programa mergesort
#include <iostream.h>
#include <stdlib.h>
#include <time.h>
void MergeSort(int *vec, int num);
void Merge(int* ,int*,int*,int,int);
void main() {
int n = 16;
int *v = new int[n];
srand( time(NULL) );
//semilla
for (int i=0; i<n; i++) {
v[i] = rand();
}
cout << "Vector antes de ordenar:\n";
for ( i=0; i<n; i++) {
cout << "v["<<i<<"] = "<<v[i]<<endl;
}
// llamada al mtodo mergesort
MergeSort(v, n);
cout <<"\nVector despues de ordenar:\n";
for (i=0; i<n; i++) {
cout << "v["<<i<<"] = "<<v[i]<<endl;
}
delete [] v;
cout << "Ya he terminado.";
} // fin de main()

void MergeSort(int vect[], int n)


{ // se supone que n deba ser potencia de 2
int *aux = new int[n];
// valores de k: 1, 2, 4, 8, ...
for (int k=1; k<n; k*=2) {
// valores de j = 0, 2, 4, 6, 8, ... (k=1)
//
j = 0, 4, 8,12,16, ... (k=2)
// Mtodo Merge() para n potencia de 2
for (int j = 0; j<=n-k; j+=2*k)
Merge(vect+j, vect+j+k, aux+j, k, k);
for (j = 0; j < n; ++j)vect[j] = aux[j];
}
delete [] aux;
} //fin de mergesort()
void Merge(int *a,int *b,int *c,int na,int nb)
{
int i=0, j=0, k=0;
// copiar ordenadamente a y b sobre c
while (i<na && j<nb) {
if (a[i] < b[j])
c[k++] = a[i++];
else c[k++] = b[j++];
}
// copiar el resto del vector a
while (i < na) c[k++] = a[i++];
// copiar el resto del vector b
while (j < nb) c[k++] = b[j++];
} // fin de merge()

Escuela Superior de Ingenieros de San Sebastin - Tecnun

13

Algoritmo Quicksort

Quicksort: Es casi siempre el mejor algoritmo.


12 8 10 14 6 3 9 11 5 13 4 16 1 15 2 7
Se elige el elemento 9 como pivot.
Se trata de dividir el conjunto en
otros dos, con elementos menores, y
mayores o iguales que el pivot.
Se establecen dos ndices que se
mueven hasta encontrarse
El conjunto queda dividido en dos,
uno con elementos menores que el
pivot, y otro con elementos mayores
o iguales que el pivot (puede
cambiar).
Se vuelve a aplicar el mtodo a cada
uno de los subconjuntos llamando al
mtodo que ha hecho la particin de
modo recursivo.

12 8 10 14 6 3 9 11 5 13 4 16 1 15 2 7
right

left
7 8 10 14 6 3 9 11 5 13 4 16 1 15 2 12
left

right

7 8 2 14 6 3 9 11 5 13 4 16 1 15 10 12
left

right

7 8 2 1 6 3 9 11 5 13 4 16 14 15 10 12
left

right

7 8 2 1 6 3 4 11 5 13 9 16 14 15 10 12
left

right

7 8 2 1 6 3 4 5 11 13 9 16 14 15 10 12
left

Escuela Superior de Ingenieros de San Sebastin - Tecnun

right
posicin final del pivot;
punto de particin del fichero
14

Algoritmo Quicksort (cont.)


#include <iostream.h>
#include <stdlib.h>
Implementacin del programa
#include <time.h>
void QuickSort(int *izdo, int *dcho);
QuickSort
int buscar_pivot(int *izdo, int* dcho, int *ppiv);
int* partir(int *izdo, int *dcho, int pivot);
void permutar(int *a, int *b);
void main() {
int n = 20;
int *v = new int[n];
srand( time(NULL) );
//semilla
for (int i=0; i<n; i++) v[i] = rand();
cout << "Vector antes de ordenar:\n";
for ( i=0; i<n; i++)
cout << "v["<< i <<"] = "<<v[i]<<endl;
// llamada al mtodo mergesort
QuickSort(&v[0], &v[n-1]);
cout << "\nVector despues de ordenar:\n";
for (i=0; i<n; i++)
cout << "v[ << i << "] = << v[i]<<endl;
delete [] v;
cout << "Ya he terminado.";
void QuickSort(int *izdo, int *dcho)
} // fin de main()
{
int *p, pivot;
if ( buscar_pivot(izdo, dcho, &pivot) > 0 ){
p = partir(izdo, dcho, pivot);
QuickSort(izdo, p-1);
QuickSort(p, dcho);
}
}

Escuela Superior de Ingenieros de San Sebastin - Tecnun

15

int buscar_pivot(int *izdo, int* dcho, int *ppiv)


{
int a, b, c;
a = *izdo;
b = *(izdo + (dcho-izdo)/2);
c = *dcho;
// elegir el elemento intermedio como pivot
if ((a<b && b<=c) || (c<b && b<=a)) {
void permutar(int *a, int *b)
*ppiv = b;
{
return 1;
int temp = *a;
}
*a = *b;
if ((b<a && a<=c) || (c<a && a<=b)) {
*b = temp;
*ppiv = a;
}
return 2;
}
if ((a<c && c<=b) || (b<c && c<=a)) {
*ppiv = c;
return 3;
}
return 0; // los tres elementos son iguales
}
int* partir(int *izdo, int *dcho, int pivot)
{
while (izdo <= dcho) { // hasta que los punteros coincidan
while (*izdo < pivot)
// desplazar puntero izdo
izdo++;
while (*dcho >= pivot) // desplazar puntero dcho
dcho--;
if (izdo < dcho) {
// los punteros an no coinciden
permutar(izdo, dcho); // se pasan los punteros
izdo++;
dcho--;
}
}
return izdo;
}

Escuela Superior de Ingenieros de San Sebastin - Tecnun

16

También podría gustarte