Escolar Documentos
Profissional Documentos
Cultura Documentos
Departamento de Computação
Ouro Preto
30 de março de 2009
Sumário
1 Introdução 1
2 Algoritmo e estruturas de dados 2
2.1 Estrutura de TMatriz . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.2 Insere/Remove . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.3 Função Get . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.4 Imprime/Soma/Multiplica . . . . . . . . . . . . . . . . . . . . . . . . 8
4 Conclusão 12
2
1 Introdução
Neste trabalho temos a apresentação de um problema na computação. Que é
a representação de uma grande quantidade de valores em uma matriz, sem se
preocupar em ocupar espaço com os valores que são nulos (conceito da ultilização
de Matrizes Esparsas).
Imagine uma mina de ouro. Agora imagine que nem toda a mina exista ouro.
Então se separarmos esta mina em seções, e cada seção, por exemplo, colocamos a
concentração 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 seções terá concentração igual à zero. Então logo nos vem uma
pergunta: "Então não seria inviável representar esta mina por seções já que pelo
menos 70% delas são nulas?".
Este é um dos casos onde podemos aplicar nosso conceito Matriz Esparsa. Uma
matriz esparsa irá representar apenas as posições válidas, 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 concentração de
ouro nula.
1
2 Algoritmo e estruturas de dados
2.1 Estrutura de TMatriz
Nesta seção é apresentada a estrutura de dados, bem como uma leve explicação
sobre a interface do programa construído. A estrutura básica da matriz esparsa,
denida como TMatriz contem um elemento chave:
public :
Apontador direita , abaixo ;
int l i n h a , c o l u n a ;
5 double v a l o r ;
}; /∗ C e l u l a ∗/
Uma TMatriz Esparsa é composta por células, cada uma delas armazena Apontadores
(uma estrutura que na verdade é um ponteiro para células) para as células da direita
e para a célula abaixo, além disso, também guardam os valores inteiros, linha e
coluna, que indicam a posição em que a célula se encontra na matriz, além de uma
variável tipo double que guarda o valor desta célula.
Então com as células denidas, temos a estrutura de TMatriz:
public :
Apontador cabeca ;
int m l i n h a ;
5 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 ) ;
10 void i n s e r e ( int l i n h a , int c o l u n a , double valor ) ;
Então vamos inicializar esta matriz da seguinte forma. Indicamos quantas linhas
e quantas colunas a matriz terá e chamamos o código criaMatriz( int linha, int
coluna ):
2
void TMatriz : : f a z M a t r i z V a z i a ( ) {
5 c a b e c a −>l i n h a = − 1;
c a b e c a −>c o l u n a = − 1;
} /∗ f a z M a t r i z V a z i a ∗/
10 int i ;
fazMatrizVazia () ;
mlinha = linha ;
mcoluna = coluna ;
aux−> d i r e i t a = c a b e c a ;
aux−>a b a i x o = aux ;
20 aux−>c o l u n a = − 1;
} /∗ f o r ∗/
aux = cabeca ;
−>a b a i x o = ( A p o n t a d o r )
aux malloc ( sizeof ( Celula ) ) ;
25 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 ∗/
30 } /∗ c r i a M a t r i z ∗/
Quando chamamos a função que cria o esqueleto de nossa matriz, ela automaticamente
a função fazMatrizVazia(), que inicializa a célula cabeça de nossa matriz, então
criamos a chave de uma lista circular, fazendo a célula cabeça 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 função.
Com a célula cabeça inicializada, a função seta qual será o número de linhas e
colunas a matriz terá e cria um Apontador para cabeça de nossa função. Então
através de um laço de repetição ele cria quantas colunas à matriz terá, alocando
espaço para a célula de controle de cada coluna, fazendo a célula a esquerda dela
apontar para ela, e para manter a lista circular, faz a célula apontar para a cabeça,
depois volta o Apontador para a cabeça e setando a variável de controle de coluna
para -1, e fazendo o mesmo procedimento cria o número de linhas, mas movendo os
ponteiros abaixo e mudando a variável de controle linha para -1.
3
Figura 2: Matriz 2x2 inicializada
Para comparar se uma Matriz é vazia, ele checa se a matriz é uma célula cabeça:
} / ∗ Vazia ∗ /
Levando em conta que uma Matriz inicializada, mesmo contendo apenas valores
nulos (zero), não é vazia.
2.2 Insere/Remove
int i ;
int p a r a = 0;
Apontador Item ;
I t e m −>c o l u n a = c o l u n a ;
} /∗ f o r ∗/
while ( p a r a == 0 ) {
15 i f ( p a r a == 0 && ( aux−>a b a i x o −>c o l u n a == −1 || −>a b a i x o −>l i n h a
aux
>= linha ) ) {
4
} /∗ i f ∗/
20 else
aux = aux−>a b a i x o ;
} /∗ w h i l e ∗/
aux = cabeca ;
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 == −1 || −> d i r e i t a −>
aux
c o l u n a >= coluna ) ) {
aux −> d i r e i t a = I t e m ;
para = 1;
} /∗ i f ∗/
else {
} /∗ w h i l e ∗/
} /∗ i n s e r e ∗/
Primeiro aloca-se a célula e seta seus atributos linha, coluna e valor, depois se cria
um Apontador que apontara para cabeça da matriz. Então ele andara para direita
até a coluna determinada, a partir daí ele terá que achar a linha correta fazendo
comparações, se o valor de controle de coluna for igual a -1 ou maior ou igual ao
determinado, ele ira setar a posição ali, fazendo a manipulação de Apontadores:
• A nova célula aponta (abaixo) para o item abaixo (Célula sucessora ou esqueleto).
• A célula Apontada seta seu apontador (abaixo) para nova célula.
Agora fazendo processos análogos aos processos acima, trocando onde for linha
por coluna e onde for abaixo por direita. Temos:
5
Figura 4: Inserindo célula - Parte II
Com o item inserido no lugar correto, através da função remove, que é o processo
inverso da insere, podemos retirar a célula valida do local:
int i ;
5 aux −> d i r e i t a
= aux ;
} /∗ f o r ∗/
for ( i = 0; i < linha ; i++ ) {
if ( −>a b a i x o −>l i n h a == l i n h a ) {
aux
10 aux = cabeca ;
if ( −> d i r e i t a −>c o l u n a == c o l u n a ) {
aux
return 1;
} /∗ i f ∗/
else {
= aux−> d i r e i t a
aux ;
20 /∗ e l s e ∗/
}
} /∗ i f ∗/
else {
= aux−>a b a i x o ;
aux
/∗ e l s e ∗/
}
25 } /∗ f o r ∗/
return 0;
} / ∗ remove ∗ /
6
Também temos a opção de ler um bloco de células de uma só vez, através da
função leMatriz( char* ):
i f ( arq )
10 while ( ! f e o f ( arq ) ) {
} /∗ w h i l e ∗/
f c l o s e ( arq ) ;
15 } / ∗ LeMatriz ∗ /
Que recebe uma string com um endereço do disco rígido contendo um arquivo
que tenha as informações no formato correto:
2, 2
1, 1, 50.0
2, 1, 10.0
7
2.3 Função Get
else
10 return aux −> d i r e i t a −>v a l o r ;
} /∗ f o r ∗/
return 0;
} /∗ g e t ∗/
A função get(int, int), após dar o valor da linha e da coluna, ela retorna o valor
da célula, e caso ela não exista, retorna o numero zero que corresponde que não
existe a célula procurada na matriz, e logo por ela ser nula seu valor é zero.
2.4 Imprime/Soma/Multiplica
int i , j ;
printf ( "\n" ) ;
for ( i = 1 ; i < m l i n h a + 1 ; i++ ) {
i f ( g e t ( i , j ) == 0 )
printf ( "0\t\t" ) ;
else
printf ( "%lf\t" , g e t ( i , j )) ;
10 printf ( "\n" ) ;
} /∗ f o r ∗/
p r i n t f ( "\n" ) ;
} / ∗ imprimeMatriz ∗ /
i f (A . m l i n h a == B . m l i n h a && A . m c o l u n a == B . m c o l u n a ) {
TMatriz C;
C. c r i a M a t r i z ( A. mlinha , A . mcoluna ) ;
int i , j ;
20 for ( i = 1 ; i < C . m l i n h a +1; i++ )
C . i n s e r e ( i , j , ( A . g e t ( i , j )+B . g e t ( i , j ) ) ) ;
return C;
8
} /∗ i f ∗/
25 else
"Não é possivel somar matrizes de dimensoes diferentes
printf (
.\n" ) ;
} / ∗ somaMatriz ∗ /
30 if ( A . m c o l u n a == B . m l i n h a ) {
TMatriz C;
C. c r i a M a t r i z ( A. mlinha , B . mcoluna ) ;
int i , j ;
for ( i = 1 ; i < C . m l i n h a + 1 ; i++ )
double k = 0 ;
for ( int soma = 1 ; soma < C . mcoluna +1; soma++ )
k += A . g e t ( i , soma ) ∗B . g e t ( soma , j ) ;
C. i n s e r e ( i , j , k ) ;
40 } /∗ f o r ∗/
return C;
} /∗ i f ∗/
else
printf ( "O numero de colunas da primeira Matriz tem que ser
igual ao numero de linhas da segunda Matriz .\n" ) ;
45 } /∗ m u l t i p l i c a M a t r i z ∗/
O(5) O(1).
3.2 criaMatriz
9
3.3 Vazia
O(1).
3.4 insere
O(6) + m n n
P P P Pm
i=0 1 + i=0 4 + O(1) + i=0 1 + O(1) + i=0 4.
O(8 + m + 4n + n + 4m) = O(8 + 5n + 5m)
O(n + m)
Se, n > ou = m :
O(n).
Se, m > n :
O(m).
3.5 remove
A função remove( int n, int m), conta com uma atribuição, um for de tamanho
m de uma atribuição, um for de tamanho n com um if, que no pior caso tem 2
comparações e 2 for, um de tamanho n com uma atribuição e outro de tamanho m
com uma atribuição também.
O(1) + m n
P P Pn Pm
i=0 1 + i=0 (2 + i=0 1+ i=0 1)
2
O(1 + m + 2n + n + nm)
O(n + m + nm + n2 )
Se, n > ou = m :
O(n2 ).
Se, m > n :
O(nm).
3.6 leMatriz
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)
3.7 get
A função get( int n, int m ), tem uma atribuição e 2 for, o primeiro com tamanho n
e 1 atribuição e outro de tamanho m com um if com uma atribuição no pior caso.
O(1) + ni=0 1 +
P Pm
i=0 1
O(1 + n + m)
Se, n > ou = m :
O(n).
Se, m > n :
O(m).
3.8 imprimeMatriz
3.9 somaMatriz
11
Se, m > n :
O(nm2 ).
3.10 multiplicaMatriz
4 Conclusão
O conceito de Matrizes Esparsas é muito útil quando se trata da representação de
poucos números em um grande bloco de números, mas a memória consumida no
caso de um bloco pequeno é muito maior do que é esperado, sendo melhor criar
matrizes não esparsas como a do TP1[1] . Durante o estruturamento da matriz,
a única diculdade foi a manipulação 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 funções simples carem muito extensas, e
quando chegou a vez de implementar a função de multiplicação, que teria que
armazenar muitos valores para a composição de um valor na nova matriz, ai sim
existiu o grande problema, por o código caria realmente muito mais extenso, então
observando novamente o TP1, tive a idéia de criar a função get, que me retornava os
valores diretamente sem precisar deixar os códigos extensos como estavam. Então
simpliquei as funções de imprimir e somar com a nova get e z tranquilamente à
função de multiplicar.
12
Referências
[1]
http://www.republicaartemanha.com/Quase/TMatriz.pdf
Produzido em LATEX
13