Estruturas de Dados: Matrizes em C++
Estruturas de Dados: Matrizes em C++
DCC200 – Algoritmos II
1 / 99
Conteúdo
▶ Introdução
▶ TADs
▶ TAD Vetor
▶ TAD Vetor Flexı́vel
▶ TAD Matriz
▶ TAD Matriz - Representação Linear
▶ TAD Matriz Flexı́vel - Representação Linear
▶ Matrizes Especiais
▶ Diagonal
▶ Triangular Inferior (ou Superior)
▶ Simétrica
▶ Anti-Simétrica
▶ Matrizes Esparsas
▶ Vetor Esparso
▶ Matriz Esparsa
2 / 99
Introdução
3 / 99
Introdução
4 / 99
TADs
5 / 99
TAD Vetor
▶ Seja o TAD Vetor de n elementos reais, representado na
classe em C++ a seguir:
class Vetor
{
public:
Vetor(int tam);
∼Vetor();
float get(int indice);
void set(int indice, float valor);
private:
int n; // tamanho do vetor
float *vet; // array que armazena n floats
6 / 99
TAD Vetor
7 / 99
TAD Vetor
▶ Construtor e destrutor
Vetor::Vetor(int tam) {
// inicializa a variavel interna n e
// aloca memoria para o vetor vet
n = 0;
if (n > 0)
n = tam;
vet = new float[n];
Vetor::∼Vetor() {
// desaloca a memoria alocada no construtor
delete [] vet;
}
8 / 99
TAD Vetor
9 / 99
TAD Vetor
float Vetor::get(int indice)
{
if ( verifica(indice) )
return vet[indice];
else {
cout << "Indice invalido: get" << endl;
exit(1) ; // finaliza o programa
}
}
int main() {
int tam = 60;
Vetor v(tam); // aloca vet[60]
Programa
VetorFlex v(-5, 6);
C F
-5 -4 -3 -2 -1 0 1 2 3 4 5 6
TAD VetorFlex
C/C++ índices 0 1 2 3 4 5 6 7 8 9 10 11
13 / 99
TAD VetorFlex
class VetorFlex
{
private:
int n; // tamanho do vetor
float *vet; // array que armazena n floats
int c, f // c: limite inferior do indice
// f: limite superior do indice
public:
VetorFlex(int a, int b);
∼VetorFlex();
float get(int indice);
void set(int indice, float valor);
};
14 / 99
TAD VetorFlex
// construtor
VetorFlex::VetorFlex(int cc, int ff)
{
c = cc;
f = ff;
n = f - c + 1;
vet = new double[n];
}
// destrutor
VetorFlex::∼VetorFlex()
{
delete [] vet;
}
15 / 99
TAD VetorFlex
16 / 99
TAD VetorFlex
17 / 99
TAD VetorFlex
float VetorFlex::get(int indice) {
int i = detInd(indice);
if(i != -1)
return vet[i];
else {
cout << "Indice invalido: get\n";
exit(1);
}
}
#include "VetorFlex.h"
int main()
{
int cc = -29; int ff = 30;
VetorFlex v(cc,ff);
for(int i = cc; i <= ff; i++)
{ // valores no intervalo 1...60
double val = i - cc + 1;
[Link](i,val);
}
for(int i = cc; i <= ff; i++)
{
double val = [Link](i);
cout << val << endl;
}
return 0;
}
19 / 99
Matrizes
20 / 99
Matrizes
21 / 99
Matrizes
▶ TAD Matriz2D
▶ Representação por ponteiro de ponteiro (ou vetor de
vetores).
▶ Esquema:
22 / 99
TAD Matriz2D
▶ Classe para o TAD Matriz de 2 dimensões:
class Matriz2D
{
public:
Matriz2D(int nnl, int nnc);
∼Matriz2D();
private:
int nl; // numero de linhas
int nc; // numero de colunas
float **mat; // array com nl*nc floats
Matriz2D::∼Matriz2D()
{
// desaloca a memoria alocada no construtor
for(int i = 0; i < nl; i++)
delete [] mat[i];
delete [] mat;
}
24 / 99
TAD Matriz2D
25 / 99
TAD Matriz2D
float Matriz2D::get(int i, int j)
{
if ( verifica(i, j) )
return mat[i][j];
else {
cout << "Erro: indice invalido" << endl;
exit(1);
}
}
27 / 99
Aplicação com o TAD Matriz2D
#include "Matriz2D.h"
int main() {
Matriz2D mat(5,5);
// etc ...
return 0;
} 28 / 99
Matriz
▶ No TAD Matriz2D, apresentado anteriormente, usamos
um array bidimensional float **mat para representar a
matriz e o acesso era realizado com a seguinte operação:
mat[i][j].
▶ Seja a matriz A (3 × 4) de inteiros
5 9 6 7
A = −3 2 0 4
1 8 3 −5
▶ Também pode-se armazenar a matriz A na memória
usando um único array unidimensional float *mat,
assim todos os elementos de A serão armazenados em
posições consecutivas de memória a partir de um endereço
base.
▶ Essa forma é conhecida como representação linear.
29 / 99
Matriz
Representação linear
30 / 99
Matriz
Representação linear
31 / 99
Matriz
Representação linear
k = 4i + j
32 / 99
Matriz
Representação linear
▶ Assim, dados:
▶ o vetor V (representação linear da matriz A)
▶ um par de ı́ndices válidos i e j de A
k = 4i + j
33 / 99
Matriz
Representação linear
34 / 99
TAD Matriz
class MatrizLin
{
public:
MatrizLin(int m, int n);
∼MatrizLin();
private:
int nl, nc; // numero de linhas e colunas
float *vet; // vetor de tamanho nl*nc
35 / 99
TAD Matriz - Representação linear
▶ Construtor e destrutor
MatrizLin::MatrizLin(int m, int n)
{
// inicializa as variaveis internas
// e aloca memoria de vet (representacao linear)
nl = m;
nc = n;
vet = new float[nl*nc];
}
MatrizLin::∼MatrizLin()
{
// desaloca a memoria alocada no construtor
delete [] vet;
}
36 / 99
TAD Matriz - Representação linear
37 / 99
TAD Matriz - Representação linear
float MatrizLin::get(int i, int j)
{
int k = detInd(i, j);
if(k != -1)
return vet[k];
else {
cout << "Erro: get" << endl;
exit(1);
}
}
int main() {
int m = 7, n = 11;
MatrizLin mat(m,n);
return 0;
}
39 / 99
Matriz - Representação linear
I = (C − c2 ) + n(L − c1 ).
40 / 99
TAD Matriz Flexı́vel - Representação linear
41 / 99
TAD MatrizFlex
class MatrizFlex
{
public:
MatrizFlex(int cc1, int ff1, int cc2, int ff2);
∼MatrizFlex();
private:
float *vet; // representacao linear da matriz
int m, n; // numero de linhas e colunas
int c1; // limite inicial da linha
int c2; // limite inicial da coluna
int f1; // limite final da linha
int f2; // limite final da coluna
int detInd(int linha, int coluna);
};
42 / 99
TAD MatrizFlex
▶ Construtor e destrutor
MatrizFlex::MatrizFlex(int cc1, int ff1,
int cc2, int ff2)
{
// inicializa os limites
c1 = cc1;
c2 = cc2;
f1 = ff1;
f2 = ff2;
m = f1 - c1 + 1; // calcula o numero de linhas
n = f2 - c2 + 1; // calcula o numero de colunas
vet = new float[m*n] ;
}
MatrizFlex::∼MatrizFlex()
{
delete [] vet;
}
43 / 99
TAD MatrizFlex
44 / 99
TAD MatrizFlex
float MatrizFlex::get(int i, int j)
{
int k = detInd(i, j) ;
if(k != -1)
return vet[k];
else
cout << "Indice invalido: get" << endl;
exit(1);
}
int main(){
int c1 = -2, f1 = 7;
int c2 = 0, f2 = 5;
MatrizFlex mat(c1,f1,c2,f2);
47 / 99
Matrizes Especiais
▶ Matriz Diagonal
▶ Matriz Triangular Inferior
▶ Matriz Triangular Superior
▶ Matriz Simétrica
▶ Matriz Anti-Simétrica
▶ Matriz Tridiagonal
48 / 99
Matrizes Especiais
49 / 99
Introdução
Representação Linear
50 / 99
Matriz Diagonal
a00
a11
i==j
a22
... diagonal
principal
dia
gon
al
pr
inc
ipa
l i != j
...
fora da diagonal
principal
an-1n-1
a00 a11 a
vet 22 an-1n-1
0 1 2 n-1
51 / 99
Matriz Triangular
52 / 99
Matriz Triangular Inferior
▶ Questões importantes:
1. Quantos elementos armazenar?
2. Representação linear: como armazenar os elementos?
3. Como acessar/modificar um elemento?
53 / 99
Matriz Triangular Inferior
1 0 0 0 0
2 3 0 0 0
4 5 6 0 0
7 8 9 10 0
11 12 13 14 15
Representação linear
índices 0 1 2 3 4 5 6 13 14
54 / 99
Matriz Triangular Inferior
▶ Quantos elementos a matriz triangular inferior L de
dimensão n possui?
l11 0 0 ... 0
l21 l22 0 . . . 0
L = l31 l32 l33 . . . 0
.. ..
. .
ln1 ln2 ln3 . . . lnn
56 / 99
Matriz Triangular Inferior
1 0 0 0 0
2 3 0 0 0
4 5 6 0 0
7 8 9 10 0
11 12 13 14 15
vet 1 2 3 4 5 6 7 8 9 10 11 12 131415
57 / 99
Matriz Triangular Inferior
▶ Como acessar/modificar um elemento?
▶ Para acessar o elemento na posição (i, j):
▶ Contar quantos elementos tem antes da linha i:
1 0 0 0 0
2 3 0 0 0
4 5 6 0 0
7 8 9 10 0
11 12 13 14 15
índices 0 1 2 3 4 5 6 ...
vet 1 2 3 4 5 6 7 8 9 ...
class MatrizTriInf
{
public:
MatrizTriInf(int ordem);
∼MatrizTriInf();
private
int n; // ordem da matriz triangular
float *vet; // representacao linear
59 / 99
Matriz Triangular Inferior
MatrizTriInf::MatrizTriInf(int ordem)
{
n = ordem;
int tam = n*(n + 1)/2;
vet = new float[tam];
}
MatrizTriInf::∼MatrizTriInf()
{
delete [] vet;
}
61 / 99
Matriz Triangular Inferior
void MatrizTriInf::set(int i, int j, float val)
{
if(verifica(i, j))
{
if(i >= j)
{
int k = i*(i + 1)/2 + j;
vet[k] = valor;
}
else
if(valor != 0.0)
cout << "Elemento fora da parte "
<< "triangular inferior\n";
}
else
cout << "Erro: indices invalidos\n";
}
62 / 99
Matriz Triangular Superior
▶ Questões importantes:
1. Quantos elementos armazenar?
2. Representação linear: como armazenar os elementos?
3. Como acessar/modificar um elemento?
63 / 99
Matriz Simétrica
▶ Definição:
aij = aji , ∀ i, j
▶ Exemplo:
a11 a12 a13 . . . a1n
a12 a22 a23 . . . a2n
A = a13 a23 a33 . . . a3n
.. ..
. .
a1n a2n a3n . . . ann
64 / 99
Matriz Anti-Simétrica
▶ Definição:
aij = −aji , ∀ i, j
▶ Exemplo:
0 a12 a13 . . . a1n
a12 0 a23 . . . a2n
A = a13 a23 0 . . . a3n
.. ..
. .
a1n a2n a3n . . . 0
65 / 99
Matriz Tridiagonal
dia
go
nal
pr
inc
ipa dia
l go
na
ls
up
er
ior
dia
go
na
l in
fer
ior
n n-1 n-1
66 / 99
Exercı́cios
67 / 99
Matrizes Esparsas
68 / 99
Vetor e Matriz Esparsa
69 / 99
Vetor Esparso
70 / 99
Vetor Esparso
Representação com dois vetores
C F
-5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8
2 1 3 0 0 6 9 0 12 -5 0 0 0 -3
índices -5 -4 -3 1 0 3 4 8
valores 2 1 3 9 6 12 -5 -3
folga
71 / 99
Vetor Esparso
Representação com vetor de duplas
C F
-5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8
2 1 3 0 0 6 9 0 12 -5 0 0 0 -3
Dupla
etor de -5 -4 -3 1 0 3 4 8
ind = 3
duplas 2 1 3 9 6 12 -5 -3 val = 12
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
folga
72 / 99
TAD Vetor Esparso
▶ Desenvolver o TAD VetorEsparso e o seu MI para um
vetor esparso de elementos reais, cujos ı́ndices podem
variar de C até F.
▶ Os limites C e F devem ser definidos em tempo de execução
para que o construtor aloque memória de forma
apropriada;
▶ O número inicial de elementos não-zeros também deve ser
fornecido para o construtor;
▶ Representar o vetor esparso original sem os seus
elementos nulos usando um vetor de duplas.
▶ Definição da dupla:
typedef struct
{
int ind;
float val;
} Dupla;
73 / 99
TAD Vetor Esparso
class VetorEsparso
{
private:
int c, f;
int max; // capacidade maxima do vetor tab
int nnz; // numero de nao-zeros incluidas
Dupla *tab; // vetor de registros
int detInd(int i);
public:
VetorEsparso(int cc, int ff, int naozeros);
∼VetorEsparso();
float get(int i);
void set(int i, float valor);
};
74 / 99
TAD Vetor Esparso
Construtor e Destrutor
VetorEsparso::∼VetorEsparso()
{
delete [] tab;
}
75 / 99
TAD Vetor Esparso
int VetorEsparso::detInd(int i)
{
if(i >= c && i <= f) // verifica validade
{
for(int t = 0; t < nnz; t++)
{
// determina indice k no vetor tab
if(tab[t].ind == i) return t;
}
// elemento nao esta representado
return -1;
}
else
{
cout << "Indice invalido!" << endl;
exit(1);
}
}
76 / 99
TAD Vetor Esparso
float VetorEsparso::get(int i)
{
int k = detInd(i);
if(k != -1) return tab[k].val;
else return 0;
}
78 / 99
TAD Vetor Esparso
Observações
79 / 99
TAD Vetor Esparso 2
80 / 99
TAD Vetor Esparso 2
class VetorEsparso2
{
private:
int c, f; // indices: comeco e fim
int max; // capacidade maxima do vetor
int nnz; // numero de elementos nao-zero
Dupla *tab; // vetor de registros
public:
VetorEsparso2(int cc, int ff, int naozeros);
∼VetorEsparso2();
float get(int i);
void set(int i, float valor);
};
81 / 99
TAD Vetor Esparso 2
Construtor e Destrutor
VetorEsparso2::VetorEsparso2(int cc, int ff, int
naozeros)
{
c = cc;
f = ff;
max = naozeros + 10; // num nao-zeros + folga
nnz = 0;
tab = new Dupla[max];
// inicializa o vetor com max duplas de folga
for(int i = 0; i < max; i++) {
tab[i].ind = f + 1;
tab[i].val = 0.0;
}
}
VetorEsparso2::∼VetorEsparso2()
{
delete [] tab;
} 82 / 99
TAD Vetor Esparso 2
int VetorEsparso2::detInd(int i)
{
if(i >= c && i <= f) {
for(int t = 0; t < nnz; t++)
if(tab[t].ind == i)
return t;
return -1;
} else {
cout << "Indice invalido!" << endl; exit(1); }
}
float VetorEsparso2::get(int i)
{
int k = detInd(i);
if(k != -1)
return tab[k].val;
else
return 0;
}
83 / 99
TAD Vetor Esparso 2
84 / 99
TAD Vetor Esparso 2
85 / 99
TAD Vetor Esparso 2
void VetorEsparso2::remove(int k)
{
int t;
86 / 99
TAD Vetor Esparso 2
void VetorEsparso2::insere(int i, float valor)
{
if(nnz < max) {
int t = 0;
// inserir o indice na ordem correta
while(t < nnz tab[t].ind < i)
t++;
for(int m = nnz; m > t; m--) {
// desloca p/ direita ate t, p/ abrir espaco
tab[m].ind = tab[m-1].ind;
tab[m].val = tab[m-1].val;
}
// insere dupla na posicao t
tab[t].ind = i;
tab[t].val = valor;
nnz++;
}
else
cout << "Nao ha espaco!" << endl;
} 87 / 99
Matrizes Esparsas
88 / 99
Matriz Esparsa
Vetor de Triplas
2 1 3 0 0 0 0
0 4 6 0 0 0 0
-5 0 9 0 0 0 0
-8 0 0 3 0 0 0
Tripla
0 0 0 0 2 0 0
lin = 3
0 0 0 0 0 8 0 col = 0
0 0 0 0 0 0 7 val =-8
Vetor de lin = 0 lin = 0 lin = 0 lin = 1 lin = 1 lin = 2 lin = 2 lin = 3 lin = 3 lin = 4 lin = 5 lin = 6
col = 0 col = 1 col = 2 col = 1 col = 2 col = 0 col = 2 col = 0 col = 3 col = 4 col = 5 col = 6
triplas val = 2 val = 1 val = 3 val = 4 val = 6 val = -5 val = 9 val = -8 val = 3 val = 2 val = 8 val = 7
89 / 99
TAD Matriz Esparsa
▶ Desenvolver o TAD MatrizEsparsa e o seu MI para uma
matriz esparsa M de elementos reais.
▶ M deve ser representada sem os seus elementos nulos;
▶ Utilizar uma folga de 10%;
▶ O ı́ndice de linha i varia de c1 até f1;
▶ O ı́ndice de coluna j varia de c2 até f2;
▶ Os limites c1,f1,c2 e f2 devem ser definidos em tempo
de execução, para que o construtor aloque memória de
forma adequada.
▶ A tripla é definida como:
typedef struct
{
int lin;
int col;
float val;
} Tripla;
90 / 99
TAD Matriz Esparsa
class MatrizEsparsa
{
private:
int c1, f1; // limites do indice de linha
int c2, f2; // limites do indice de coluna
int max; // capacidade maxima do vetor
int nnz; // numero de nao-zeros (triplas)
Tripla *tab; // vetor de registros
int detInd(int i, int j);
void remove(int k);
void insere(int i, int j, float valor);
public:
MatrizEsparsa(int i1,int i2,int j1,int j2,int n);
∼MatrizEsparsa();
float get(int i, int j);
void set(int i, int j, float valor);
};
91 / 99
TAD Matriz Esparsa
Construtor
MatrizEsparsa::MatrizEsparsa(int a1, int b1, int a2
, int b2, int n)
{
c1 = a1;
f1 = b1;
c2 = a2;
f2 = b2;
int folga = ((f1-c1+1)*(f2-c2+1)) * 0.1;
max = n + folga;
nnz = 0;
tab = new Tripla[max];
// inicializa tab com triplas de folga
for(int i = 0; i < max; i++) {
tab[i].lin = f1 + 1;
tab[i].col = f2 + 1;
tab[i].val = 0.0;
}
}
92 / 99
TAD Matriz Esparsa
Determina ı́ndice
int MatrizEsparsa::detInd(int i, int j)
{
if(i >= c1 && i <= f1 && j >= c2 && j <= f2) {
int k = -1;
for(int t = 0; t < nnz; t++) {
if(tab[t].lin == i && tab[t].col == j) {
k = t;
break;
}
}
return k;
}
else
{
cout << "Indice invalido!" << endl;
exit(1);
}
}
93 / 99
TAD Matriz Esparsa
94 / 99
TAD Matriz Esparsa
float MatrizEsparsa::get(int i, int j)
{
int k = detInd(i, j);
if(k != -1) return tab[k].val;
else return 0;
}
96 / 99
TAD Matriz Esparsa
void MatrizEsparsa::insere(int i, int j, float valor)
{
if(nnz < max) {
int t = 0;
// inserir o indice na ordem correta
while(t < nnz) {
if(tab[t].lin > i) break;
if(tab[t].lin == i && tab[t].col > j) break;
t++;
}
for(int m = nnz; m > t; m--) {
//desloca para direita ate t para abrir espaco
tab[m].lin = tab[m-1].lin;
tab[m].col = tab[m-1].col;
tab[m].val = tab[m-1].val;
}
// insere tripla na posicao t
tab[t].lin = i;
tab[t].col = j;
tab[t].val = valor;
nnz++;
}
else
cout << "Nao ha espaco!" << endl;
} 97 / 99
Matriz Esparsa
Exercı́cios
linha 0 0 0 1 1 2 2 3 3 4 5 6
coluna 0 1 2 1 2 0 2 0 3 4 5 6
valores 2 1 3 4 6 -5 9 -8 3 2 8 7
folga
98 / 99
Matriz Esparsa
Exercı́cios
99 / 99