Professional Documents
Culture Documents
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
llegir el vector
temp=v[i];
v[i]=v[i+1]
v[i+1]=temp
final si
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
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.
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.
La gràcia està en aprofitar la variable passada i anar restant-la del bucle que controla les i,
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).
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
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.