¡Descarga Teoria capitol 7 y más Apuntes en PDF de Introducción a la Informática solo en Docsity!
Fonaments d'informàtica
7. Estructures de dades
Índex del tema
Objectius.................................................................................................................................. 1 7.1. Introducció ........................................................................................................................ 1 7.2. Tipus de dades definits per l'usuari.................................................................................. 1 7.3. Estructura de dades array................................................................................................. 2 7.3.1. Definició d'estructures array...................................................................................... 3 7.3.2. Ús d'arrays................................................................................................................. 4 7.3.3. Recorregut d'arrays................................................................................................... 4 7.3.4. Arrays n-dimensionals............................................................................................... 6 7.4. Estructura de dades tupla................................................................................................. 8 7.4.1. Definició d'estructures tupla...................................................................................... 8 7.4.2. Ús de tuples............................................................................................................. 11 7.4.3. Instrucció with.......................................................................................................... 12 7.5. Estructures de dades complexes................................................................................... 14
Objectius
1. Saber definir nous tipus de dades.
2. Conèixer les dues estructures de dades bàsiques, arrays i tuples.
3. Saber quan fer servir l'una o l'altre.
4. Saber definir i utilitzar, tant en Pascal com en pseudocodi, ambdues estructures.
7.1. Introducció
Totes les dades que hem fet servir fins ara eren dades escalars, es a dir, només tenen un valor.
Moltes vegades, però, això no es així, sinó que una dada pot tenir diversos valors.
Per exemple, si estem recollim dades de temperatura d'una habitació cada 10 minuts i volem
recordar-nos dels 100 últims valors, no tindrem un únic valor sinó uns quants valors. Pensem per un
moment el que seria tenir 100 variables diferents (temp1, temp2, temp3...temp100) per guardar-los, i
per tractar-los. No més per escriure'ls per pantalla necessitem escriure 100 instruccions write.
Necessitem doncs algun mecanisme que ens permeti emmagatzemar dades d'aquest tipus.
Un altre cas és, per exemple, les dades d'una persona, nom, cognoms, telèfon, etc. Podem tenir
variables diferents per cada dada, però sembla més lògic que poguéssim tenir, en una sola variable,
agrupades totes les dades, ja que tenen més sentit totes juntes que per separat. Totes juntes són les
dades d'una persona, per contra, el telèfon, ell sol, només és un telèfon, no una persona.
Necessitarem, també, mecanismes per crear variables d'aquest tipus.
Abans de veure aquestes dues estructures, però, veurem com el programador pot crear els seus
propis tipus de dades. D'aquesta manera podrem crear tipus de dades nous amb les estructures que
veurem.
7.2. Tipus de dades definits per l'usuari
L'usuari, el programador en el nostre cas, pot crear nous tipus de dades, que posteriorment podrà fer
servir per declarar variables.
Per definir nous tipus de dades podem fer-ho reanomenant un tipus ja existent, o bé, creant
estructures de dades amb els mecanismes que veurem al llarg d'aquest capítol. Les definicions de
tipus han de fer-se dintre de la secció adient en funció del llenguatge.
Estructures de dades
En pseudocodi la definició de nous tipus es fa de la següent manera:
tipus
< nom > és {< tipus > | < definició d'estructura de dades > |
< enumeració > | < subrang >}
ftipus
En Pascal de forma similar tindrem la sintaxi següent:
type
= {< tipus > | < definició d'estructura de dades > |
< enumeració > | < subrang >};
Alguns exemples de definicions de nous tipus de dades:
Podem veure que els noms dels nous tipus de dades comencen tots per la lletra T. Això, no és
obligatori en cap llenguatge, però és una norma que seguirem al llarg d'aquest llibre, per distingir
clarament els identificadors dels tipus de les variables.
Hom pot pensar quin sentit té reanomenar tipus de dades ja existents. El sentit es guanyar en
llegibilitat o claredat en el programa. Es aconsellable fer-ho per a tipus de dades importants del
programa.
7.3. Estructura de dades array
L' array és una estructura de dades on tots els elements que formen l'estructura són del mateix tipus,
i distingim un element de l'altre per la posició que ocupa dins l'estructura. És una estructura que és
un reflex fidel de la memòria.
L'estructura array es pot tractar com una única entitat amb el seu nom o cada element de forma
independent indicant el nom de l' array i la posició. Habitualment a la posició se l'anomena índex de
l' array.
A altres llibres podem trobar que els arrays se'ls anomeni vectors, taules o matrius.
Gràficament podem veure un array com ens mostra la il·lustració 1. L'índex de l' array es pot definir
des del límit inferior fins al límit superior.
Pseudocodi Tipus TEdat és 0.. TNom és Cadena[30] TPes és Real TParell és Natural TColor és (Blanc, Vermell, Blau, Groc, Verd, Negre) FTipus Pascal Type TEdat = 0..120; TNom = String[30]; TPes = Real; TParell = Word; TColor = (Blanc, Vermell, Blau, Groc, Verd, Negre); Exemple 1 Definició de nous tipus de dades
Estructures de dades
7.3.2. Ús d' arrays
Veiem ara com fem ús dels arrays. Ja hem dit que podem fer-los servir tenint en conte que són una
única entitat. També podrem referir-nos a un dels seus elements.
El nom de la variable es refereix a tota l'estructura array , mentre que el nom de la variable seguit
d'una expressió entre corxets serà la manera de referir-nos a un element de l'estructura. L'expressió
ha de donar com a resultat un valor dintre del subrang de l'índex. En cas contrari, es generarà un
error d'execució.
< variable tupla >[< expressió >]
Els corxets, per tant, és l'operador selector d'element d'un array.
Cal recordar que una variable array en pseudocodi:
- Pot assignar-se a un altre variable array si són del mateix tipus (es a dir, són exactament
iguals).
- L'únic operador que admet és el selector de d'element. No es poden sumar, ni dividir, etc.
- Els elements de la variable poden ser a la seva vegada arrays.
En Pascal, a més a més, cal recordar:
- Només es pot assignar una variable array a un altra si són del mateix tipus de dades, es a
dir, o estan definides a la mateixa declaració, o s'ha definit l'array com un nou tipus de
dades i s'han declarat les variables amb aquest tipus.
- Que les instruccions read , readLn , write i writeLn no saben treballar amb variables array.
Per tant, per exemple, per llegir una variable array haurem de llegir cadascun dels seus
elements per separat.
Tant en pseudocodi com en Pascal, sobre un element d'una estructura array es poden fer totes les
operacions vàlides del tipus de dades de l'element.
7.3.3. Recorregut d' arrays
Com a exemple d'ús d' arrays podem veure l'operació més habitual que es fa sobre un array , el
recorregut.
El recorregut d'un array és l'operació per la qual es fa una acció sobre tots
o uns quants elements de l'array en l'ordre, directe o invers, en que es
troben.
L'avantatge de l' array , respecte la tupla o l'ús de variables independents, rau en que com tots els
elements es diuen igual i es diferencien en l'índex, podem utilitzar una estructura iterativa per
recorrer els elements. La instrucció iterativa més habitual serà el per , ja que coneixem els límits de
l'índex.
Type TDies = (Dilluns, Dimarts, Dimecres, Dijous, Divendres, Dissabte, Diumenge); TTemperatures = Array [1..31] of Real; TNoms = Array [1..50] of string[100]; TEdifici = Array [-3..8] of Word; TIngressos = Array [Dilluns..Divendres] of Real; Var IngSet : Tingressos; TempMes : Ttemperatures; Alumnes : Tnoms; Superficie : Tedifici; CapSetmana : Array [Dissabte..Diumenge] of Real; Exemple 3 Definicions i declaracions d'estructures array
Fonaments d'informàtica
Com a exemple, veiem el recorregut que permet en Pascal llegir de teclat els valor d'un array de
reals. Aprofitem per fer, també, un recorregut de l' array per escriure el seu contingut per pantalla,
però, en ordre invers.
Un altre operació de recorregut habitual consisteix en passar per tots el elements i anar-los
acumulant per calcular, per exemple, la mitjana. A l'exemple 5 trobem aquest cas amb l' array de
temperatures.
El recorregut no té perquè fer una operació sobre tots el elements, si no únicament sobre aquells
que compleixin una determinada condició. Per exemple, si suposem que un element de l' array de
temperatures té el valor -100 quan s'ignora la temperatura d'un dia per calcular la mitjana haurem
d'ignorar aquests valors. El programa ens quedarà:
Per acabar amb els exemples, veurem ara una operació habitual en els arrays , la cerca d'un valor
dins l' array per determinar la seva posició. El que farem en aquest cas es un recorregut mirant si el
valor de l'element és el que cerquem. En aquest cas, cal tenir en compte que quan l'haguem trobat
no caldrà continuar el recorregut, per tant, canviarem la instrucció iterativa per per una instrucció
mentre.
Com exemple, veurem una cerca dins d'un array de noms de persones. No indiquem a l'exemple, el
7 en aquest cas, com s'omple l'array, ni altres qüestions auxiliars. Suposarem també que l' array no
se sap si està o no ordenat (per tant, es com si estès desordenat). El resultat de la cerca serà que la
variable pos valdrà la posició de l'element de l' array que conté el nom buscat. Si no es troba el nom,
pos valdrà zero.
Type TTemperatures = Array [1..31] of Real; Var TempMes : Ttemperatures; i : 1..31; Begin for i:= 1 to 31 do begin write('Entra la temperatura del dia ',i,': '); readLn(TempMes[i]); end; clrscr; for i:=31 downto 1 do writeLn('Dia ',i:3,': ',TempMes[i]); end. Exemple 4 Exemple de recorregut d'un array Suma := 0; for i:= 1 to 31 do Suma := Suma + TempMes[i]; Mitjana := Suma / 31; WriteLn('La mitjana de temperatures és :',Mitjana); Exemple 5 Exemple de recorregut d'un array acumulat valors Suma := 0; Quants := 0; for i:= 1 to 31 do if TempMes[i] <> -100 then begin Suma := Suma + TempMes[i]; Quants := Quants + 1 end; Mitjana := Suma / Quants; WriteLn('La mitjana de temperatures és :',Mitjana); Exemple 6 Exemple de recorregut d'alguns elements d'un array acumulat valors
Fonaments d'informàtica
En pseudocodi tindrem
array [{< subrang >|< lím_sup >} {,{< subrang >|< lím_sup >}}] de < tipus > o bé array [{< subrang >|< lím_sup >}] {de array [{< subrang >|< lím_sup >}]} de < tipus > o bé array [{< subrang >|< lím_sup >}] de < tipus_array >
On tipus_array és una definició prèvia d' array.
En Pascal tindrem
array [< subrang > {,< subrang >}] of < tipus > o bé array [< subrang >] {of array [< subrang >]} of < tipus > o bé array [< subrang >] of < tipus_array >
Veiem ara alguns exemples de definicions de tipus d' arrays n-dimensionals
Als exemples 10 i 11 podem veure alguns recorreguts amb matrius de dos dimensions.
Tipus TTempMes és Array [ 31 ] de Real TTempAny és Array [ 12 ] de TTempMes TTaulaNoms és Array [ 15 ] de Array [ 10..20 ] de Cadena TMatriu és Array [ 10,20 ] de Enter TMatriuCub és Array [ -3..3,10,10 ] de Real TTempAnySala és Array [ 5,12 ] de TTempMes FTipus Type TTempMes = Array [1..31] of Real; TTempAny = Array [1..12] of TTempMes; TTaulaNoms = Array [1..15] of Array [10..20] of String TMatriu = Array [1..10,1..20] of Integer; TMatriuCub = Array [-3..3,1..10,1..10] of Real; TTempAnySala = Array [1..5,1..12] of TTempMes; Exemple 9 Definicions i declaracions d'estructures array n-dimensionals Array de dues dimensions 10x 1 2 1 E1,1 E1, 2 E2,1 E2, 3 E3,1 E3, 4 E4,1 E4, 5 E5,1 E5, 6 E6,1 E6, 7 E7,1 E7, 8 E8,1 E8, 9 E9,1 E9, 10 E10,1 E10, Il·lustració 2 Representació gràfica d'un array de dues dimensions
Estructures de dades
Program ArraysNDim; {Donada una matriu d'enters de FILES x COLUM calcula la matriu trasposta} Uses Crt; Const FILES = 5; COLUM = 7; Type TMatriu = Array [1..FILES,1..COLUM] of Integer; TMatTra = Array [1..COLUM,1..FILES] of Integer; Var M : TMatriu; T : TMatTra; i,j : Integer; begin {Llegim la matriu} for i:=1 to FILES do for j:=1 to COLUM do begin write('[',i,',',j,']: '); readLn(M[i,j]); end; {Fem la trasposta} for i:=1 to FILES do for j:=1 to COLUM do T[j,i] := M[i,j]; {Escrivim la matriu trasposta} clrscr; for i:=1 to COLUM do {recordem que la trasposta te COLUM files i FILES columnes} begin for j:=1 to FILES do write(T[i,j]:8); writeLn; end; end. Exemple 10 Exemple amb recorreguts de matrius de dos dimensions
Estructures de dades
7.4. Estructura de dades tupla
L'estructura de dades tupla és una estructura que permet emmagatzemar diferents dades d'una
mateixa entitat. Cada dada que pertany a l'estructura pot tenir un tipus de dades diferent. Cada dada
que composa l'estructura s'anomena camp i està identificat per un nom.
És la representació informàtica d'un formulari. L'estructura seria el formulari i, cada casella que es
pot omplir, seria un camp.
7.4.1. Definició d'estructures tupla
Veiem la sintaxis per definir estructures tupla, tant en pseudocodi com en Pascal. Podem veure que
consisteix a indicar que és una tupla, i la llista de camps que la composen. De cada camp s'indica el
nom i el tipus de dades. No hi ha cap restricció en el tipus de dades del camp. Pot ser qualsevol tipus
predefinit o qualsevol definit per l'usuari.
Pseudocodi:
tupla
< camp > és < tipus >
{< camp > és < tipus >}
ftupla
On camp és un identificador creat seguint les normes de creació de identificadors
En Pascal les tuples reben el nom de record (registre). D'aquí bé que molta literatura faci servir el
nom registre en lloc del de tupla. La sintaxis per la definició de tuples és:
record
< camp > : < tipus >
{; < camp > : < tipus >}
end
La manera més habitual de definir una tupla és crear un nou tipus de dades indicant que és una
tupla i definint cadascun dels camps que el composen. A partir d'aquí, es declaren les variables amb
el nou tipus creat. Podem veure, a l'exemple 12 , un exemple de definicions d'un nou tipus de dades
tupla i la declaració de variables.
També es pot declarar una variable indicant, com a tipus, directament la definició de la tupla. Això no
es gaire aconsellable fer-ho, ja que no es podran declarar més variables de la mateixa tupla, encara
que les dues definicions siguin iguals.
A l'exemple 13 podem veure com seria la declaració de variables feta d'aquesta manera. Cal tenir en
conte que quan fem això, Pascal considera la definició de la tupla com un nou tipus de dades anònim
(sense nom). Les variables declarades a la mateixa declaració seran del mateix tipus, mentre que les
declarades a declaracions diferents, encara que siguin exactament iguals, seran de tipus de dades
anònims diferents. Per tant, a l'exemple 13 , les variables a i b són del mateix tipus, c i d són del
mateix tipus, però, a i c són de tipus diferents.
Núm. Treballador: ________ Nom: ________________________ Cognoms: _________________________________________ Telèfon: _____________ Mòbil: _____________ Adreça: ________________________________________________________________________ C.P.:_________ Població: ______________________ Província : _________________________ Núm. Seguretat social: __________________ Núm. Mútua d'accidents: ____________________ Estat civil: _______________ Núm. de fills: _________ Núm. ascendents a càrrec : __________ Grau de minusvalidesa : _____% CCC : ______-______-___-___________________ Banc o caixa: ___________________________________________ Il·lustració 3 Típica fitxa d'un treballador
Fonaments d'informàtica
Pseudocodi Tipus TCoordenades és Tupla X és Real Y és Real ftupla TData és Tupla Dia és 1.. Mes és 1.. Any és 1900.. fTupla fTipus Var a,b són TCoordenades c,d són TCoordenades f és TData fVar Pascal Type TCoordenades = Record X : Real; Y : Real End; TData = Record Dia : 1..31; Mes : 1..12; Any : 1900.. End; Var a,b : TCoordenades; c,d : TCoordenades; f : TData; Exemple 12 Definició d'un tipus anomenat Coordenades en Pascal i pseudocodi i declaració de variables del nou tipus Pseudocodi Var a,b són Tupla X és Real Y és Real ftupla c,d són Tupla X és Real Y és Real ftupla f és Tupla Dia és 1.. Mes és 1.. Any és 1900.. fTupla fVar Pascal Var a,b : Record X : Real; Y : Real End; c,d : Record X : Real; Y : Real End; f : Record Dia : 1..31; Mes : 1..12; Any : 1900.. End; Exemple 13 Operacions correctes sobre tuples en pseudocodi i en Pascal
Fonaments d'informàtica
Com exemple d'us de tuples, farem un programa que demana les dades d'una persona i les escriu
per pantalla en forma de fitxa. Les dades que demanarem són: nom, cognoms, adreça postal, codi
postal, població, telèfon fix, mòbil, adreça electrònica, data de neixament i NIF. El podem veure a
l'exemple 16.
7.4.3. Instrucció with
Com podem suposar i hem pogut veure als exemples amb tuples, resulta molt farragós haver
d'escriure contínuament en nom de l'estructura. Això, es fa molt evident quan tenim estructures més
complexes que podem suposar escriure noms molt llargs com per exemple:
Alumne.DataN.Mes, Alumne.DataN.Dia, Alumne.DataN.Any
Podem veure que per accedir als tres camps mes, dia i any, hem hagut d'escriure tres vegades
Alumne.DataN.
La instrucció Amb o With ens estalvia haver d'escriure cada cop la part comuna. El que fa és definir
un bloc de codi, dins del qual, s'afegeix als noms de camps que es trobin la part comuna. És una
instrucció atípica, ja que no genera codi màquina.
En pseudocodi farem que els noms de camp dins del bloc Amb s'escriguin precedits del símbol '.'.
D'aquesta manera si un camp es diu igual que una variable podrem distingir un de l'altre.
Amb < nom de tupla > fer < instruccions > fAmb
En Pascal no s'escriu un punt davant del nom del camp. És per això que no el podrem fer servir quan
dins del bloc quedés una instrucció que fes confondre un camp i una variable.
with do
<instrucció>;
A l'exemple següent podem veure l'ús d' amb i de with.
7.5. Estructures de dades complexes
Tant a la definició de tuples com a la definició d'arrays, no hem posat cap restricció al tipus de dades
de cada element que composen les estructures. I, efectivament, no hi ha cap restricció. Per tant, es
poden definir arrays on cada element sigui una tupla. O tuples on alguns dels seus camps siguin, a
la seva vegada, tuples, o bé, arrays.
Això fa que puguem construir estructures de dades complexes que ens permet representar més
eficaçment la realitat.
Per exemple, imaginem un professor que vol emmagatzemar les dades dels alumnes d'un grup
d'una assignatura, on per cada alumne vol saber, a més a més, les notes que ha obtingut en cada
control que s'ha fet.
Pseudocodi soposant la declaració de variables de l'exemple 12 c ← a * b {l'operador * no existeix sobre tuples} b ← f {els tipus de dades d'f i de b són diferents} Si la declaració de variables fos la de l'exemple 13 les instruccions anteriors són igualment incorrectes en pseudocodi. Pascal soposant la declaració de variables de l'exemple 12 ReadLn(a); {no es poden llegir tuples} ReadLn(f); {no es poden llegir tuples} a := f; {a i f són de tipus de dades diferents} WriteLn(a, f); {no es podem escriure tuples} Pascal soposant la declaració de variables de l'exemple 13 c := a; {c i a són de tipus de dades anònims diferents} d := b; {d i b són de tipus de dades anònims diferents} Exemple 15 Operacions incorrectes amb tuples
Estructures de dades
Program Tuplas; Uses Crt,SysUtils; type TAdreca = Record Carrer : String[60]; Num : Integer; Pis : String[4]; Porta : String[4]; CP : String[5]; Pobla : String[30]; end; TNIF = Record Num : LongInt; Lletra : Char; end; TPersona = Record Nom : String[20]; Cog1 : String[20]; Cog2 : String[20]; Adre : TAdreca; Telef : String[9]; Mobil : String[9]; Mail : String[70]; DatN : TDateTime; NIF : TNIF; end; Var P : TPersona; D : String[10]; begin ClrScr; Write('Nom : '); ReadLn(P.Nom); Write('Cognom 1 : '); ReadLn(P.Cog1); Write('Cognom 2 : '); ReadLn(P.Cog2); Write('Carrer : '); ReadLn(P.Adre.Carrer); Write('Número : '); ReadLn(P.Adre.Num); Write('Pis : '); ReadLn(P.Adre.Pis); Write('Porta : '); ReadLn(P.Adre.Porta); Write('C.P. : '); ReadLn(P.Adre.CP); Write('Població : '); ReadLn(P.Adre.Pobla); Write('Telèfon : '); ReadLn(P.Telef); Write('Mòbil : '); ReadLn(P.Mobil); Write('E-mail : '); ReadLn(P.mail); Write('Data naix.: '); ReadLn(D); P.DAtN := StrToDate(D); Write('DNI : '); ReadLn(P.NIF.Num); Write('Lletra NIF: '); ReadLn(P.NIF.Lletra); ClrScr; WriteLn(' Nom : ',P.Nom); WriteLn(' Cognom 1 : ',P.Cog1); WriteLn(' Cognom 2 : ',P.Cog2); WriteLn(' Carrer : ',P.Adre.Carrer); WriteLn(' Número : ',P.Adre.Num); WriteLn(' Pis : ',P.Adre.Pis); WriteLn(' Porta : ',P.Adre.Porta); WriteLn(' C.P. : ',P.Adre.CP); WriteLn(' Població : ',P.Adre.Pobla); WriteLn(' Telèfon : ',P.Telef); WriteLn(' Mòbil : ',P.Mobil); WriteLn(' E-mail : ',P.mail); WriteLn(' Data naix.: ',DateToStr(P.DatN)); WriteLn(' DNI : ',P.NIF.Num); WriteLn(' Lletra NIF: ',P.NIF.Lletra); ReadKey; end. Exemple 16 Programa d'exemple de tuples
Estructures de dades
Sabem que un grup té, com a màxim, 25 alumnes, però no té perquè estar ple. El número de
controls que fa el professor és de tres. Alguns alumnes, però, poden no presentar-se a tots els
controls. A la il·lustració 4 podem veure un la llista en paper que fins ara es fa servir.
El que hem d'intentar és crear un a única estructura que englobi totes les dades, de la mateixa
manera que, si ho fes manualment, el professor intentaria tenir tota la informació en un sol full.
Primerament pensem com emmagatzemar les dades del grup. Necessitem saber el nom de
l'assignatura, la identificació del grup i la llista d'alumnes. L'estructura que ens permet tenir aquestes
tres informacions és la tupla, ja que cadascuna és d'un tipus de dades diferent.
La llista d'alumnes s'implementarà com un array , ja que cadascun dels elements que el formen són
del mateix tipus, són alumnes. El problema ens ve en que l' array el tenim que definir d'un tamany fix
(en el nostre cas 25, ja que és el número màxim d'alumnes d'un grup), per contra ens diuen que el
grup no té perquè estar ple. D'alguna manera haurem de saber quantes posicions de l' array
contenen informació. Una manera, la que farem servir en aquest exemple, consisteix en mantenir les
posicions amb informació vàlida agrupades, sense buits, des de l'inici de l' array , i mantenir un
comptador amb el número d'alumnes (o de posicions vàlides).
Com aquest comptador no té sentit sense l' array d'alumnes, i l' array d'alumnes sense el comptador
no sabríem quantes posicions són vàlides, podem concloure que ambdues dades són part de la
mateixa, i per tant, la tupla del grup inclourà el nom de l'assignatura, la identificació del grup, la llista
d'alumnes i el comptador que ens indica quants alumnes hi ha a la llista.
En segon lloc haurem de definir les dades d'un alumne. Aquestes estaran formades per el noms i
cognoms, el número de matrícula i per la llista de notes dels controls. Les agruparem també amb
una tupla.
La llista de notes serà un array de tres posicions, on cada posició contindrà un número real de 0.0 a
10.0, ambdós inclosos. Caldrà, però, distingir quan l'alumne no s'ha presentat. Això ho farem
emmagatzemant el valor -1.0, ja que aquest és un valor que una nota no pot tenir, però és un valor
vàlid del tipus de dades real.
El que hem d'intentar es crear una única estructura que englobi totes les dades, de la mateixa
manera que si ho fes manualment, el professor intentaria en un sol full tenir tota la informació.
No caldrà tenir un comptador ja que tots els alumnes tindran tres controls, i a més la nota del primer
control estarà a la primera posició i així successivament. Tampoc emmagatzemarem les notes
mitges, ja que les podem calcular en qualsevol moment a partir de les notes del controls.
Als requadres d'exemples des del 18 al 20 , podem veure el programa complet en Pascal.
7.6. Ordenació d'arrays
En moltes ocasions necessitem que el contingut de l'array estigui ordenat per algun criteri. Si l'array
no està ja ordenat, no ens quedarà altre opció que ordenar-lo. Aquesta operació es pot realitzar
mitjançant diferents algoritmes. Veurem alguns d'ells, sense voler ser una recopilació completa, que
ja s'ha fet en molts llibres.
Els diferents algoritmes es basen, principalment, en fer una sèrie de recorreguts de l'array de forma
que aconseguim, al final de cada recorregut, tenir ordenat un element més que al recorregut anterior.
Així doncs, partim de la idea que una part de l'array ja està ordenat i un altre pendent d'ordenar. A
cada recorregut el que intentem és aconseguir que un dels seus elements passi a la zona ordenada,
evidentment en el seu lloc. En general, quan la zona pendent d'ordenar estigui buida haurem acabat.
La diferència entre els diferents mètodes d'ordenació radica en què fem amb la zona pendent
d'ordenar, i en com posem l'element escollit dins la zona ordenada.
Fonaments d'informàtica
Program Alumnes; Uses Crt; Const MAXALU = 25; {Nombre d'alumnes m`xim en un grup} NUMNOT = 3; {Nombre de notes de cada alumne} TAMNOM = 20; {Tamany del nom o cognom} TAMASS = 60; {Tamany del nom d'una assignatura} TAMGRU = 4; {Tamany del identificador del grup} NUMLIN = 10; {Número d'alumnes en cada pàgina dels llistats} Type TMatri = Word; {Tipus: número de matrícula} TAssig = string[TAMASS]; {Tipus: nom assignatura} TIdGr = string[TAMGRU]; {Tipus: identificador de grup} TNota = Real; {Tipus: nota} TContr = Array [1..NUMNOT] of TNota; {Tipus: Controls un alumne} TNom = string[TAMNOM]; {Tipus: nom o cognoms de persones} TNomCom = string[TAMNOM*3+3]; {Tipus: nom de persona complet} TAlumne = Record {Tipus: dades d'un alumne} Nom : TNom; Cog1 : TNom; Cog2 : TNom; Mat : TMatri; Notes: TContr; End; TLlista = Array [1..MAXALU] of TAlumne; {Tipus: Llista d'alumnes} TGrup = Record {Tipus: Grup d'alumnes d'una assignatura} Id : TIdGr; Assi : TAssig; Quants : 0..MAXALU; Alumnes : TLlista; End; Var G : TGrup; {Dades del grup} N : TNom; {Nom auxiliar} Al : TNomCom; {Nom complet d'un alumne} i,j : Integer; {Comptadors de bucles} lin : Word; {Comptador delínies d'un llistat} MitAlu : TNota; {Per al càlcul de la nota mitja d'un alumne} Mitjes : TContr; {Array per al càlcul de la nota mitja de cada control} begin {Entrada de dades} Write('Nom de l''assignatura: '); ReadLn(G.Assi); Write('Identificador del grup: '); ReadLn(G.Id); WriteLn; WriteLn('Entrada de dades d''alumnes: '); WriteLn('Deixar el nom en blanc per acabar l''entrada'); WriteLn; G.Quants := 0; {Inicialment no hi ha cap alumne dins la llista} N := 'a'; {assegurem que entrarem dins el bucle} while (N <> '') and (G.Quants <= MAXALU) do begin WriteLn('Alumne ',G.Quants+1); Write('Nom: '); ReadLn(N); if N <> '' then {si no s'ha deixat en blanc} begin G.Quants := G.Quants + 1; with G.Alumnes[G.Quants] do begin Nom := N; Write('Cognom 1: '); ReadLn(Cog1); Write('Cognom 2: '); ReadLn(Cog2); Write('Num. matrícula: '); ReadLn(Mat); for i:=1 to NUMNOT do {inicialitzem les notes a No Presentat} Notes[i] := -1.0; end; end; end; {Mostrem per pantalla les dades entrades paginades en grups de NUMLIN alumnes} ClrScr; lin := 0; {Inicialitzem a zero el comptador de línies escrites} for i := 1 to G.Quants do begin if lin = 0 then {Mostrem la capçalera} begin WriteLn('Llistat d''alumnes'); WriteLn; Write('Nom i cognoms '); Writeln('Mat. Nota1 Nota2 Nota3'); WriteLn(stringofchar('=',79)); end; Exemple 18 Programa d'exemple d'estructures complexes
Fonaments d'informàtica
WriteLn; Write('Nom i cognoms '); Writeln('Mat. Nota1 Nota2 Nota3 NotaMitja'); WriteLn(stringofchar('=',79)); end; lin := lin + 1; with G.Alumnes[i] do begin Al := copy(Cog1+' '+Cog2+', '+Nom,1,40); Write(Al,stringofchar(' ',40-length(Al)+1),Mat:5,' '); MitAlu := 0.0; {Inicialitzem la var. d'acumulació de notes d'un alumne} for j:=1 to NUMNOT do begin if Notes[j] >= 0 then {Si nota és no presentat no la sumem} begin MitAlu := MitAlu + Notes[j]; {Acumulació d'un alumne} Mitjes[j] := Mitjes[j] + Notes[j]; {Ac. del control} end; Write(Notes[j]:5:1,' '); end; end; WriteLn(' ',MitAlu/NUMNOT:5:1); {Escrivim la mitja de l'alumne} if lin >= NUMLIN then begin WriteLn('Prem qualsevol tecla per continuar.'); ReadKey; lin := 0; end; end; {Mostrem ara les notes mitjes de cada control} WriteLn(Stringofchar('=',79)); Write('Notes mitjes per control '); MitAlu := 0; {Aprofitem variable per càlcular la mitja del grup} for i:= 1 to NUMNOT do begin Write(Mitjes[i]/G.Quants:5:1,' '); {esc. mitja de cada control} MitAlu := MitAlu + Mitjes[i]/G.Quants; end; WriteLn(' ',MitAlu/NUMNOT:5:1); {escrivim la mitja del grup} WriteLn; WriteLn('Llistat acabat. Prem qualsevol tecla per continuar.'); ReadKey; end. Exemple 20 Programa d'exemple d'estructures complexes (continuació)
Estructures de dades
Veiem ara alguns dels algoritmes d'ordenació. Per implementar els diferents algoritmes farem servir
un array d'enters que hem d'ordenar de menor a major. Amb aquesta definició en pseudocodi i en
Pascal.
Pseudocodi
Const
INI = 1 és enter
FI = 100 és enter
fconst
tipus
TArray és Array [ INI..FI ] de enter
ftipus
Pascal
const
INI = 1;
FI = 100;
type
TArray = Array [INI..FI] of integer;
7.6.1. Mètode de selecció directe
El mètode de selecció parteix de considerar que la zona ordenada està buida i, per tant, la zona
pendent d'ordenar inclou tots els elements.
Dins la zona pendent d'ordenar busquem l'element més petit i l'intercanviem amb el que ocupa la
primera posició de la zona. Un cop fet això tenim que la zona ordenada conté un element i la
pendent d'ordenar un element menys.
Si repetim el procediment, cada cop tenim un element més a la zona ordenada i un menys a la
pendent d'ordenar.
Quan la zona pendent d'ordenar tingui només un element podem acabar, ja que no cal buscar quin
és l'element més petit i intercanviar-lo amb si mateix.
Farem servir la variable i per indicar on comença la zona pendent d'ordenar. Com a cada recorregut
aconseguim un element ordenat la zona anirà començant a INI , INI +1, INI +2... i així successivament.
Fins que la zona comenci a FI , que no hem de fer res. A la variable PosPetit guardarem la posició de
l'element més petit de la zona pendent d'ordenar.
La primera aproximació que podem fer és
per i ← INI fins FI-1 fer PosPetit ← CercarPosicioDelMesPetit(V,i) intercanviar(V[i],V[PosPetit]) fper
De fet aquest programet que hem escrit ja ordena, però clar, ens falta fer la funció
CercarPosicioDelMesPetit i l'acció Intercanviar.
Per això, ara ens plantegem el problema següent: fer una funció que donat un array d'enters i un
enter x que és una posició vàlida de l'array, ens retorni la posició de l'enter més petit situat entre la
posició x i la posició FI de l'array.
En aquest moment és important que ens oblidem que estem ordenant un array, el problema que ens
ocupa ara és fer la funció CercarPosicioDelMesPetit.
Per fer aquesta cerca, utilitzarem la variable Min per emmagatzemar la posició de l'element més petit
que hem trobat fins ara. Considerarem que inicialment el més petit és l'element situat a la posició x ,
per tant, Min valdrà x. Compararem l'element de la posició Min amb els elements de les posicions
x+1 , x+2 , x+3 i així successivament. Cada cop que element d'una posició sigui més petit que el de la
posició Min , emmagatzemarem a Min la posició. Al final del recorregut tindrem a Min la posició del
l'element més petit.
Farem servir la variable i per recorre l'array des de x+1 fins a FI.