You are on page 1of 5

Mètodes d'ordenació de vectors

Quan tractem amb vectors, és habitual haver d'ordenar-los segons algun criteri, ( habitualment
de petit a gran o al revés) però podem tenir altres problemes d'ordenació ( ordenar els equips de
futbol segons els seus punts etc). Els informàtics han desenvolupat diferents mètodes
d'ordenació cadascun amb les seves fortaleses i febleses. Avui parlarem de dos mètodes senzills
d'ordenació, el mètode de la bombolla, i el mètode d'inserció.

Mètode de la bombolla.

Aquest mètode ordena un vector comparant valors consecutius. Per exemple si tenim un vector
de enters i volem ordenar-lo en ordre creixent, podem recórrer el vector i anar comparant els
elements consecutius. Si estan ben ordenats, els deixem tal qual, si no ho estan, els intercanviem
de lloc. Al final de un nombre determinat de passades per tots els elements del vector, ens
trobarem que el vector es troba ordenat, ja que a cada passada, el valor més gran ha anat fins la
última posició, semblant a la forma que una bombolla d'aire es mou per dintre d'un tub d'aigua.

El pseudocodi seria

variables

vector v d' enters

enter i // índex per recórrer el vector

enter temp // per fer intercanvi dels elements del vector

llegir el vector

per cada passada des de 0 fins a v.Length

per cada i = fins v.Length-1

si v[i]>v[i+1] // estan mal ordenats

temp=v[i];

v[i]=v[i+1]

v[i+1]=temp

final si

final per cada i

final per cada passada

mostrar el vector ordenat

En C# això seria com aquest programa a on he fet una modificació al pseudocodi per tal de que
vagi mostrant com està el vector a cada passada.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Ordenacio
{
class Program
{
static void Main(string[] args)
{
int[] v = new int[] { 3, 45, 22, 87, 72, 98, 13, 53, 8 };
int i=0;
int passada = 0;
int temp = 0;
for (passada = 0; passada < v.Length; passada++)
{
for (i = 0; i < v.Length - 1; i++)
{// si no estan ordenats en ordre creixent
if (v[i] > v[i + 1])
{// els intercanviem
temp = v[i];
v[i] = v[i + 1];
v[i + 1] = temp;
}// final if

}// final for (i


// mostrem el vector a cada passada

Console.Write(" passada :{0,3:d} ||", passada);


for (i = 0; i < v.Length; i++)
{
Console.Write("{0,4:d}", v[i]);
}
Console.WriteLine();
}// final for passadas
Console.WriteLine("\nFINAL");
Console.ReadLine();

}// final programa


}// final classe
}// final namespace

El resultat seria com aquest

Si ens fixem, veurem que a partir de la passada 6 el vector ja està ordenat i tot el que fem és
treballar amb un vector ja ordenat. Aquest és un desavantatge d'aquest mètode i en general fa
que no es faci servir per ordenar grans volums de dades. Si ens fixem, per un vector de N
elements ( N=9 en el nostre cas) es fan N comparacions a dintre del if, i això es fa N vegades
( una per cada passada) per tant, una aproximació de quantes operacions requereix el nostre
mètode per ordenar un vector de N elements és N*N=N 2 per 9 elements fem 81 operacions cosa
que és acceptable, el problema el tindrem quan intentem ordenar 1000 enters, haurem de fer
1000*1000=1.000.000 operacions, i si volem ordenar 10.000 elements, haurem de fer
10.000*10.000=100.000.000 operacions. Ja veieu que això és insostenible, i per això els
informàtics han desenvolupats millores d'aquest mètode i altres mètodes, per exemple el mètode
QuickSort és un dels més ràpids ordenant vector i es basa en la idea de que és més senzill
ordenar vectors petits que grans, per això divideix el vector en subvectors més petits i ordena
recursivament els diferents subvectors.

Millores del mètode de la bombolla.

Si mirem la captura de pantalla, veurem que els darrers elements no cal que els tornem a
comparar a la següent passada, ja que estan ordenats. Per tant, ens podem estalviar
comparacions fent que el bucle intern de les i, no compari tots els elements sinó que compari
tots menys l'últim a la segona passada, tots menys l'últim i penúltim a la tercera etc.

