You are on page 1of 15

Universidade Federal de Ouro Preto Instituto de Cincias Exatas e Biolgicas Departamento de Computao

ALGORITMOS E ESTRUTURAS DE DADOS


http://www.decom.ufop.br/prof/menotti/aedI082/tps/tp2.pdf

Matrizes Esparsas Segundo Trabalho disponvel em:

Brayan Vilela Alves Neves Professor - David Menotti

Ouro Preto 30 de maro de 2009

Sumrio
1 Introduo 2 Algoritmo e estruturas de dados 2.1 Estrutura de TMatriz . . . . . . 2.2 Insere/Remove . . . . . . . . . 2.3 Funo Get . . . . . . . . . . . 2.4 Imprime/Soma/Multiplica . . . 3 Anlise de complexidade 3.1 fazMatrizVazia . . . . 3.2 criaMatriz . . . . . . . 3.3 Vazia . . . . . . . . . . 3.4 insere . . . . . . . . . . 3.5 remove . . . . . . . . . 3.6 leMatriz . . . . . . . . 3.7 get . . . . . . . . . . . 3.8 imprimeMatriz . . . . 3.9 somaMatriz . . . . . . 3.10 multiplicaMatriz . . . 4 Concluso
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1 2 2 4 8 8 9 9 9 10 10 10 10 11 11 11 12 12

dos algoritmos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Introduo

Neste trabalho temos a apresentao de um problema na computao. Que a representao de uma grande quantidade de valores em uma matriz, sem se preocupar em ocupar espao com os valores que so nulos (conceito da ultilizao de Matrizes Esparsas). Imagine uma mina de ouro. Agora imagine que nem toda a mina exista ouro. Ento se separarmos esta mina em sees, e cada seo, por exemplo, colocamos a concentrao de ouro que exista nela. Tendo que o ouro um mineral muito raro (supondo que o ouro domina cerca de 30% da rea da mina), logo percebemos que a maioria das nossas sees ter concentrao igual zero. Ento logo nos vem uma pergunta: "Ento no seria invivel representar esta mina por sees j que pelo menos 70% delas so nulas?". Este um dos casos onde podemos aplicar nosso conceito Matriz Esparsa. Uma matriz esparsa ir representar apenas as posies vlidas, sendo assim, analisando o caso da mina de ouro citada acima, nosso banco de dados ir ter apenas 30% do que teria se fosse representar toda a mina, incluindo as partes com concentrao de ouro nula. Em nosso Trabalho iremos apresentar apenas matrizes bidimensionais, tendo em vista que a principio que a base de nossa matriz uma lista encadeada, temos todas as funes bsicas da mesma e outras para operaes entre matrizes:
Faz Matriz Vazia (cria e inicializa o elemento principal da Matriz Esparsa) Vazia (retorna se a matriz j foi criada ou no) Cria Matriz (gera o esqueleto de nossa matriz) Insere (insere um elemento na matriz) Remove (remove um elemento da matriz) L Matriz (recebe um endereo de um arquivo na memria do computador e

l a matriz a partir dele)

Get (l o valor de um item da matriz) Imprime Matriz (imprime a matriz na tela, incluindo as posies nulas) Soma Matriz (retorna uma matriz que a soma de outras duas) Multiplica Matriz (retorna uma matriz que a multiplicao de outras duas)

O trabalho est organizado da seguinte forma. Na Seo 2 so apresentadas as estruturas de dados utilizadas para os algoritmos e uma descrio sobre a implementao daa bibliotecaa. Na Seo 3 so apresentadas as analises de complexidade dos algoritmos utilizados. E nalmente na Seo 4, as concluses so apontadas. 1

2
2.1

Algoritmo e estruturas de dados


Estrutura de TMatriz

Nesta seo apresentada a estrutura de dados, bem como uma leve explicao sobre a interface do programa construdo. A estrutura bsica da matriz esparsa, denida como TMatriz contem um elemento chave: Listagem 1: Estrutura de uma celula de TMatriz
class Celula public :
Apontador { direita , abaixo ;

int l i n h a , c o l u n a ; double v a l o r ;
};

