Baixe o app para aproveitar ainda mais
Prévia do material em texto
DCC013 Estruturas de Dados Matrizes Em Computação, as matrizes são representadas por meio de estruturas de dados conhecidas como vetores ou arrays, onde cada posição/valor pode ser referenciada por um ou mais índices (dependendo da quantidade de dimensões da matriz); Exemplos (pseudolinguagem, pascal e C++): Matrizes 2 tipo Mat = vet[1..3, 1..4] real; Mat: A; var A = array [1..3, 1..4] of real; typedef float Mat[3][4]; Mat A; Enquanto na Matemática uma matriz possui sempre duas dimensões, na Computação chama- se qualquer vetor de matriz, podendo possuir uma ou mais dimensões: Matrizes unidimensionais; Matrizes bidimensionais; Matrizes n-dimensionais. Matrizes 3 Quanto de memória ocupa uma matriz 5000 x 5000 de reais? Um valor real (float) ocupa 4 bytes; Uma matriz 5000 x 5000 de reais (float) ocupa, aproximadamente, 100 MB. E se somente alguns poucos elementos dessa matriz fossem diferentes de zero? Seria possível reduzir a sua representação de forma que ela passasse a ocupar menos espaço de memória? Matrizes 4 Como representar de forma compactada: Matrizes Diagonais; Matrizes Triangulares; Matrizes Esparsas; Etc... Matrizes 5 Matriz Unidimensional ou Vetor (TAD Vetor) Seja o TAD TVetor de n elementos reais, representado na classe em C++ a seguir: Matrizes 6 class TVetor { private://dominio: int n; //tamanho do vetor float *vet;//array que armazena n floats //operacoes: bool Verifica(int indice); public: TVetor(int tam); float Consulta(int indice); void Atribui(int indice, float valor); ~TVetor(); }; Função privada: só pode ser chamada por operações (métodos) declarados dentro do TAD (classe). Matriz Unidimensional – Aplicação 1: Desenvolver o MI do TAD TVetor anterior para um vetor de reais, atendendo: O tamanho do vetor deve ser definido no PA, em tempo de execução. Assim, o construtor deve alocar memória de acordo com o tamanho especificado pelo seu parâmetro tam; Verificar a validade do índice; Em seguida, desenvolver um PA através de uma função main() para testar o TAD TVetor (e seu MI), usando um vetor de 60 elementos reais. Matrizes 7 Matriz Unidimensional – Aplicação 1: MI do TAD TVetor: Construtor e Destrutor: Matrizes 8 TVetor::~TVetor() {//desaloca a memoria alocada no construtor delete [] vet; } TVetor::TVetor(int tam) {//inicializa a variavel interna n e aloca memoria //para o vetor vet n = tam; vet = new float[n]; } Matriz Unidimensional – Aplicação 1: MI do TAD TVetor: Operador Verifica: A função privada Verifica() analisa a validade do indice do vetor vet. O indice pode assumir um valor entre 0 e n–1 (padrão C/C++): Matrizes 9 bool TVetor::Verifica(int indice) {//verifica validade de indice if(indice >= 0 && indice < n) return true; else return false; //indice invalido }; Matriz Unidimensional – Aplicação 1: MI do TAD TVetor: Operação Consulta: Matrizes 10 float TVetor::Consulta(int indice) { // verifica validade de indice if (Verifica(indice)) return vet[indice]; else cout<<“Indice invalido - Consulta"<<endl; exit(1); // finaliza o programa } Matriz Unidimensional – Aplicação 1: MI do TAD TVetor: Operação Atribui: Matrizes 11 void TVetor::Atribui(int indice, float valor) { //verifica validade de indice if (Verifica(indice)) //armazena valor na posicao indice de vet vet[indice] = valor; else cout<<“Indice invalido - Atribuicao"<<endl; } Matriz Unidimensional – Aplicação 1: PA suportado pelo TAD TVetor (gravado no arquivo Vetor.h) e usando um vetor de 60 elementos reais: Matrizes 12 #include <iostream> #include “Vetor.h” using namespace std; int main(){ int tam = 60; Tvetor* v = new TVetor(tam); //aloca vet[60] for(int i=0; i<tam; i++) //armazena sequencia v->Atribui(i,i+1); //de 1 a 60 for(int i=0; i<tam; i++){ float val = v->Consulta(i); cout<<val<<endl;} delete v; return 0;} Matriz Unidimensional – Exercício 1: Sabendo que na linguagem C/C++, o índice de um vetor de tamanho n é um valor inteiro entre 0 e n-1, pede-se: Desenvolver um TAD para viabilizar vetores cujos índices podem assumir seus valores em intervalos inteiros e quaisquer. Por exemplo: -10 .. 45. Desenvolver o MI do TAD anterior. Desenvolver um PA (função main()) para testar o TAD anterior, criando um vetor de 60 elementos reais numerados de –29 (limite inferior) a 30 (limite superior). Matrizes 13 Matriz Unidimensional – Exercício 1: Observações: Os valores limites (inferior e superior) do intervalo do índice devem ser definidos no PA, em tempo de execução. Assim, o construtor deve alocar memória dinamicamente para o vetor, de acordo com a definição desses limites. Verificar a validade do índice, quando necessário; Matrizes 14 Matriz Unidimensional – Exercício 1: Uma solução poderia ser o TAD TVetFlex abaixo: Matrizes 15 class TVetFlex { private: int n; //tamanho ou comprimento do vetor float *vet;//array que armazena n floats int c, f //c: limite inferior do indice de vet //f: limite superior do indice de vet int DetInd(int indice); //operador privado public: TVetFlex(int cc, int ff); float Consulta(int indice); void Atribui(int indice, float valor); ~TVetFlex(); }; Matriz Unidimensional – Exercício 1: MI do TAD TVetFlex: Construtor e Destrutor: Matrizes 16 TVetFlex::TVetFlex(int cc, int ff) { c = cc; //inicializa os atributos da classe f = ff; n = f - c + 1; //calcula o comprimento de vet vet = new float[n]; } TVetFlex::~TVetFlex() {//desaloca a memoria alocada no construtor delete [] vet; } Matriz Unidimensional – Exercício 1: MI do TAD TVetFlex: Operação DetInd: Matrizes 17 A operação privada DetInd() verifica a validade do indice de vet, isto é, se c ≤ indice ≤ f. Se indice for válido, DetInd() retorna o valor do índice de acordo com o padrão C/C++, isto é, o valor correspondente a indice dentro do intervalo de 0 a n–1. Se indice for inválido, DetInd() retorna -1. Matriz Unidimensional – Exercício 1: MI do TAD TVetFlex: Operação DetInd(): Matrizes 18 int TVetFlex::DetInd(int indice) {//verifica validade de indice if(indice >= c && indice <= f) return (indice – c); else return -1; //indice invalido }; Por que a operação DetInd() foi criada como privada? Matriz Unidimensional – Exercício 1: MI do TAD TVetFlex: Operação Consulta(): Matrizes 19 float TVetFlex::Consulta(int indice) { int i = DetInd(indice); if(i != -1) // verifica validade de indice return vet[i]; else cout<<“Indice invalido – Consulta”<<endl; exit(1); // finaliza o programa } Matriz Unidimensional – Exercício 1: MI do TAD TVetFlex: Operação Atribui(): Matrizes 20 void TVetFlex::Atribui(int indice, float valor) { int i = DetInd(indice); if(i != -1) // verifica validade de indice vet[i] = valor; else cout<<“Indice invalido – Atribuicao”<<endl; } Matriz Unidimensional – Exercício 1: Matrizes 21 #include<iostream> #include “VetorFlex.h” using namespace std; int main() { int cc = -29, ff = 30; TVetFlex* v = new TVetFlex(cc,ff); for(int i = cc; i <= ff; i++) { //sequencia numerica no intervalo 1..60 float val = i-cc + 1; v->Atribui(i,val); } //Continua PA para testar o TAD TVetFlex (arquivado em VetorFlex.h), criando um vetor de 60 elementos reais com índices numerados de –29 a 30: Matrizes 22 //Continuação for(int i = cc; i <= ff; i++) { float val = v->Consulta(i); cout<<val<<endl; } delete v; return 0; } Matriz Unidimensional – Exercício 1: PA para testar o TAD TVetFlex (arquivado em VetorFlex.h), criando um vetor de 60 elementos reais com índices numerados de –29 a 30: Matrizes com mais de uma Dimensão As principais operações são de atribuição e consulta; O projeto do TAD-MATRIZ é idêntico ao do TAD- VETOR, devendo-se utilizar tantos índices quantas forem as dimensões da matriz considerada; Matrizes 23 Matrizes com mais de uma Dimensão - TAD Assim, uma classe para o TAD-MATRIZ de 2 dimensões poderia ser: Matrizes 24 class TMatriz2D { private://dominio: int nl, nc; //numero de linhas e de colunas //array bidimensional com nl*nc floats float **mat; //operacoes: bool Verifica(int i, int j); public: TMatriz2D(int nnl, int nnc); float Consulta(int i, int j); void Atribui(int i, int j, float valor); ~TMatriz2D(); }; // necessita de ponteiro duplo. A matriz mat pode ser vista como um vetor de vetores, isto é, cada linha é um vetor Matrizes com mais de uma Dimensão - Aplicações 2. Desenvolver o MI do TAD TMatriz2D anterior. 3. Desenvolver um PA suportado pelo TAD TMatriz2D para: a) Ler 25 valores reais e gerar uma matriz 5x5, linha por linha. b) Imprimir a 4ª coluna da matriz. c) Ler índice de linha, índice de coluna e um valor real e alterar a posição correspondente da matriz. d) Determinar e imprimir a transposta da matriz. e) Determinar o maior valor da diagonal secundária da matriz. Matrizes 25 Matrizes com mais de uma dimensão – Aplicação 2 MI do TAD-MATRIZ2D: Construtor e destrutor: Matrizes 26 TMatriz2D::~TMatriz2D() {//desaloca a memoria alocada no construtor for(int i = 0; i < nl; i++) delete [] mat[i]; delete [] mat; } TMatriz2D::TMatriz2D(int nnl, int nnc) { nl = nnl; nc = nnc; mat = new float*[nl]; //aloca vetor com nl ponteiros for(int i = 0; i < nl; i++) mat[i] = new float[nc];//cada ponteiro aponta para //um vetor de nc floats } A função privada Verifica() analisa a validade dos índices i e j. O índice i pode assumir valor entre 0 e nl–1 e o j entre 0 e nc-1 (padrão C/C++). Matrizes 27 bool TMatriz2D::Verifica(int i, int j) {//verifica validade dos indices if(i >= 0 && i < nl && j >= 0 && j < nc) return true; else return false; //indice invalido }; Matrizes com mais de uma dimensão – Aplicação 2 MI do TAD-MATRIZ2D: Operador Verifica: Matrizes 28 float TMatriz2D::Consulta(int i, int j) { // verifica validade dos indices if (Verifica(i, j)) return mat[i][j]; else cout<<“Indice invalido – Consulta”<<endl; exit(1); // finaliza o programa } Matrizes com mais de uma dimensão – Aplicação 2 MI do TAD-MATRIZ2D: Operador Consulta: Matrizes 29 void TMatriz2D::Atribui(int i, int j, float valor) { //verifica validade dos indices if (Verifica(i, j)) mat[i][j] = valor;//armazena Valor na posição i,j else cout<<“Indice invalido – Atribuicao”<<endl; } Matrizes com mais de uma dimensão – Aplicação 2 MI do TAD-MATRIZ2D: Operador Atribui: Representação Linear de Matrizes Seja a representação natural da matriz A(3x4) de inteiros O armazenamento da matriz A na memória é feito em posições consecutivas a partir de um endereço base b. Matrizes 30 6381 4023 7695 A Representação Linear de Matrizes Considerando que: o índice de linha (L) de A varia de 0 a 2 o índice de coluna (C) varia de 0 a 3 a matriz A seja percorrida linha por linha para o seu armazenamento na memória Uma visão das posições de memória ocupadas por A poderia ser: Matrizes 31 Endereços . . . b b+1 b+2 b+3 b+4 b+5 b+6 b+7 b+8 b+9 b+10 b+11 . . . Valor . . . 5 9 6 7 -3 2 0 4 1 8 3 -6 . . . C 0 1 2 3 0 1 2 3 0 1 2 3 L 0 0 0 0 1 1 1 1 2 2 2 2 Representação Linear de Matrizes Desta forma, a matriz bidimensional A(3x4) é representada linearmente por um vetor V do tipo: array [b..b+11] de inteiros Isto é, V é a representação linear de A. Para acessar um elemento de A em V, é necessário relacionar o índice I de V com os índices L e C de A: Matrizes 32 Representação Linear de Matrizes Matrizes 33 L C I 0 0 b+0 b + C + 0 b + C + 4*L 0 1 b+1 0 2 b+2 0 3 b+3 1 0 b+4 b + C + 4 1 1 b+5 1 2 b+6 1 3 b+7 2 0 b+8 b + C + 8 2 1 b+9 2 2 b+10 2 3 b+11 Representação Linear de Matrizes Assim, dados: o vetor V (representação linear da matriz A) um par de índices válidos L e C de A Para obter o valor do elemento A[L, C], deve-se acessar V[I], sendo: Matrizes 34 LCbI *4 Notar que a matriz A não está armazenada na memória, isto é, somente a sua representação linear V está armazenada e o que se deseja é consultar o valor de A[L, C] a partir de V. Representação Linear de Matrizes Genericamente, seja A [L, C] de elementos do tipo-t (qualquer), tal que: L = c1 .. f1 C = c2 .. f2 A matriz A possui um total de: linhas: m = f1 – c1 + 1 colunas: n = f2 – c2 + 1 elementos: t = m * n Matrizes 35 Representação Linear de Matrizes A representação linear de A é um vetor V cujos elementos são do tipo-t e os índices variam no intervalo b..(b + t – 1). O índice I de V correspondente a [L, C] de A é dado por: Como em C/C++, o índice do primeiro elemento em qualquer dimensão de array é 0, então b = 0, c1 = 0 e c2 = 0. Logo, em C/C++: Matrizes 36 12 * cLncCbI LnCI * Representação Linear de Matrizes – Aplicação 4 Desenvolver o TAD TMat2D e seu MI para uma matriz mn de elementos reais. Obs: A representação interna da matriz deve ser linear. O número de linhas m e o de colunas n devem ser definidos em tempo de execução. Assim, o construtor deve alocar memória de acordo com o tamanho da matriz especificado pelos parâmetros m e n; Verificar a validade dos índices; Desenvolver um PA para testar o TAD TMat2D, que usa uma matriz 711 de elementos reais. Matrizes 37 Representação Linear de Matrizes – Aplicação 4 O TAD pode ser assim definido: Matrizes 38 class TMat2D { private: float *vet;//vetor de tamanho n*m int m, n; //quantidade de linhas e de coluna int DetInd(int linha, int coluna); public: TMat2D(int mm, int nn); void Atribui(int linha, int coluna, float valor); float Consulta(int linha, int coluna); ~TMat2D(); }; Representação Linear de Matrizes – Aplicação 4 O TAD pode ser assim definido: Matrizes 39 Função privada. Só pode ser chamada por métodos declarados dentro da classe classTMat2D { private: float *vet;//vetor de tamanho n*m int m, n; //quantidade de linhas e de coluna int DetInd(int linha, int coluna); public: TMat2D(int mm, int nn); void Atribui(int linha, int coluna, float valor); float Consulta(int linha, int coluna); ~TMat2D(); }; Representação Linear de Matrizes – Aplicação 4 MI do TAD TMat2D: Construtor e destrutor: Matrizes 40 TMat2D::~TMat2D() {//desaloca a memoria alocada no construtor delete [] vet; } TMat2D::TMat2D(int mm, int nn) {//inicializa as variaveis internas e aloca memoria //para o vetor vet (representacao linear da matriz) m = mm; n = nn; vet = new float[m*n]; } Representação Linear de Matrizes – Aplicação 4 MI do TAD TMat2D: Operador DetInd: A função privada DetInd converte os índices linha e coluna da matriz no índice k do vetor vet. Além disso, verifica validade de linha e coluna. Todos os índices (linha, coluna e k) variam a partir de 0 (padrão C/C++): Matrizes 41 int TMat2D::DetInd(int linha, int coluna) {//verifica intervalo da linha e da coluna if(linha>=0 && linha<m && coluna>=0 && coluna < n) return coluna + n*linha; else return -1; //indice invalido }; Representação Linear de Matrizes – Aplicação 4 MI do TAD TMat2D: Operador Consulta: Matrizes 42 float TMat2D::Consulta(int linha, int coluna) { //determina o índice k de vet dados linha e coluna int k = DetInd(linha, coluna); if(k != -1) return vet[k]; //retorna o k-ésimo valor de vet else cout<<“Indice invalido – Consulta”<<endl; exit(1); // finaliza o programa } Representação Linear de Matrizes – Aplicação 4 MI do TAD TMat2D: Operador Atribui: Matrizes 43 void TMat2D::Atribui(int linha, int coluna, float valor) { //determina o índice k de vet dados linha e coluna int k = DetInd(linha, coluna); if(k != -1) // verifica validade dos indices vet[k] = valor;//armazena valor na posição k de vet else cout<<“Indice invalido – Atribuicao”<<endl; } Representação Linear de Matrizes – Aplicação 4 PA suportado pelo TAD TMat2D e criando uma matriz mat 711 Matrizes 44 #include <iostream> #include “Mat2D.h” using namespace std; int main(){ int m = 7, n = 11; TMat2D *mat = new TMat2D(m,n); //aloca vet(mxn) for(int i=0; i<m; i++) for(int j=0; j<n; j++){ //sequencia numerica no intervalo 0..(m*n-1) float val = j + n*i; mat->Atribui(i,j,val);} //Continua Matrizes 45 //Continuacao for(int i=0; i<m; i++){ for(int j=0; j<n; j++){ float val = mat->Consulta(i,j); cout<<val<<"\t"; } cout<<endl; } delete mat; return 0;} Representação Linear de Matrizes – Aplicação 4 PA suportado pelo TAD TMat2D e criando uma matriz mat 711 Representação Linear de Matrizes – Aplicação 5 Desenvolver o TAD TMat2DFlex e o seu MI para uma matriz mn de elementos reais. Obs: A representação interna da matriz deve ser linear; Os limites dos intervalos dos índices de linha e de coluna devem ser arbitrários e definidos em tempo de execução. Assim, o construtor deve alocar memória de acordo com esses limites; Verificar a validade dos índices, quando necessário; Desenvolver um PA suportado pelo TAD TMat2DFlex, que crie uma matriz de elementos reais com os intervalos de linha = -2..7 e de coluna = 0..5. Matrizes 46 Representação Linear de Matrizes – Aplicação 5 TAD TMat2DFlex: Matrizes 47 class TMat2DFlex { private: float *vet;//representação linear da matriz M(nxm) int m, n; //quantidades de linhas e de colunas int c1, c2, f1, f2; //c1: limite inicial da linha //c2: limite inicial da coluna //f1: limite final da linha //f2: limite final da coluna int DetInd(int linha, int coluna); public: TMat2DFlex(int cc1, int ff1, int cc2, int ff2); float Consulta(int linha, int coluna); void Atribui(int linha, int coluna, float valor); ~TMat2DFlex(); }; Representação Linear de Matrizes – Aplicação 5 MI do TAD TMat2DFlex: Construtor e destrutor: Matrizes 48 TMat2DFlex::~TMat2DFlex() {//desaloca a memoria alocada no construtor delete [] vet; } TMat2DFlex::TMat2DFlex(int cc1, int ff1, int cc2, int ff2) { c1 = cc1; //inicializa os campos da classe 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]; } Representação Linear de Matrizes – Aplicação 5 MI do TAD TMat2DFlex: Operador DetInd: A função privada DetInd converte os índices linha e coluna da matriz no índice k do vetor vet. Além disso, verifica validade de linha e coluna. Matrizes 49 int TMat2DFlex::DetInd(int linha, int coluna) { if(linha>=c1 && linha<=f1 && coluna>=c2 && coluna<=f2) return (coluna - c2) + n*(linha - c1); else return -1; //índice invalido }; Representação Linear de Matrizes – Aplicação 5 MI do TAD TMat2DFlex: Operações Consulta: Matrizes 50 float TMat2DFlex::Consulta(int linha, int coluna) { //determina o índice k de vet dados linha e coluna int k = DetInd(linha, coluna); if(k != -1) return vet[k]; //retorna o k-ésimo valor de vet else cout<<“Indice invalido – Consulta”<<endl; exit(1); // finaliza o programa } Representação Linear de Matrizes – Aplicação 5 MI do TAD TMat2DFlex: Operador Atribui: Matrizes 51 void TMat2DFlex::Atribui(int linha, int coluna, float valor) { //determina o índice k de vet dados linha e coluna int k = DetInd(linha, coluna); if(k != -1) // verifica validade dos indices vet[k] = valor;//armazena valor na posição k de vet else cout<<“Indice invalido – Atribuicao”<<endl; } Representação Linear de Matrizes – Aplicação 5 PA apoiado no TAD TMat2DFlex, que cria uma matriz mat com intervalos L=-2..7 e C=0..5. Matrizes 52 #include <iostream> #include “Mat2DFlex.h” using namespace std; int main(){ int c1 = -2, f1 = 7, c2 = 0, f2 = 5; //aloca a representação linear de mat(n,m) TMat2DFlex *mat = new TMat2DFlex(c1,f1,c2,f2); //atribui valores a matriz mat for(int i=c1; i<=f1; i++) for(int j=c2; j<=f2; j++){ float val = (f2-c2+1)*(i-c1) + j - c2;//0..(n*m-1) mat->Atribui(i,j,val);} //Continua Matrizes 53 //Continua for(int i=c1; i<=f1; i++){//imprime a matriz mat for(int j=c2; j<=f2; j++){ float val = mat->Consulta(i,j); cout<<val<<"\t"; } cout<<endl; } delete mat; return 0; } Representação Linear de Matrizes – Aplicação 5 PA apoiado no TAD TMat2DFlex, que cria uma matriz mat com intervalos L=-2..7 e C=0..5.
Compartilhar