Linha | Codigo |
001 | // Prof. Leo^nidas - http://www.matematica.br http://line.ime.usp.br |
002 | // MAC0122 - 2017/10/30 |
003 | |
004 | // Busca em largura em grafos: utilizando fila. |
005 | // Exemplo de grafo construido modo "estatico" (vide 'criaGrafo1()' e 'criaGrafo2()'. |
006 | |
007 | // Para evitar construcao ciclica, criar um vetor de nos e cada um com |
008 | // uma lista de vizinhos apontando para o inteiro do vetor. |
009 | |
010 | // $ gcc -fsanitize=address -g -o busca_em_largura busca_em_largura.c |
011 | |
012 | #include <stdio.h> |
013 | #include "../lista_ligada/fila_lista_ligada_struct.h" // estrutura para fila e funcoes para criar, inserir e remover |
014 | |
015 | #define MAXNOS 10 // numero maximo de nos do grafo |
016 | |
017 | typedef struct noV { // Lista de vizinhos |
018 | int indice; // supoe que os nos do grafo estao em um vetor |
019 | struct noV *prox; |
020 | } Lista; |
021 | |
022 | typedef struct no { // Cada no do grafo |
023 | int info; |
024 | Lista *vizinhos; |
025 | } No; |
026 | |
027 | // Globais |
028 | No *vetNosGrafo[MAXNOS]; // vetor de nos do grafo |
029 | Lista *vetProxViz[MAXNOS]; // (truque) vetor de nos do grafo com proximo vizinho do no' a ser visitado |
030 | int visitado[MAXNOS]; // auxiliar para marcar os nos visitados |
031 | int inserido[MAXNOS]; // auxiliar para marcar os nos ja inseridos alguma vez na fila |
032 | int nVG; // numero de nos do grafo |
033 | tipoRegistroFila *primeiro, *ultimo; // "../lista_ligada/fila_lista_ligada_struct.h" declara 'tipoRegistroFila' |
034 | |
035 | // Lista os vizinhos do no' de indice "i": imprime "indice" e "rotulo" de cada vizinho |
036 | void listaVizinhos (int i) { |
037 | No *no = vetNosGrafo[i]; |
038 | Lista *viz; |
039 | int ind; |
040 | if (no==NULL) { printf("Erro: nao existe o no %d\n", i); return; } |
041 | if ((viz = no->vizinhos)==NULL) { printf("<vazio>\n"); return; } |
042 | while (viz != NULL) { |
043 | ind = viz->indice; |
044 | printf("<%d: ", ind); |
045 | printf("%d > ", vetNosGrafo[ind]->info); |
046 | viz = viz->prox; |
047 | } |
048 | printf("\n"); |
049 | } |
050 | |
051 | |
052 | // Atencao, precisa de alocacao dinamica e antes de voltar para quem chamou, |
053 | // e' necessario que alguma variavel de quem chamou preserve os apontadores. |
054 | void criaGrafo1 () { // Grafo 1 (1)---(2) |
055 | nVG = 4; // num. nos do grafo | \ | |
056 | No *no1, *no2, *no3, *no4; // (3)---(4) |
057 | Lista *lista1, *lista2, *lista3, |
058 | *lista4, *listaAux; // uma lista de adjacentes para cada no |
059 | no1 = malloc(sizeof(No)); no2 = malloc(sizeof(No)); |
060 | no3 = malloc(sizeof(No)); no4 = malloc(sizeof(No)); |
061 | no1->info = 1; no2->info = 2; no3->info = 3; no4->info = 4; |
062 | vetNosGrafo[0] = no1; // No 1 : tem como vizinhos 2, 3, 4 - neste ponto preserva-se os end alocados |
063 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 1; // no 2 |
064 | lista1 = listaAux; |
065 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 2; // no 3 |
066 | lista1->prox = listaAux; |
067 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 3; // no 4 |
068 | listaAux->prox = NULL; |
069 | lista1->prox->prox = listaAux; vetProxViz[0] = lista1; |
070 | no1->vizinhos = lista1; |
071 | vetNosGrafo[1] = no2; // No 2 : tem como vizinhos 1, 4 |
072 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 0; // no 1 |
073 | lista2 = listaAux; |
074 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 3; // no 4 |
075 | listaAux->prox = NULL; |
076 | lista2->prox = listaAux; vetProxViz[1] = lista2; |
077 | no2->vizinhos = lista2; |
078 | vetNosGrafo[2] = no3; // No 3 : tem como vizinhos 1, 4 |
079 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 0; // no 1 |
080 | lista3 = listaAux; |
081 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 3; // no 4 |
082 | listaAux->prox = NULL; |
083 | lista3->prox = listaAux; vetProxViz[2] = lista3; |
084 | no3->vizinhos = lista3; |
085 | vetNosGrafo[3] = no4; // No 4 : tem como vizinhos 1, 2, 3 |
086 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 0; // no 1 |
087 | lista4 = listaAux; |
088 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 1; // no 2 |
089 | lista4->prox = listaAux; |
090 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 2; // no 3 |
091 | listaAux->prox = NULL; |
092 | lista4->prox->prox = listaAux; vetProxViz[3] = lista4; |
093 | no4->vizinhos = lista4; |
094 | } |
095 | |
096 | void criaGrafo2 () { // Grafo 2 (1)---(2) |
097 | nVG = 4; // num. nos do grafo | \ (nao terminar em '\') |
098 | No *no1, *no2, *no3, *no4; // (3)---(4) |
099 | Lista *lista1, *lista2, *lista3, |
100 | *lista4, *listaAux; // uma lista de adjacentes para cada no |
101 | no1 = malloc(sizeof(No)); no2 = malloc(sizeof(No)); |
102 | no3 = malloc(sizeof(No)); no4 = malloc(sizeof(No)); |
103 | no1->info = 1; no2->info = 2; no3->info = 3; no4->info = 4; |
104 | vetNosGrafo[0] = no1; // No 1 : tem como vizinhos 2 |
105 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 1; // no 2 |
106 | listaAux->prox = NULL; |
107 | lista1 = listaAux; vetProxViz[0] = lista1; |
108 | no1->vizinhos = lista1; |
109 | vetNosGrafo[1] = no2; // No 2 : tem como vizinhos 1, 3, 4 |
110 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 0; // no 1 |
111 | lista2 = listaAux; |
112 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 2; // no 3 |
113 | lista2->prox = listaAux; |
114 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 3; // no 4 |
115 | listaAux->prox = NULL; |
116 | lista2->prox->prox = listaAux; vetProxViz[1] = lista2; |
117 | no2->vizinhos = lista2; |
118 | vetNosGrafo[2] = no3; // No 3 : tem como vizinhos 2, 4 |
119 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 1; // no 2 |
120 | lista3 = listaAux; |
121 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 3; // no 4 |
122 | listaAux->prox = NULL; |
123 | lista3->prox = listaAux; vetProxViz[2] = lista3; |
124 | no3->vizinhos = lista3; |
125 | vetNosGrafo[3] = no4; // No 4 : tem como vizinhos 2, 3 |
126 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 1; // no 2 |
127 | lista4 = listaAux; |
128 | listaAux = malloc(sizeof(Lista)); listaAux->indice = 2; // no 3 |
129 | listaAux->prox = NULL; |
130 | lista4->prox = listaAux; vetProxViz[3] = lista4; |
131 | no4->vizinhos = lista4; |
132 | } |
133 | |
134 | void iniciaVisitados (int n) { // inicia cada no' como NAO visitado e NAO inserido na fila |
135 | int i; |
136 | for (i=0; i<n; i++) { |
137 | visitado[i] = 0; // marque como NAO visitado |
138 | inserido[i] = 0; // marque como NAO inserido |
139 | } |
140 | } |
141 | |
142 | void visite (int i) { // Visite o no' |
143 | printf("<%d: ", i); |
144 | if (vetNosGrafo[i]==NULL) { printf("x > - erro! 'visite(%d)'!\n", i); return ; } //S seguranca |
145 | printf("%d > ", vetNosGrafo[i]->info); |
146 | visitado[i] = 1; // marque como visitado |
147 | } |
148 | |
149 | int temVizinho (No *item) { // Verifica se o no' tem algum vizinho |
150 | if (item==NULL) { printf("Erro! 'temVizinho(NULL)'!\n"); return 0; } //S seguranca |
151 | return item->vizinhos!=NULL; // se nao NULL => tem filhos |
152 | } |
153 | |
154 | // Truque para pegar iterativa (a cada chamada) os vizinhos de um no' |
155 | int proximoVizinho (int indice) { // devolva proximo vizinho de vetNosGrafo[indice] |
156 | Lista *viz = vetProxViz[indice]; // pegue atual vizinho do no de indice dado |
157 | if (viz==NULL) { //D printf("<sem vizinhos>"); |
158 | return -1; // este no NAO tem vizinhos! |
159 | } |
160 | vetProxViz[indice] = viz->prox; // avance para o seguinte |
161 | return viz->indice; // devolva indice do ultimo |
162 | } |
163 | |
164 | // Algoritmo de busca em largura. |
165 | // Utiliza uma fila para inserir vizinhos de cada no' visitado. |
166 | // Usa vetor de "bits" (visitado[], inserido[]) para marcar visitados e inseridos. |
167 | void buscaEmLargura (int vg) { // recebe primeiro elemento da fila |
168 | No *aux, *no = vetNosGrafo[0]; |
169 | tipoRegistroFila *item; |
170 | int ind, aux_ind, conta = 0; |
171 | item = criarRegFila(0, "no"); // define item->ind = conta |
172 | iniciaVisitados(vg); |
173 | inserirFila(&primeiro, &ultimo, item); inserido[0] = 1; // marque como inserido |
174 | while (filaNaoVazia(primeiro)) { // ../lista_ligada/fila_lista_ligada_struct.h: filaNaoVazia(...) |
175 | //D printf("Indices na fila: "); imprimirFilaToda(primeiro); |
176 | item = removerFila(&primeiro, &ultimo); |
177 | ind = item->ind; |
178 | //D printf("\n-------------\nbuscaEmLargura: conta=%d, item->ind=%d\n", conta, ind); |
179 | if (visitado[ind]==0) { // verifica se item ainda nao foi visitado |
180 | visite(ind); printf(" : "); |
181 | //D printf(" vizinhos de item->ind=%d (vetProxViz[%d]->indice=%d): ", ind, ind, vetProxViz[ind]->indice); |
182 | while ((aux_ind = proximoVizinho(ind))>=0) { |
183 | if (inserido[aux_ind]!=1) { // insere apenas se NAO foi inserido antes |
184 | item = criarRegFila(aux_ind, "no"); conta++; |
185 | inserirFila(&primeiro, &ultimo, item); inserido[aux_ind] = 1; // marque como inserido |
186 | //D printf("(v=0, item->ind=%d) ", item->ind); |
187 | printf(" <%d, %d> ", item->ind, vetNosGrafo[aux_ind]->info); |
188 | } |
189 | else printf("[%d, %d] ", aux_ind, vetNosGrafo[aux_ind]->info); // ja inserido |
190 | } |
191 | } |
192 | //D else printf(" %d ja foi visitado *****\n", ind); |
193 | printf("\n"); |
194 | } // while (filaNaoVazia(primeiro)) |
195 | } // void buscaEmLargura (int vg) |
196 | |
197 | |
198 | int main (void) { |
199 | int i; |
200 | printf("Simulando operacoes: nos\n"); |
201 | criaGrafo2(); // nVG = 4 |
202 | for (i=0; i<nVG; i++) { // inserir os 5 item |
203 | printf("%d: ", vetNosGrafo[i]->info); |
204 | listaVizinhos(i); |
205 | } |
206 | buscaEmLargura(nVG); |
207 | printf("\n"); |
208 | |
209 | return 0; |
210 | } |