/ C e l u l a /

typedef struct

Celula

Apontador ;

Uma TMatriz Esparsa composta por clulas, cada uma delas armazena Apontadores (uma estrutura que na verdade um ponteiro para clulas) para as clulas da direita e para a clula abaixo, alm disso, tambm guardam os valores inteiros, linha e coluna, que indicam a posio em que a clula se encontra na matriz, alm de uma varivel tipo double que guarda o valor desta clula. Ento com as clulas denidas, temos a estrutura de TMatriz: Listagem 2: Estrutura de TMatriz
c l a s s TMatriz public :
Apontador { cabeca ;

10

int m l i n h a ; int m c o l u n a ; void f a z M a t r i z V a z i a ( void ) ; int V a z i a ( void ) ; void c r i a M a t r i z ( int l i n h a , int c o l u n a ) ; void i m p r i m e M a t r i z ( void ) ; void i n s e r e ( int l i n h a , int c o l u n a , double int r e m o v e ( int l i n h a , int c o l u n a ) ; double g e t ( int l i n h a , int c o l u n a ) ; void l e M a t r i z ( char l o c a l ) ;
};

valor

) ;

/ TMatriz /

A estrutura de TMatriz na verdade uma clula cabea, e dois inteiros que indicam o tamanho vertical (mlinha) e o tamanho horizontal (mcoluna) da matriz, alm das funes j citadas anteriormente na introduo. Ento vamos inicializar esta matriz da seguinte forma. Indicamos quantas linhas e quantas colunas a matriz ter e chamamos o cdigo criaMatriz( int linha, int coluna ): Listagem 3: Funo que cria a estrutura de TMatriz 2

void

TMatriz : : f a z M a t r i z V a z i a ( ) = ( Apontador ) malloc (

cabeca cabeca

sizeof ( Celula ) ) ;

>a b a i x o = c a b e c a ; cabeca d i r e i t a = cabeca ; > cabeca >l i n h a = 1; cabeca >c o l u n a = 1; } / f a z M a t r i z V a z i a /

10

void T M a t r i z : : int i ;
mlinha = = mcoluna

