|
| 1 | +/* |
| 2 | + Autor: Gustavo Michels de Camargo |
| 3 | +
|
| 4 | + Projeto: Algoritmo estrural de um Grafo |
| 5 | +
|
| 6 | +
|
| 7 | +*/ |
| 8 | + |
| 9 | + |
| 10 | +use std::{collections::HashMap}; |
| 11 | + |
| 12 | +// Matriz de Vector usada ara construir o Grafo. |
| 13 | +type MatrizGrafo = Vec<Vec<isize>>; |
| 14 | + |
| 15 | + |
| 16 | + |
| 17 | +// O dicionario serve para podermos dar entrada a qualquer String e ter como abstrair suas posições dentro. |
| 18 | +// da matriz numerica, isso serve apenas para fins de uso, não requerer transcrever um Nodo com X para valor numerico. |
| 19 | +#[derive(PartialEq, Eq, Clone, Debug)] |
| 20 | +struct Grafo { |
| 21 | + matriz: MatrizGrafo, |
| 22 | + dicionario: HashMap<String, usize>, |
| 23 | + bicondicional: bool |
| 24 | +} |
| 25 | + |
| 26 | +trait Projeto { |
| 27 | + // Geral |
| 28 | + fn new(tamanho: usize, tipo: &str) -> Grafo; |
| 29 | + |
| 30 | + // Funcçoes envolvendo o dicionario - Usuario |
| 31 | + fn usr_pegar_indice(&self, chave: String) -> usize; |
| 32 | + fn usr_pegar_chave(&self, indice: usize) -> String; |
| 33 | + |
| 34 | + // Usuario |
| 35 | + fn usr_adicionar_conexao(&mut self, a: String, b: String, valor: isize); |
| 36 | + fn usr_remover_conexao(&mut self, a: String, b: String); |
| 37 | + fn usr_numero_conexoes(&self, no: String) -> usize; |
| 38 | + fn usr_verificar_se_existe_conexao(&self, a: String, b: String) -> bool; |
| 39 | + fn usr_conexoes(&self, a: String) -> Vec<String>; |
| 40 | + |
| 41 | + // Maquina / uso para os Algoritmos |
| 42 | + fn adicionar_conexao(&mut self, a: usize, b: usize, valor: isize); |
| 43 | + fn remover_conexao(&mut self, a: usize, b: usize); |
| 44 | + fn numero_conexoes(&self, no: usize) -> usize; |
| 45 | + fn verificar_se_existe_conexao(&self, a: usize, b: usize) -> bool; |
| 46 | + fn conexoes(&self, a: usize) -> Vec<usize>; |
| 47 | + |
| 48 | + // Algoritmos que atuam sobre Grafos |
| 49 | +} |
| 50 | + |
| 51 | + |
| 52 | +// Este é a implementação da "Classe" de um grafo. |
| 53 | +impl Projeto for Grafo { |
| 54 | + // Tamanho: Numero Maximo de Vertices que a matriz ppode usar de 0 até tamanho. |
| 55 | + // Em notação matematica relativa a limites: [0, tamanho). |
| 56 | + // Toda função que começa com 'usr_'(usr = usuario) é a versão da função que deve ser usada para interagir diretamente com o usuario. |
| 57 | + // As funções de mesmo nome mas sem 'usr_' deve ser usada apenas dentro dos algoritmos, como o Dijkstra para menor caminho entre dois nos. |
| 58 | + // Fiz assim para otimizar processamento e descartar necessidade de acessar e |
| 59 | + // consultaro dicionario o tempo todo quando se apenas como Objetivo encontrar um menor caminho com Dijkstra por exemplo. |
| 60 | + |
| 61 | + // Apenas essa função foge a regra por ser universal |
| 62 | + fn new(tamanho: usize, tipo: &str) -> Grafo { |
| 63 | + Grafo { |
| 64 | + matriz: vec![vec![-1; tamanho]; tamanho], |
| 65 | + dicionario: HashMap::new(), |
| 66 | + bicondicional: match tipo { |
| 67 | + "->" => false, // Condicional |
| 68 | + "<->" | _ => true // Bicondicional |
| 69 | + } |
| 70 | + } |
| 71 | + } |
| 72 | + |
| 73 | + // ---- Funções para uso direto do usuario ---- |
| 74 | + |
| 75 | + // Retorna o indice da matriz relacionada a chave |
| 76 | + fn usr_pegar_indice(&self, chave: String) -> usize { |
| 77 | + if self.dicionario.contains_key(&chave) { |
| 78 | + return (&self.dicionario.get(&chave)).unwrap().clone(); |
| 79 | + } |
| 80 | + |
| 81 | + return 0; |
| 82 | + } |
| 83 | + |
| 84 | + // Retorna a chave do dicionario relacionada ao valor do indice da matriz do grafo |
| 85 | + fn usr_pegar_chave(&self, indice: usize) -> String { |
| 86 | + for (key, value) in self.dicionario.iter() { |
| 87 | + if *value == indice { |
| 88 | + return (*key).clone(); |
| 89 | + } |
| 90 | + } |
| 91 | + |
| 92 | + return "".to_string(); |
| 93 | + } |
| 94 | + |
| 95 | + // Conecta Dois vertices |
| 96 | + fn usr_adicionar_conexao(&mut self, a: String, b: String, valor: isize) { |
| 97 | + if !self.dicionario.contains_key(&a){ |
| 98 | + let num: usize = self.dicionario.len(); |
| 99 | + self.dicionario.insert(a.to_owned(), num); |
| 100 | + } |
| 101 | + |
| 102 | + if !self.dicionario.contains_key(&b){ |
| 103 | + let num: usize = self.dicionario.len(); |
| 104 | + self.dicionario.insert(b.to_owned(), num); |
| 105 | + } |
| 106 | + |
| 107 | + let (valor_a, valor_b): (usize, usize) = (self.usr_pegar_indice(a), self.usr_pegar_indice(b)); |
| 108 | + |
| 109 | + self.matriz[valor_a][valor_b] = valor; |
| 110 | + |
| 111 | + if self.bicondicional { |
| 112 | + self.matriz[valor_b][valor_a] = valor; |
| 113 | + } |
| 114 | + |
| 115 | + } |
| 116 | + |
| 117 | + fn usr_remover_conexao(&mut self, a: String, b: String) { |
| 118 | + let (valor_a, valor_b): (usize, usize) = (self.usr_pegar_indice(a), self.usr_pegar_indice(b)); |
| 119 | + |
| 120 | + self.matriz[valor_a][valor_b] = -1; |
| 121 | + self.matriz[valor_b][valor_a] = -1; |
| 122 | + } |
| 123 | + |
| 124 | + // Retorba o numero de vertices na qual ele se conecta |
| 125 | + fn usr_numero_conexoes(&self, no: String) -> usize { |
| 126 | + self.matriz[self.usr_pegar_indice(no)].iter() |
| 127 | + .filter(|x| **x >= 0) |
| 128 | + .collect::<Vec<&isize>>() |
| 129 | + .len() as usize | 0 |
| 130 | + } |
| 131 | + |
| 132 | + // Verifica se dois nos estão conectados |
| 133 | + fn usr_verificar_se_existe_conexao(&self, a: String, b: String) -> bool { |
| 134 | + self.matriz[self.usr_pegar_indice(a)][self.usr_pegar_indice(b)] >= 0 |
| 135 | + } |
| 136 | + |
| 137 | + |
| 138 | + fn usr_conexoes(&self, a: String) -> Vec<String> { |
| 139 | + let mut result: Vec<String> = Vec::new(); |
| 140 | + let a_value: usize = self.usr_pegar_indice(a); |
| 141 | + |
| 142 | + for i in 0..self.matriz[a_value].len() { |
| 143 | + if a_value != i && self.matriz[a_value][i] > -1 { |
| 144 | + result.push(self.usr_pegar_chave(i)); |
| 145 | + } |
| 146 | + } |
| 147 | + |
| 148 | + return result; |
| 149 | + } |
| 150 | + |
| 151 | + |
| 152 | + |
| 153 | + // ---- Funções para uso direto dos algoritmos (tem melhor perfomance) ---- |
| 154 | + |
| 155 | + |
| 156 | + // Retorna um array dos indice de todos os nos na qual o no 'a' se conecta |
| 157 | + // Esera usar esta função apenas para usos proprios dentro do Grafo, como em algoritmos tipo dijkstra |
| 158 | + // Conecta Dois vertices |
| 159 | + fn adicionar_conexao(&mut self, a: usize, b: usize, valor: isize) { |
| 160 | + self.matriz[a][b] = valor; |
| 161 | + |
| 162 | + if self.bicondicional { |
| 163 | + self.matriz[b][a] = valor; |
| 164 | + } |
| 165 | + } |
| 166 | + |
| 167 | + fn remover_conexao(&mut self, a: usize, b: usize) { |
| 168 | + self.matriz[a][b] = -1; |
| 169 | + self.matriz[b][a] = -1; |
| 170 | + } |
| 171 | + |
| 172 | + // Retorba o numero de vertices na qual ele se conecta |
| 173 | + fn numero_conexoes(&self, no: usize) -> usize { |
| 174 | + self.matriz[no].iter() |
| 175 | + .filter(|x| **x >= 0) |
| 176 | + .collect::<Vec<&isize>>() |
| 177 | + .len() as usize | 0 |
| 178 | + } |
| 179 | + |
| 180 | + fn verificar_se_existe_conexao(&self, a: usize, b: usize) -> bool { |
| 181 | + self.matriz[a][b] >= 0 |
| 182 | + } |
| 183 | + |
| 184 | + fn conexoes(&self, a: usize) -> Vec<usize> { |
| 185 | + let mut result: Vec<usize> = Vec::new(); |
| 186 | + |
| 187 | + for i in 0..self.matriz[a].len() { |
| 188 | + if a != i && self.matriz[a][i] > -1 { |
| 189 | + result.push(i); |
| 190 | + } |
| 191 | + } |
| 192 | + return result; |
| 193 | + } |
| 194 | + |
| 195 | + |
| 196 | + // ---- Funções dos algoritmos ---- |
| 197 | + |
| 198 | + |
| 199 | +} |
| 200 | + |
| 201 | + |
| 202 | +// Main |
| 203 | +fn main() { |
| 204 | + // Grafo com no maximo mil vertices |
| 205 | + // "->" = Grafo condicional, "<->" = Grafo Bicondicional |
| 206 | + let mut grafo: Grafo = Grafo::new(1000, "->"); |
| 207 | + |
| 208 | + grafo.usr_adicionar_conexao(0.to_string(), 1.to_string(), 1); |
| 209 | + grafo.usr_adicionar_conexao(1.to_string(), 2.to_string(), 1); |
| 210 | + grafo.usr_adicionar_conexao(2.to_string(), 3.to_string(), 1); |
| 211 | + grafo.usr_adicionar_conexao(3.to_string(), 0.to_string(), 1); |
| 212 | + |
| 213 | + println!("{:?}", grafo.conexoes(2)); |
| 214 | +} |
| 215 | + |
| 216 | + |
| 217 | +#[cfg(test)] |
| 218 | +mod test { |
| 219 | + use super::*; |
| 220 | + |
| 221 | + #[test] |
| 222 | + fn usr_numero_conexoes() { |
| 223 | + let mut grafo: Grafo = Grafo::new(1000, "->"); |
| 224 | + |
| 225 | + for i in 1..1000 { |
| 226 | + grafo.usr_adicionar_conexao(0.to_string(), i.to_string(), 1); |
| 227 | + } |
| 228 | + |
| 229 | + assert_eq!(grafo.usr_numero_conexoes(0.to_string()), 999); |
| 230 | + assert_eq!(grafo.usr_numero_conexoes(0.to_string()), grafo.numero_conexoes(0)); |
| 231 | + } |
| 232 | + |
| 233 | + #[test] |
| 234 | + fn numero_conexoes() { |
| 235 | + let mut grafo: Grafo = Grafo::new(1000, "<->"); |
| 236 | + |
| 237 | + for i in 1..1000 { |
| 238 | + grafo.adicionar_conexao(0, i, 1); |
| 239 | + } |
| 240 | + |
| 241 | + assert_eq!(grafo.numero_conexoes(0), 999); |
| 242 | + assert_eq!(grafo.numero_conexoes(0), grafo.usr_numero_conexoes(0.to_string())); |
| 243 | + } |
| 244 | +} |
0 commit comments