Estruturas de dados
10.2. MATRIZES 193 A declara¸c˜ ao do tipo matriz em Pascal ´ e assim:
10.2.2 Exemplos elementares
Do mesmo modo como fizemos para os vetores, vamos iniciar o estudo das matrizes apresentando problemas simples.
Lendo e imprimindo matrizes
A leitura dos elementos de uma matriz ´e bastante parecida com a leitura de vetores.
Imaginando que cada linha da matriz ´e um vetor, basta fixar uma linha e ler todos os elementos das colunas. Agora ´e s´o repetir o procedimento para todas as linhas. Isto leva naturalmente a um c´odigo com um la¸co duplo: um para variar as linhas o outro para as colunas. A figura 10.38 permite visualizar o c´odigo para a leitura de uma matriz.
program ler matriz ;
var w: array [ 0 . . 5 0 , 1 . . 1 0 ] of real; i , j : integer;
begin
for i := 0 to 50 do for j:= 1 to 10 do
read (w[ i , j ] ) ; end.
Figura 10.38: Lendo uma matriz.
Da forma como foi constru´ıdo, este c´odigo exige que se digite os elementos da primeira linha, depois os da segunda e assim por diante. No la¸co mais interno, con-trolado pelo j, observem que o i ´e fixo, apenas o j varia, desta forma, a leitura das
colunas de uma linha fixa ´e idˆentico a ler um vetor. O la¸co mais externo, controlado peloi, faz variar todas as linhas.
Da mesma forma como apresentamos os vetores, vamos mostrar os c´odigos ape-nas em termos de procedimentos e fun¸c˜oes. Para isto vamos precisar considerar as seguintes defini¸c˜oes:
const maxLin = 50; maxCol = 40;
type matriz=array [ 0 . . maxLin, 1 . .maxCol] of integer;
Tamb´em vamos considerar que apenas uma parte da matriz ser´a usada, logo pre-cisaremos sempre fazer a leitura das dimens˜oes de uma matriz. Neste sentido, a figura 10.39 apresenta um procedimento que lˆe uma matriz de dimens˜oes n×m.
procedure ler matriz (varw: matriz ; var n,m: integer) ; var i , j : integer;
begin
read (n) ; (∗ n deve estar no intervalo 1 . .maxLin ∗) read (m) ; (∗ m deve estar no intervalo 1 . .maxLin ∗) for i := 1 to n do
for j:= 1 tomdo read (w[ i , j ] ) ; end;
Figura 10.39: Procedimento para ler uma matriz.
As mesmas observa¸c˜oes sobre passagem de parˆametros que foram feitas sobre os ve-tores se aplicam aqui, isto ´e, pelo overhead, sempre passamos matrizes por referˆencia.
A figura 10.40 apresenta um procedimento para impress˜ao de uma matriz usando passagem de parˆametros por referˆencia, embora n˜ao fosse estritamente necess´ario. O procedimento foi constru´ıdo para imprimir a matriz linha por linha.
procedure imprimir matriz (var w: matriz ; n,m: integer) ; var i , j : integer;
begin
for i := 1 to n do begin
for j:= 1 tomdo write (w[ i , j ] ,’ ’) ;
writeln; (∗ muda de linha a cada fim de coluna ∗) end;
end;
Figura 10.40: Procedimento para imprimir uma matriz.
Tomando como exemplo a matriz do in´ıcio desta se¸c˜ao, se forem digitados todos os valores, linha por linha, para cada uma do in´ıcio at´e o final de cada coluna, ter´ıamos em mem´oria algo como ilustrado na figura seguinte:
10.2. MATRIZES 195 1 2 3 4 5 . . . 40
1 4 6 2 1 ? ?
2 9 0 0 2 ? ?
3 8 7 3 9 ? ?
4 1 2 3 4 ? ?
5 0 1 0 1 ? ?
...
50 ? ? ? ? ? ?
A t´ıtulo de exemplo, poder´ıamos construir um procedimento que imprime a matriz em sua forma transposta, isto ´e, com as linhas e colunas invertidas. Isto ´e apresentado na figura 10.41. Basta inverteriej no comando de impress˜ao! Observem que a matriz n˜ao mudou na mem´oria, apenas a impress˜ao ´e diferente.
procedure imprimir transposta (var w: matriz ; n,m: integer) ; var i , j : integer;
begin
for i := 1 tomdo begin
for j:= 1 to n do write (w[ j , i ] ,’ ’) ; writeln;
end;
end;
Figura 10.41: Procedimento para imprimir a transposta de uma matriz.
Outros procedimentos interessantes s˜ao os de impress˜ao de apenas uma certa linha (figura 10.42) ou de apenas uma certa coluna (figura 10.43).
procedure imprimir uma linha (varw: matriz ; n,m: integer; K: integer) ; (∗ imprime a linha K da matriz ∗)
var j : integer; begin
for j:= 1 tomdo
write (w[K, j ] ,’ ’) ; (∗ K fixo na primeira posicao ∗) writeln;
end;
Figura 10.42: Procedimento para imprimir uma unica linha da matriz.
Considerando o exemplo acima e fazendo K = 2 ter´ıamos a seguinte sa´ıda:
9 0 0 2
Considerando o exemplo acima e fazendo K = 2 ter´ıamos a seguinte sa´ıda:
procedure imprimir uma coluna(var w: matriz ; n,m: integer; K: integer) ; (∗ imprime a coluna K da matriz ∗)
var i : integer; begin
for i := 1 to n do
writeln (w[ i ,K] ) ; (∗ K fixo na segunda posicao ∗) end;
Figura 10.43: Procedimento para imprimir uma unica coluna da matriz.
6 0 7 2 1
Outro exemplo interessante seria imprimir apenas os elementos da matriz que s˜ao pares, conforme mostrado na figura 10.44.
procedure imprimir os pares (var w: matriz ; n,m: integer) ; var i , j : integer;
begin
for i := 1 to n do begin
for j:= 1 tomdo
i f eh par (w[ i , j ] ) then write (w[ i , j ] ,’ ’) ; end;
writeln;
end;
Figura 10.44: Procedimento para imprimir os elementos pares matriz.
Considerando novamente a nossa matriz exemplo, ter´ıamos a seguinte sa´ıda:
4 6 2 0 0 2 8 2 4 0 0
Para finalizarmos esta se¸c˜ao inicial, apresentamos na figura 10.45 um c´odigo que imprime os elementos cujos ´ındices das linhas e das colunas s˜ao pares. Considerando novamente a nossa matriz exemplo, ter´ıamos a seguinte sa´ıda:
0 2 2 4
10.2. MATRIZES 197
procedure imprimir as linhas e colunas pares (varw: matriz ; n,m: integer) ; var i , j : integer;
begin
for i := 1 to n do begin
for j:= 1 tomdo
i f eh par ( i ) and eh par( j ) then write (w[ i , j ] ,’ ’) ;
writeln;
end;
end;
Figura 10.45: Procedimento para imprimir os elementos cujos indices s˜ao pares.
Encontrando o menor elemento de uma matriz
Vamos retornar ao velho e conhecido problema de se determinar qual ´e o menor elemento de um conjunto de n´umeros em mem´oria, considerando que, desta vez, eles estar˜ao armazenados em uma matriz. A figura 10.46 cont´em o c´odigo que faz isto.
Note a semelhan¸ca com os programas das se¸c˜oes anteriores. A t´ecnica ´e a mesma: o primeiro elemento ´e considerado o menor de todos e depois a matriz tem que ser toda percorrida (todas as linhas e todas as colunas) para ver se tem outro elemento ainda menor.
function acha menor matriz (varw: matriz ; n,m: integer) : integer; var i , j : integer;
menor: integer; begin
menor:= w[ 1 , 1 ] ; for i := 1 to n do
for j:= 1 tomdo
i f w[ i , j ] <menor then menor:= w[ i , j ] ; acha menor matriz:= menor;
end;
Figura 10.46: Encontrando o menor elemento de uma matriz.
Soma de matrizes
Nesta se¸c˜ao vamos implementar o algoritmo que soma duas matrizes. Para isto pre-cisamos antes entender como funciona o processo.
Sejam v e w duas matrizes. Para som´a-las, ´e preciso que elas tenham o mesmo tamanho. Isto posto, o algoritmo cria uma nova matrizv+wonde cada elementoi, j da nova matriz ´e a soma dos respectivos elementosv[i, j] ew[i, j]. O esquema ´e muito parecido com a soma de vetores, j´a estudada, apenas, novamente, trata-se tamb´em da segunda dimens˜ao.
Desta forma, o algoritmo que soma os dois vetores dever´a, para cada par i, j fixo, somar os respectivos elementos emv e w e guardar em v+w. Variandoi de 1 at´e o n´umero de linhas e j de 1 at´e o n´umero de colunas resolve o problema. O programa que implementa esta ideia ´e apresentado na figura 10.47.
procedure somar matrizes (var v , w, soma v w : matriz ; n,m: integer) ; var i , j : integer;
begin
(∗ n e m sao o numero de linhas e colunas , respectivamente ∗) for i := 1 to n do
for j:= 1 tomdo
soma v w [ i , j ]:= v [ i , j ] + w[ i , j ] ; end;
Figura 10.47: Somando duas matrizes.
E interessante comparar com o procedimento que soma vetores, apresentado na´ figura 10.13. Se considerarmos que, no la¸co interno controlado peloj oi´e fixo, ent˜ao os dois procedimentos fazem a mesma opera¸c˜ao de somar dois vetores!
Multiplica¸c˜ao de matrizes
Agora vamos resolver o problema da multiplica¸c˜ao de matrizes. Inicialmente vamos recordar como isto ´e feito.
Do ponto de vista matem´atico cada elemento da matriz resultado da multiplica¸c˜ao de duas matrizes pode ser encarado como sendo o produto escalar de dois vetores formados por uma linha da primeira matriz e por uma coluna da segunda.
Vamos considerar duas matrizes An×m e Bm×p. A multiplica¸c˜ao s´o pode ocorrer se o n´umero de colunas da matrizA for igual ao n´umero de linhas da matriz B. Isto por causa do produto escalar de vetores, que exige que os vetores tenham o mesmo tamanho. O resultado ´e uma matriz n×p. O produto escalar de vetores, conforme j´a estudado, ´e o resultado da seguinte somat´oria:
m
X
k=1
V[k]×W[k].
Vamos considerar duas matrizes A e B, fixando uma linha I na matriz A e uma colunaJ na matriz B. Conforme j´a mencionado, fixar linhas ou colunas em matrizes
´e o mesmo que trabalhar com vetores. Ent˜ao, neste caso, o produto escalar da linha I da matriz A pela coluna J da matriz B ´e dado pela seguinte somat´oria:
m
X
k=1
A[I, k]×B[k, J].
O programa que realiza esta opera¸c˜ao ´e uma adapta¸c˜ao simples do c´odigo exibido na figura 10.14, que para fins did´aticos ´e mostrado na figura 10.48.
10.2. MATRIZES 199
begin (∗ considerando I e J fixos ∗) soma:= 0;
for i := 1 tomdo
soma:= soma + A[ I , k ] ∗ B[ k , J ] ; prod escalar:= soma;
end;
Figura 10.48: Produto escalar de uma linha da matriz por uma coluna da outra.
Vejamos isto de forma ilustrada considerando as duas matrizes seguintes:
A:
O produto escalar da linha (terceira) pela coluna (segunda) em destaque ´e o re-sultado da seguinte opera¸c˜ao: 8×3 + 7×0 + 3×7 + 9×0 = 45. Este resultado ´e o valor da linha 3 coluna 2 da matriz produto, isto ´e, ´e o elemento AB[3,2].
Para se obter a resultado completo do produto de A por B, basta variar I nas linhas de A e J nas colunas de B. Isto ´e apresentado na figura 10.49.
procedure multiplicar matrizes (varA: matriz ; lin A , col A : integer; varB: matriz ; lin B , col B : integer;
Figura 10.49: Multiplica¸c˜ao de duas matrizes.