criaMatriz (

int

linha ,

int

coluna

fazMatrizVazia () ; linha ; coluna ; aux 0; i = < cabeca ; linha ; i+ + ) { malloc (

Apontador

15

for (

= aux

20
} aux = i

> d i r e i t a = ( A p o n t a d o r ) aux = aux d i r e i t a ; > aux d i r e i t a = c a b e c a ; > aux >a b a i x o = aux ; aux >c o l u n a = 1; / f o r /
cabeca ; = 0; i < coluna ; i+ + ) {

sizeof ( Celula ) ) ;

for (

25

30

>a b a i x o = ( A p o n t a d o r ) aux = aux >a b a i x o ; aux d i r e i t a = aux ; > aux >a b a i x o = c a b e c a ; aux >l i n h a = 1; } / f o r / / c r i a M a t r i z /
aux

malloc (

sizeof ( Celula ) ) ;

Quando chamamos a funo que cria o esqueleto de nossa matriz, ela automaticamente a funo fazMatrizVazia(), que inicializa a clula cabea de nossa matriz, ento criamos a chave de uma lista circular, fazendo a clula cabea apontar para ela mesmo tanto pra direita quanto para a esquerda e o seu valor de linha e coluna inicializado com -1, para futuro controle da funo.

Figura 1: Clula Cabea inicializada Com a clula cabea inicializada, a funo seta qual ser o nmero de linhas e colunas a matriz ter e cria um Apontador para cabea de nossa funo. Ento atravs de um lao de repetio ele cria quantas colunas matriz ter, alocando espao para a clula de controle de cada coluna, fazendo a clula a esquerda dela apontar para ela, e para manter a lista circular, faz a clula apontar para a cabea, depois volta o Apontador para a cabea e setando a varivel de controle de coluna para -1, e fazendo o mesmo procedimento cria o nmero de linhas, mas movendo os ponteiros abaixo e mudando a varivel de controle linha para -1.

Figura 2: Matriz 2x2 inicializada Para comparar se uma Matriz vazia, ele checa se a matriz uma clula cabea: Listagem 4: Determina se uma matriz vazia
int return
} TMatriz : : Vazia ( ) ( cabeca { = = cabeca

>a b a i x o

> d i r e i t a

) ;

/ Vazia /

Levando em conta que uma Matriz inicializada, mesmo contendo apenas valores nulos (zero), no vazia.

2.2

Insere/Remove

Para inserir um elemento na matriz, informamos apenas as coordenadas onde ele ser inserido e o valor da clula e temos: Listagem 5: Iserindo item na matriz
void T M a t r i z : : int i ; int p a r a =
Apontador insere (

int

linha ,

int

coluna ,

double

valor

0;

Item ; malloc (

Item Item

( Apontador )

sizeof ( Celula ) ) ;

>v a l o r = v a l o r ; I t e m >l i n h a = l i n h a ; I t e m >c o l u n a = c o l u n a ;


Apontador

10

for (

aux 0; i

= <

cabeca ; coluna ; ; i+ + ) {

aux }

= aux

> d i r e i t a

/ f o r /
1 >a b a i x o >l i n h a

15

while ( p a r a == 0 ) { i f ( p a r a == 0 && ( aux>a b a i x o >c o l u n a


>= linha ) ) { Item aux

= =

||

aux

>a b a i x o = aux>a b a i x o ; >a b a i x o = I t e m ;


= 1;

para

20

else
} aux = i

/ i f /

aux = aux >a b a i x o ; / w h i l e / cabeca ; = 0; i < linha ; i+ + ) {

for (

25
}

aux

= aux

>a b a i x o ;

/ f o r /
= 0;

while ( p a r a == 0 ) { i f ( p a r a == 0 && ( aux> d i r e i t a >l i n h a


c o l u n a >= coluna ) ) { ;

para

= =

||

aux

> d i r e i t a >

30

Item aux

> d i r e i t a = aux> d i r e i t a > d i r e i t a = I t e m ;


= 1;

para

else
35

/ i f /
{ = aux

aux }

> d i r e i t a

} / w h i l e / / i n s e r e /

Primeiro aloca-se a clula e seta seus atributos linha, coluna e valor, depois se cria um Apontador que apontara para cabea da matriz. Ento ele andara para direita at a coluna determinada, a partir da ele ter que achar a linha correta fazendo comparaes, se o valor de controle de coluna for igual a -1 ou maior ou igual ao determinado, ele ira setar a posio ali, fazendo a manipulao de Apontadores:
A nova clula aponta (abaixo) para o item abaixo (Clula sucessora ou esqueleto). A clula Apontada seta seu apontador (abaixo) para nova clula.

Supondo que chamamos o comando insere(1,1,50), temos at agora:

Figura 3: Inserindo clula - Parte I Agora fazendo processos anlogos aos processos acima, trocando onde for linha por coluna e onde for abaixo por direita. Temos: 5

Figura 4: Inserindo clula - Parte II Com o item inserido no lugar correto, atravs da funo remove, que o processo inverso da insere, podemos retirar a clula valida do local: Listagem 6: Removendo item da matriz
int int
TMatriz : : remove ( i ; aux 0; i = < cabeca ; coluna ; ; i+ + ) {

int

linha ,

int

coluna

Apontador

for (

aux

for ( i if (
10

> d i r e i t a / f o r /
= aux = 0; i < aux

linha ;

i+ +

>a b a i x o >l i n h a == l i n h a ) { aux >a b a i x o = aux >a b a i x o >a b a i x o ;


aux

for (

= i

cabeca ; = 0; i < linha ; i+ + )

for ( i if (
15

aux

= aux = 0;

>a b a i x o ;
i < coluna ; i+ + )

> d i r e i t a >c o l u n a == c o l u n a ) { aux d i r e i t a = aux d i r e i t a d i r e i t a > > >


aux

return
{

1;

else
20
}

/ i f /
;

else
25
} }

= aux d i r e i t a > / e l s e / / i f / aux } {

/ remove /

return

= aux >a b a i x o ; / e l s e / / f o r / aux } 0;

A diferena que primeiro s recebemos no parmetro a posio da clula a ser removida. Ento se procura a clula tanto por cima quanto pela direita, seta a clula anterior apontar para a prxima depois da selecionada e destri a clula selecionada.

Tambm temos a opo de ler um bloco de clulas de uma s vez, atravs da funo leMatriz( char* ): Listagem 7: Funo que l um bloco de clulas a partir de um arquivo
void
TMatriz : : l e M a t r i z (

char l o c a l
"r" ) ;

FILE

int m, n , i , j ; double v a l o r ;
fscanf ( arq , criaMatriz (

arq

fopen ( l o c a l ,

"%d, %d" ,&m,& n ) ;


n ) ;

10

i f ( arq ) while ( !
}

m,

f e o f ( arq ) ) ( arq , i ,

fscanf insere (

"%d, %d, %lf" ,& i ,& j ,& v a l o r ) ;


valor ) ;

j ,

/ w h i l e /

f c l o s e ( arq ) ;

15

/ LeMatriz /

Que recebe uma string com um endereo do disco rgido contendo um arquivo que tenha as informaes no formato correto: 2, 2 1, 1, 50.0 2, 1, 10.0 A primeira linha do arquivo uma dupla com o numero de linhas e colunas da matriz, e o restante do arquivo de triplas com as coordenadas do prximo ponto e o valor da clula correspondente. Aps chamar a funo com o arquivo acima temos a matriz:

Figura 5: Matriz lida a partir do arquivo

2.3

Funo Get

Esta a funo chave para a resoluo do resto do programa: Listagem 8: Retorna valor da posio dada
double
TMatriz : : g e t ( aux i = = 0;

int
<

linha ,

int
){

coluna

Apontador

for ( int
}

cabeca ; i linha ; i+ +

aux

= aux

>a b a i x o ;
i+ + != ){ )

for ( int i = 0 ; i < c o l u n a ; i f ( aux> d i r e i t a >c o l u n a else return


} } aux = aux

/ f o r /

coluna

> d i r e i t a

10

aux

> d i r e i t a >v a l o r ;

/ g e t /

return

/ f o r /
0;

A funo get(int, int), aps dar o valor da linha e da coluna, ela retorna o valor da clula, e caso ela no exista, retorna o numero zero que corresponde que no existe a clula procurada na matriz, e logo por ela ser nula seu valor zero.

2.4

Imprime/Soma/Multiplica

Com o auxilio da funo Get, usaremos apenas simples algoritmos de Impresso, soma e multiplicao de matrizes para resolver tais problemas[1] Listagem 9: Simples altoritmos de manipulao de matrizes usando a funo Get
void T M a t r i z : : i m p r i m e M a t r i z ( ) int i , j ;
printf ( {

for ( i = 1 ; i < m l i n h a + 1 ; i++ for ( j = 1 ; j < m c o l u n a + 1 ; i f ( g e t ( i , j ) == 0 )


"%lf\t" , g e t ( i "\n" ) ; } / f o r / p r i n t f ( "\n" ) ; / imprimeMatriz /
printf ( printf ( somaMatriz ( TMatriz A,

"\n" ) ;

{ )

j+ +

else

printf (

"0\t\t" ) ;

, j )) ;

10

15

TMatriz

i f (A . m l i n h a
TMatriz

TMatriz

{ {

= = B. mlinha C;

& & A . mcoluna = = B . mcoluna )

C. c r i a M a t r i z (

20

int i , j ; for ( i = 1 ; for ( j =


C;

A. mlinha ,

A . mcoluna

) ;

i 1;

< C . m l i n h a +1; j

i+ +

) j+ + )

< C . mcoluna +1;

return

C . i n s e r e ( i , j , ( A . g e t ( i , j )+ . g e t ( i , j ) ) ) ; B

25

"No possivel somar matrizes de dimensoes diferentes .\n" ) ; / somaMatriz /


printf ( multiplicaMatriz ( TMatriz ) { A, TMatriz B ) {

else

/ i f /

TMatriz

30

if (

A . mcoluna = = B. mlinha TMatriz C; A. mlinha ,

C. c r i a M a t r i z (

35

int i , j ; for ( i = 1 ; i < C . m l i n h a + 1 ; i++ for ( j = 1 ; j < C . m c o l u n a + 1 ; double k = 0 ; for ( int soma = 1 ; soma <
k + = A . g e t ( i , soma ) C. i n s e r e ( i , j , k ) ; }

B . mcoluna

) ;

) j+ + ) {

C . mcoluna +1; j ) ;

soma+ +

B . g e t ( soma ,

40

return
}

/ f o r /

C;

45

"O numero de colunas da primeira Matriz tem que ser igual ao numero de linhas da segunda Matriz .\n" ) ; / m u l t i p l i c a M a t r i z /
printf (

else

/ i f /

3
3.1

Anlise de complexidade dos algoritmos


fazMatrizVazia

A funo fazMatrizVazia(), conta apenas com uma alocao de memria e 4 atribuies, sendo assim: O(5) O(1).

3.2

criaMatriz

A funo criaMatriz( int n, int m ), contem uma chama da funo fazMatrizVazia( O(1) ), 3 atribuies, um for de tamanho n com 5 atribuies, mais uma atribuio e outro for de tamanho m de 5 atribuies:
O(4) + n 5 + O(1) + i=0 O(5 + 5n + 5m) O(n + m) Se, n > ou = m : O(n). Se, m > n : O(m).
m i=0

3.3

Vazia

A funo Vazia(), conta com apenas uma comparao:


O(1).

3.4

insere

A funo insere( int n, int m, double x ), comea com 6 atribuies, um for de tamanho m com uma atribuio, um while que no pior caso tem tamanho n, contendo um if de 3 atribuies no pior caso, uma atribuio, um outro for com tamanho n, outra atribuio e de m mais um while de tamanho m e com um if de 3 atribuies no pior caso.
O(6) + m 1 + n 4 + O(1) + n 1 + O(1) + i=0 i=0 i=0 O(8 + m + 4n + n + 4m) = O(8 + 5n + 5m) O(n + m) Se, n > ou = m : O(n). Se, m > n : O(m).
m i=0

4.

3.5

remove

A funo remove( int n, int m), conta com uma atribuio, um for de tamanho m de uma atribuio, um for de tamanho n com um if, que no pior caso tem 2 comparaes e 2 for, um de tamanho n com uma atribuio e outro de tamanho m com uma atribuio tambm.
O(1) + m 1 + n (2 + i=0 i=0 O(1 + m + 2n + n2 + nm) O(n + m + nm + n2 ) Se, n > ou = m : O(n2 ). Se, m > n : O(nm).
n i=0

1+

m i=0

1)

3.6

leMatriz

A funo leMatriz( char* f ), conta com 3 atribuies, uma chamada de criaMatriz( int n, int m ) (O(n + m)), um if que no pior caso tem um while de tamanho f com 3 atribuies e uma chamada de insere( int i, int j, double v ) O(i + j)
O(3) + O(n + m) + f (3 + O(i + j)) i=0 O(3 + n + m + 3f + f i + f j)

10

O(n + m + f + f i + f j) O(n + m + f i + f j)

Podendo ter 4 respostas diferentes, de acordo com o tamanho das entradas, se n for maior ser O(n), se m for maior ser O(m), se (f*i) for maior ser O() e por m se (f*j) for maior ser O(fj).

3.7

get

A funo get( int n, int m ), tem uma atribuio e 2 for, o primeiro com tamanho n e 1 atribuio e outro de tamanho m com um if com uma atribuio no pior caso.
O(1) + n 1 + i=0 O(1 + n + m) Se, n > ou = m : O(n). Se, m > n : O(m).
m i=0

3.8

imprimeMatriz

A funo imprimeMatriz(), comea com uma atribuio tem um for de tamanho mlinha (l) com outro for em cascata de tamanho mcoluna (c) com um if de uma atribuio no pior caso.
O(1) + O(1 + l c) O(lc).
l i=0 ( c i=0

1)

3.9

somaMatriz

A funo somaMatriz( TMatriz a, TMatriz b ), conta com 1 if de 2 comparaes que no pior caso, chama a funo criaMatriz( int n, int m ) (O(n + m)) e com 2 for em cascata, o primeiro de tamanho n e o segundo de tamanho m com uma chamada de insere( int i, int j, double x ) O(i + j), sendo o valor maximo de i, n e o valor maximo de j, m, no nal do segundo.
O(2) (O(n + m) + n ( m (O(i + j)))) i=0 i=0 O(2) (O(n + m) + n (O(m n + m2 ))) i=0 O(2) (O(n + m + mn2 + nm2 )) O(2n + 2m + 2mn2 + 2nm2 ) O(n + m + mn2 + nm2 ) O(mn2 + nm2 ) Se, n > ou = m : O(mn2 ).

11

Se, m > n : O(nm2 ).

3.10

multiplicaMatriz

A funo multiplicaMatriz( TMatriz a, TMatriz b ), tem um if que no pior caso tem a chamada de criaMatriz( int n, int m ) (O(n + m)), um for de tamanho n com um for em cascata de tamanho m com uma atribuio e outro for em cascata de tamanho m com uma chamada de insere( int i, int j, double x ) O(i + j), sendo o valor maximo de i, n e o valor maximo de j, m.
O(1) (O(n + m) + n ( m (1 + m (O(i + j))))) i=0 i=0 i=0 O(1) (O(n + m) + n ( m (O(1 + nm + m2 )))) i=0 i=0 O(1) (O(n + m) + n (O(m + nm2 + m3 ))) i=0 O(1) (O(n + m) + O(nm + (nm)2 + nm3 )) O(1) (O(n + m + nm + (nm)2 + nm3 )) O(n + m + nm + (nm)2 + nm3 ) O((nm)2 + nm3 ) Se, n > ou = m : O((nm)2 ). Se, m > n : O(nm3 ).

Concluso

O conceito de Matrizes Esparsas muito til quando se trata da representao de poucos nmeros em um grande bloco de nmeros, mas a memria consumida no caso de um bloco pequeno muito maior do que esperado, sendo melhor criar matrizes no esparsas como a do TP1[1] . Durante o estruturamento da matriz, a nica diculdade foi a manipulao dos ponteiros, para que se encaixassem de acordo com que a estrutura casse sempre circular. Depois da estrutura pronta, montei a estrutura de imprimir e de somar sem problemas, capturando os itens direto das matrizes, mas isso fazia as funes simples carem muito extensas, e quando chegou a vez de implementar a funo de multiplicao, que teria que armazenar muitos valores para a composio de um valor na nova matriz, ai sim existiu o grande problema, por o cdigo caria realmente muito mais extenso, ento observando novamente o TP1, tive a idia de criar a funo get, que me retornava os valores diretamente sem precisar deixar os cdigos extensos como estavam. Ento simpliquei as funes de imprimir e somar com a nova get e z tranquilamente funo de multiplicar.

12

Referncias
[1]

http://www.republicaartemanha.com/Quase/TMatriz.pdf

A Produzido em LTEX

13

You might also like