public CArco(CVertice destino, int peso) { this.nDestino = destino; this.peso = peso; this.grosor_flecha = 2; this.color = Color.Black; this.Cfuente = Color.Black; }
bool[] visitados; // variable para comprobar los nodos ya visitados #endregion Fields #region Constructors public Form1() { InitializeComponent(); nuevoNodo = null; var_control = 0; ventanaVertice = new Vertice(); ventanaArco = new Arco(); ventanaRecorrido = new Recorrido(); Duracion = new Stopwatch(); miGrafo = new NuevoGrafo(); nuevoArco = new AgregarArcos(); loading = false; opening = false; tiempo = 100; recorrido = ""; VentanaGuardar = new SaveFileDialog(); VentanaCargar = new OpenFileDialog(); this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true); }
// Crea la arista a partir de los nodos de origen y de destino public bool AgregarArco(CVertice origen, CVertice nDestino) { if (DiGrafo) { if (origen.ListaAdyacencia.Find(v => v.nDestino == nDestino) == null) { origen.ListaAdyacencia.Add(new CArco(nDestino)); return true; } return false; } else { if ((origen.ListaAdyacencia.Find(v => v.nDestino == nDestino) == null) && (nDestino.ListaAdyacencia.Find(v => v.nDestino == origen) == null)) { origen.ListaAdyacencia.Add(new CArco(nDestino)); nDestino.ListaAdyacencia.Add(new CArco(origen)); return true; } return false; } }
private void rbnBAgregarArista_Click(object sender, EventArgs e) { List<string> miLista = new List<string>(); //Se crea una lista de tipo string foreach(CVertice cv in grafo.nodos) { miLista.Add(cv.Valor.ToString()); //Se agregan los valores de los vertices } nuevoArco.Refresh(miLista); //Se actualizan los datos en la ventanan Nuevo arco nuevoArco.ShowDialog(); //Se muestra la ventana nuevo Arco if (nuevoArco.control) //Si todo fue bien { NodoOrigen = grafo.BuscarVertice(nuevoArco.cmbNodoInicial.Text); //Nodo origen es igual al seleccionado NodoDestino = grafo.BuscarVertice(nuevoArco.cmbNodoFinal.Text); //Nodo destino es igual al seleccionado if (grafo.AgregarArco(NodoOrigen, NodoDestino)) //Se procede a crear la arista { int distancia = int.Parse(nuevoArco.txtValor.Text); //Se guarda el peso de la arista NodoOrigen.ListaAdyacencia.Find(v => v.nDestino == NodoDestino).peso = distancia; //Se busca la arista recien creada y se le asigna el peso anterior if (!EsDigrafo) //Si no es digrafo NodoDestino.ListaAdyacencia.Find(v => v.nDestino == NodoOrigen).peso = distancia; //Se asigna el peso a ambos lados HabilitarControles(); //Se habilitan los controles comunes } } NodoOrigen = null; //NodoOrigen se setea con null NodoDestino = null; //NodoDestino se setea con null pbCanvas.Refresh(); //Se refresca el Canvas }
//Métodos public CArco(CVertice destino) : this(destino, 1) { this.nDestino = destino; }
//Metodo para resaltar nodos del grafo public void Colorear(CVertice nodo) { nodo.Color = Color.AliceBlue; nodo.FontColor = Color.Black; }
//Agrega un nodo a la lista de nodos del grafo public void AgregarVertice(CVertice nuevonodo) { nodos.Add(nuevonodo); }
//Funcion para re-dibujar los arcos que llegan a un nodo public void DibujarEntrantes(CVertice nDestino) { foreach (CVertice nodo in nodos) { foreach (CArco a in nodo.ListaAdyacencia) { if (nodo.ListaAdyacencia != null && nodo != nDestino) { if (a.nDestino == nDestino) { a.color = Color.Black; a.grosor_flecha = 2; break; } } } } }
private void pbCanvas_MouseDown(object sender, MouseEventArgs e) { if (e.Button == System.Windows.Forms.MouseButtons.Left) // Si se ha presionado el botón // izquierdo del mouse { if ((NodoOrigen = grafo.DetectarPunto(e.Location)) != null) { var_control = 1; // recordemos que es usado para indicar el estado en la pizarra: // 0 -> sin accion, 1 -> Dibujando arco, 2 -> Nuevo vértice } if (nuevoNodo != null && NodoOrigen == null) //Si hay un nodo origen pero no hay nuevonodo { ventanaVertice.Visible = false; //Se marca la propiedad Visible de la venta Vertica como false ventanaVertice.control = false; //La variable de control se inicializa con false grafo.AgregarVertice(nuevoNodo); //Se agrega un nuevo nodo al grafo btnDelNode.Enabled = true; //Se habilita el boton eliminar nodo rbnBAgregarArista.Enabled = true; //Se haabilita el boton agregar arista numeronodos = grafo.nodos.Count;//cuenta cuantos nodos hay en el grafo ventanaVertice.ShowDialog(); //Se muestra la ventana nuevo nodo if (ventanaVertice.control) //Si todo fue bien { if (grafo.BuscarVertice(ventanaVertice.txtVertice.Text) == null) //Si un nodo con el mismo valor no existe en el grafo { nuevoNodo.Valor = ventanaVertice.txtVertice.Text; //Se agrega el nuevo valor nuevo nodo } else //sino Error { MessageBox.Show("El Nodo " + ventanaVertice.txtVertice.Text + " ya existe en el grafo ", "Error nuevo Nodo", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); grafo.ELiminarNodo(""); } } else //Si no fue bien { grafo.ELiminarNodo(ventanaArco.txtArco.Text); //Se elimina el nodo recien creado grafo.RestablecerGrafo(pbCanvas.CreateGraphics()); //Se reestablece el grafo pbCanvas.Refresh(); //Se refresca el canvas } var_control = 0; //variable de control con valor 0 nuevoNodo = null; //nuevoNodo se setea con null this.Cursor = Cursors.Default; //Se cambia el cursor al default pbCanvas.Refresh(); //Se refresca el canvas } } if (e.Button == System.Windows.Forms.MouseButtons.Right) // Si se ha presionado el botón // derecho del mouse { if (var_control == 0) //Si la variable de control es 0 { if ((NodoOrigen = grafo.DetectarPunto(e.Location)) != null) { CMSCrearVertice.Text = "Nodo " + NodoOrigen.Valor; } else pbCanvas.ContextMenuStrip = this.CMSCrearVertice; //Se abre el menu strip cmscrear vertice } } }
private void pbCanvas_MouseUp(object sender, MouseEventArgs e) { switch (var_control) { case 1: // Dibujando arco this.Cursor = Cursors.Cross; //Se cambia el cursos a una cruz ventanaArco.Visible = false; //Se actualiza el dato Visible ventanaArco.control = false; //Se setea la variable de control por defecto false if ((NodoDestino = grafo.DetectarPunto(e.Location)) != null && NodoOrigen != NodoDestino) //Si el nodoDestino esta donde se encuentra el mouse y el nodo origen es distinto del nodo destino { ventanaArco.ShowDialog(); //Se muestra la ventana para crear un nuevo arco if (ventanaArco.control) //Si todo fue bien { if (grafo.AgregarArco(NodoOrigen, NodoDestino)) //Se procede a crear la arista { int distancia = int.Parse(ventanaArco.txtArco.Text); //Se guarda el peso de la arista NodoOrigen.ListaAdyacencia.Find(v => v.nDestino == NodoDestino).peso = distancia; //Se busca la arista recien creada y se le aisigna el peso anterior if (!EsDigrafo) //Si no es digrafo NodoDestino.ListaAdyacencia.Find(v => v.nDestino == NodoOrigen).peso = distancia; //Se asigna el peso a ambos lados HabilitarControles(); //Se habilitan los controles comunes } } } var_control = 0; //Origen set = 0 NodoOrigen = null; //NodoORigen se setea con null NodoDestino = null; //NodoDestino se setea con nodo null pbCanvas.Refresh(); //Se refresca el canvas break; } }
private void mostrarArreglo(CVertice i) { int m = int.MaxValue; limpiar(arreglo, arreglo2); Point xy = new Point(14, 64); Point xy2 = new Point(14, 94); Label[] ArregloNodos = new Label[numeronodos]; Label[] ArregloDistnacias = new Label[numeronodos]; for (int j = 0; j < numeronodos; j++) { Label label = new Label(); Label label2 = new Label(); label.Text = grafo.nodos[j].Valor; ArregloNodos[j] = label; if (grafo.nodos[j].distancianodo == m || grafo.nodos[j].distancianodo == int.MaxValue) { label2.Text = "inf"; } else { label2.Text = grafo.nodos[j].distancianodo.ToString(); } ArregloDistnacias[j] = label2; } foreach (Label l in ArregloNodos) { if (l != null) { l.Width = 30; l.Height = 30; l.BackColor = Color.White; l.ForeColor = Color.Black; l.TextAlign = ContentAlignment.MiddleCenter; l.Location = xy; l.BorderStyle = BorderStyle.FixedSingle; PnSimulador.Controls.Add(l); xy += new Size(30, 0); } } foreach (Label l in ArregloDistnacias) { if (l != null) { l.Width = 30; l.Height = 30; l.BackColor = Color.White; l.ForeColor = Color.Black; l.TextAlign = ContentAlignment.MiddleCenter; l.Location = xy2; l.BorderStyle = BorderStyle.FixedSingle; PnSimulador.Controls.Add(l); xy2 += new Size(30, 0); } } PnSimulador.Refresh(); arreglo = ArregloNodos; arreglo2 = ArregloDistnacias; }
private void RecorridoAnchura(CVertice nodo) { rbnRestaurar.Enabled = true; opc = 1; LblSimu.Text = "Simulacion: Recorrido en Anchura"; label2.Text = "COLA:"; label1.Text = "RECORRIDO:"; CVertice temp = new CVertice(); nodo.Visitado = true; nodo.Padre = null; Queue<CVertice> cola = new Queue<CVertice>(); cola.Enqueue(nodo); grafo.Colorear(nodo); pbCanvas.Refresh(); mostrarCola(cola); Thread.Sleep(tiempo); recorrido += nodo.Valor + " "; lbRecorrido.Text = recorrido; while (cola.Count != 0) { temp = cola.Dequeue(); foreach (CArco arco in temp.ListaAdyacencia) { if (arco.nDestino.Visitado == false) { cola.Enqueue(arco.nDestino); } } mostrarCola(cola); foreach (CArco arco in temp.ListaAdyacencia) { if (arco.nDestino.Visitado == false) { recorrido += arco.nDestino.Valor + " "; lbRecorrido.Text = recorrido; arco.nDestino.Visitado = true; arco.nDestino.Padre = temp; grafo.Colorear(arco.nDestino); pbCanvas.Refresh(); Thread.Sleep(tiempo); } } } }
// Algortimo de dijkstra private void dijkstra(CVertice inicio) { if (inicio.ListaAdyacencia.Count != 0) { rbnRestaurar.Enabled = true; opc = 3; LblSimu.Text = "Simulacion: Algortimo de Dijkstra"; label2.Text = "Arreglo de distancias:"; int n = grafo.nodos.Count; arreglo = new Label[numeronodos]; arreglo2 = new Label[numeronodos]; foreach (CVertice nodo in grafo.nodos) { foreach (CArco a in nodo.ListaAdyacencia) { if (nodo == inicio) { a.nDestino.distancianodo = a.peso; a.nDestino.pesoasignado = true; a.color = Color.LimeGreen; a.grosor_flecha = 4; } else if (nodo != inicio && a.nDestino.pesoasignado == false) { a.nDestino.distancianodo = Int32.MaxValue; } } } inicio.distancianodo = 0; inicio.Visitado = true; grafo.Colorear(inicio); pbCanvas.Refresh(); mostrarArreglo(inicio); Thread.Sleep(tiempo); while (grafo.nododistanciaminima() != null) { CVertice nododismin = grafo.nododistanciaminima(); nododismin.Visitado = true; grafo.Colorear(nododismin); pbCanvas.Refresh(); foreach (CArco arco in nododismin.ListaAdyacencia) { if (arco.nDestino.distancianodo > nododismin.distancianodo + arco.peso) { if (arco.nDestino.pesoasignado) { grafo.DibujarEntrantes(arco.nDestino); } arco.nDestino.distancianodo = nododismin.distancianodo + arco.peso; arco.nDestino.pesoasignado = true; arco.color = Color.LimeGreen; arco.grosor_flecha = 4; } } mostrarArreglo(inicio); Thread.Sleep(tiempo); } } else { rbnRestaurar.Enabled = true; MessageBox.Show("El nodo que ha elegino no tiene nodos adyacentes" , "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
private void btnNewNode_Click(object sender, EventArgs e) { this.Cursor = Cursors.Cross; nuevoNodo = new CVertice(); var_control = 2; // recordemos que es usado para indicar el estado en la pizarra: 0 -> // sin accion, 1 -> Dibujando arco, 2 -> Nuevo vértice }
//devuelva el árbol final private int[,] AlgPrim(int[,] Matriz, bool[] marcados, CVertice vertice, int[,] Final) { marcados[grafo.nodos.IndexOf(vertice)] = true;//marcamos el primer nodo grafo.Colorear(vertice); pbCanvas.Refresh(); Thread.Sleep(tiempo); int aux = -1; if (!TodosMarcados(marcados)) { //Mientras que no todos estén marcados for (int i = 0; i < marcados.GetLength(0); i++) { //Recorremos sólo las filas de los nodos marcados if (marcados[i]) { for (int j = 0; j < Matriz.GetLength(0); j++) { if (Matriz[i, j] != -1) { //Si la arista existe if (!marcados[j]) { //Si el nodo no ha sido marcado antes if (aux == -1) { //Esto sólo se hace una vez aux = Matriz[i, j]; } else { aux = Math.Min(aux, Matriz[i, j]); //Encontramos la arista mínima } } } } } } //Aquí buscamos el nodo correspondiente a esa arista mínima (aux) for (int i = 0; i < marcados.GetLength(0); i++) { if (marcados[i]) { for (int j = 0; j < Matriz.GetLength(0); j++) { if (Matriz[i, j] == aux) { if (!marcados[j]) { //Si no ha sido marcado antes Final[i, j] = aux; //Se llena la matriz final con el valor Final[j, i] = aux;//Se llena la matriz final con el valor grafo.ColoArista(grafo.nodos[i].Valor, grafo.nodos[j].Valor); grafo.ColoArista(grafo.nodos[j].Valor, grafo.nodos[i].Valor); return AlgPrim(Matriz, marcados, grafo.nodos[j], Final); //se llama de nuevo al método con //el nodo a marcar } } } } } pbCanvas.Refresh(); Thread.Sleep(tiempo); } return Final; }
private int[,] AlgPrim(CVertice nodoInicial, int[,] Matriz) { //Llega la matriz a la que le vamos a aplicar el algoritmo bool[] marcados = new bool[grafo.nodos.Count]; //Creamos un vector booleano, para saber cuales están marcados return AlgPrim(Matriz, marcados, nodoInicial, new int[Matriz.GetLength(0), Matriz.GetLength(0)]); //Llamamos al método recursivo mandándole }
private void RecorridoProfundidad(CVertice nodo) { rbnRestaurar.Enabled = true; opc = 2; LblSimu.Text = "Simulacion: Recorrido en Profundidad"; label2.Text = "Pila:"; label1.Text = "RECORRIDO:"; CVertice temp = new CVertice(); Stack<CVertice> pila = new Stack<CVertice>(); pila.Push(nodo); mostrarPila(pila); while (pila.Count != 0) { mostrarPila(pila); temp = pila.Pop(); if (temp.Visitado == false) { recorrido += temp.Valor + " "; lbRecorrido.Text = recorrido; temp.Visitado = true; grafo.Colorear(temp); pbCanvas.Refresh(); Thread.Sleep(tiempo); foreach (CArco arco in temp.ListaAdyacencia) { pila.Push(arco.nDestino); } } } }