static void Main(string[] args)


{
int[] v = new int[] { 3, 45, 22, 87, 72, 98, 13, 53, 8 };
int i = 0;
int passada = 0;
int temp = 0;
Console.WriteLine(" Bombolla millorada ");
for (passada = 0; passada < v.Length; passada++)
{
for (i = 0; i < v.Length - 1-passada; i++)
{// si no estan ordenats en ordre creixent
if (v[i] > v[i + 1])
{// els intercanviem
temp = v[i];
v[i] = v[i + 1];
v[i + 1] = temp;
}// final if

}// final for (i


Console.Write(" passada :{0,3:d} ||", passada);
// mostrem el vector a cada passada

for (i = 0; i < v.Length; i++)


{
Console.Write("{0,4:d}", v[i]);
}
Console.WriteLine();
}// final for passadas
Console.WriteLine("\nFINAL");
Console.ReadLine();
}// final programa

La gràcia està en aprofitar la variable passada i anar restant-la del bucle que controla les i,

for (passada = 0; passada < v.Length; passada++)


{
for (i = 0; i < v.Length - 1-passada; i++)
{// si no estan ordenats en ordre creixent
quan passada val 0, comparem tots els elements del vector des de 0 fins v.length-1 ( recordeu
que com comparem cada element amb el següent, quan arribem al final, el següent element surt
fora del vector, per tant aquest bucle cal parar-lo un lloc abans fent v.Length-1

Quan passada val 1, comparem tots menys el darrer que ja es troba al seu lloc ( és el més gran
que s'ha trobat i per tant s'ha posat al final del vector).

Aquesta millora ajuda una mica, però encara fem moltes passades inútils. Podríem intentar
canviar això si sabéssim quan el vector està ordenat. Però imaginem que ho està, zas, aleshores,
no entrarem al if ja que mai es compleix la condició v[i]>v[i+1]. Això ens pot permetre canviar
el bucle de les passades per un while regulat per una bandera que direm ordenat. Quan el
programa comença, ordenat=false ja que el vector està desordenat. Al entrar al bucle while
mirem dos coses, si la bandera està a false i si hem fet totes les passades ( no cal fer més
passades el conte, ja que ho estarem fent a sobre d'un vector ordenat).

El programa seria com aquest

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Ordenacio3
{
class Program
{
static void Main(string[] args)
{
int[] v = new int[] { 3, 45, 22, 87, 72, 98, 13, 53, 8 };
int i = 0;
int passada = 0;
int temp = 0;
bool ordenat = false;// inicialment el vector segur que esta
desordenat
Console.WriteLine(" Bombolla millorada amb while ");
do
{
ordenat = true;
for (i = 0; i < v.Length - 1 - passada; i++)
{// si no estan ordenats en ordre creixent
if (v[i] > v[i + 1])
{// els intercanviem
ordenat = false;
temp = v[i];
v[i] = v[i + 1];
v[i + 1] = temp;
}// final if

}// final for (i


Console.Write(" passada :{0,3:d} {1,5}||", passada,
ordenat.ToString());
passada++;
// mostrem el vector a cada passada
for (i = 0; i < v.Length; i++)
{
Console.Write("{0,4:d}", v[i]);
}
Console.WriteLine();
} while ((ordenat == false) && (passada < v.Length));// final for
passadas
Console.WriteLine("\nFINAL");
Console.ReadLine();
}
}
}

El resultat seria com aquest

Ens hem estalviat 2 passades respecte a la solució anterior. Fixeu-vos que encara fa una darrera
passada quan la bandera és true, però no entra a dintre del if, ja que el vector està ordenat. Per
tant, en aquest cas hem reduït de 9 a 7 les passades, això representa un estalvi del 22% respecte
a la solució sense el while.

Així veieu com els programes evolucionen, s'optimitzen i aconsegueixen millor rendiment. Per
una banda, sempre s'estan buscant nous algorismes més eficients, per altre, s'intenta optimitzar i
millorar els algorismes existents per aconseguir el màxim de la màquina, o bé per ser capaços de
tractar problemes més grans. De totes formes, els algorismes també tenen el seu límit, no
podem aconseguir que un algorisme bombolla optimitzat funcioni igual de bé que un Quicksort.

You might also like