Graphe.ml
De wiki-prog
Implantation des graphes en "semi-dynamique": la liste des sommets est un vecteur et par conséquent les listes d'adjacence contiennent les numéros des sommets. Attention, les tableaux OCaml commecant à 0, on numérote les sommets de 0 à (ordre - 1).
Le programme charge un fichier "graphe.ex" dont le format est le suivant:
- La première ligne contient l'ordre du graphe;
- les lignes suivantes contiennent la description de la matrice d'adjacence où les entiers sont séparés par ':'.
- Chaque ligne (sauf la première) doit se terminer par ':' suivit d'un retour à la ligne.
Le fichier suivant correspond au graphe G1 du td.
9 0:1:1:0:0:0:1:0:0: 0:0:0:1:0:0:0:0:0: 0:0:0:0:0:1:0:0:1: 0:0:0:0:0:0:1:0:0: 0:0:0:1:0:0:0:0:0: 0:0:1:0:0:0:1:0:1: 0:0:0:1:1:0:0:0:0: 0:0:0:0:0:1:1:0:1: 0:0:0:0:0:0:0:0:0:
Le reste du code est commenté et correspond au TD d'algo sur les graphes.
(* graphe.ml *) (* Les sommets *) type sommets = { mutable succ : (int * float) list; mutable pred : (int * float) list; } let sommet_vide () = { succ = []; pred = []; } (* 1-graphe oriente value*) type graphe = { ordre : int; sommets: sommets array; } (* Creation d'un graphe depuis la matrice d'adjacence * * et de la matrice celle de cout. Meme si la matrice * * d'adjancence represente un p-graphe, on ne * * construit que des 1-graphes *) let from_matrix ordre adj cost = let g = { ordre = ordre; sommets = Array.init ordre (fun _ -> sommet_vide ()); } in for i = 0 to (ordre - 1) do for j = 0 to (ordre - 1) do if (adj.(i).(j) <> 0) then begin (* Ajout du successeur *) g.sommets.(i).succ <- (j, cost.(i).(j))::g.sommets.(i).succ; (* Ajout du predecesseur *) g.sommets.(j).pred <- (i, cost.(i).(j))::g.sommets.(j).pred; end done done; g (* Parcours en largeur et construction du vecteur de pere. * * Attention les tableaux commencent à 0, par consequent les * * sommets sont aussi numerotes de 0 à (ordre-1). Les racines * * sont marquees par -1 et les sommets non visites par -42 *) let largeur g s = (* initialisation du vecteur de pere *) let pere = Array.make g.ordre (-42) in (* La fonction recursive *) let larg_rec s = begin (* marquage du pere *) pere.(s) <- -1; (* Creation de la file *) let q = Queue.create () in Queue.add s q; (* boucle principale *) while not (Queue.is_empty q) do let s = Queue.take q in List.iter (fun (pa,_) -> if pere.(pa) = -42 then begin pere.(pa) <- s; Queue.add pa q; end ) g.sommets.(s).succ done end in begin larg_rec s; for i = 0 to (g.ordre - 1) do if pere.(i) = -42 then larg_rec i done; pere end let make_matrix_from_stream s = (* recupere la premiere ligne qui doit coder un entier *) let rec get_ordre s = let c = Stream.next s in if (c = '\n') then "" else (String.make 1 c)^(get_ordre s) in let rec get_num s = let c = Stream.next s in if (c = ':') then "" else (String.make 1 c)^(get_num s) in let ordre = int_of_string (get_ordre s) in let adj = Array.make_matrix ordre ordre 0 in for i = 0 to (ordre - 1) do for j = 0 to (ordre -1) do adj.(i).(j) <- int_of_string (get_num s) done; ignore(Stream.next s) done; (ordre,adj) (* Affiche le graphe (uniquement les successeurs) *) let print_graphe g = let rec print_ladj = function [] -> Printf.printf "X" | (nb,c)::t -> Printf.printf "%i -> " nb; print_ladj t in Array.iteri (fun s adj -> Printf.printf "%i : " s; print_ladj adj.succ; Printf.printf "\n"; ) g.sommets let main () = let s = Stream.of_channel (open_in "graphe.ex") in let (ordre,adj) = make_matrix_from_stream s in let g = from_matrix ordre adj (Array.make_matrix ordre ordre 0.) in let pere = largeur g 7 in print_graphe g; Printf.printf "\n"; Array.iteri (fun s p -> Printf.printf "%i <- %i\n" s p) pere; exit 0 let _ = main ()