Qué es un ARBOL.??
Altas
Consultas
Bajas
Modificar
Bonus
| VOLVER | |
Archivo | |
Base de Dato | |
Listas | |
Matriz y Vector |
.. ahora si crees que los árboles solo sirven de inodoro para perros y estas de acuerdo con la Caperucita, que afirma que el Lobo la tiene chica...!!!, te puedo demostrar que ..
.. pero si lo anterior te huele mal, solo necesitas..
ARBOL BINARIO
Un árbol binario es un conjunto de elementos que esta vacio o dividido en tres subconjuntos separados.
El primer subconjunto contiene un elemento único llamado la raíz. Los otros dos subconjuntos son por si mismo arboles binarios y se les llama subárboles izquierdo y subárboles derecho.
Cada elemento se denomina nodo. Un Arbol se representa así:
A / \ B C / \ D E / \ F G Si A es raíz de un árbol binario y B es la raíz del subárbol izquierdo o derecho, se dice que A es el padre de B B es el hijo izquierdo de A, C será el hijo derecho de A. Un nodo que no tiene hijos se denomina hoja ej: B, D, F, G de la figura.
El nodo n1 es un ancestro de del nodo n2 (y n2 es descendiente de n1) si n1 es el padre de n2 o el padre de algún ancestro de n2.
Por ejemplo A es un ancestro de F y G es descendiente de C. Dos nodos se dicen hermanos si son los hijos derecho e izquierdo del mismo padre.
Si cada nodo que no es una hoja tiene subárboles izquierdo y derecho que no están vacíos, se llama árbol estrictamente binario.
Un árbol estrictamente binario de n hojas siempre tienen 2n-1 nodos.
El nivel de un árbol se define de la siguiente forma, el nivel de la raíz de un árbol es 0, y el nivel de cualquier otro nodo es uno mas que el de su padre.
La profundidad de un árbol es el máximo nivel de cualquier hoja.
La potencia total de la técnica de asignación dinámica con acceso a través de apuntadores es exhibida en aquellas aplicaciones en las cuales la estructura del árbol mismo varia, es decir crece y/o se contrae durante la ejecución del programa.
RECORRER: el árbol que consta en visitar todos los nodos del árbol. Existen tres ordenamientos principales que surgen en forma natural de las estructuras de los árboles.
Al igual que la estructura de árbol, se expresan en forma recursiva.
1. Preorden : R, A, B (visitar el nodo raíz antes que los subárboles) 2. En orden : A, R, B 3. Postorden :A, B, R (visitar los subárboles antes de la raíz) | R / \ A B
Los árboles binarios se usan para representar un conjunto de datos cuyos elementos se recuperan a través de una llave única.
Si un árbol se organiza en tal forma que para cada nodo Ti todas las llaves en el subárbol izquierdo de Ti sean menores que la llave Ti, y las llaves del subárbol derechos sean mayores que la llave Ti, entonces ese árbol se llama árbol de búsqueda.
Para comenzar es necesario que registres las declaraciones de las estructuras de tus datos
type UnRegistro=record CampoNombre,CampoEmail:string; end; NodoPino=^NodoDeArbol; NodoDeArbol=record CampoNombre,CampoEmail:string; RamaIzquierda,RamaDerecha: NodoPino; end; ////////////////////////////////////// // PROCEDIMIENTOS SIN PARAMETRO ////////////////////////////////////// PROCEDURE NoHayDatos; PROCEDURE ActivoPanelAltas; PROCEDURE ActivoPanelABM; PROCEDURE LimpioLosBoxes; PROCEDURE DesabilitoBoxDatos; ////////////////////////////////////// // PROCEDIMIENTOS CON PARAMETROS ////////////////////////////////////// procedure HagoPelotaElNodo(var DatoBuscado:string;var UnNuevoNodo:NodoPino); procedure delete(DatoBuscado:string;var UnNuevoNodo:NodoPino); procedure LeoDatosDeBoxes(var FichaLeida:UnRegistro); procedure BuscoDatoDeNodo(var DatoBuscado:string;var UnNuevoNodo:NodoPino); procedure ModificoDatoDeNodo(var DatoBuscado:string;var UnNuevoNodo:NodoPino); procedure LimpioGrillaDatos(UnNuevoNodo:NodoPino; var Fila:integer); procedure CargoComboConCampoNombre(UnNuevoNodo:NodoPino); procedure CargoNodoConDatosFicha(var FichaLeida:UnRegistro; var UnNuevoNodo:NodoPino); PROCEDURE InOrden (UnNuevoNodo:NodoPino; VAR Fila:Integer); var MiFormulario: TMiFormulario; UnNuevoNodo: NodoPino; FichaLeida: UnRegistro; implementation
Si tenes ganas de estudiar, sentate hasta que se te pase..!!!
GENERANDO NUEVOS NODOS
Los siguientes procedimientos te permiten cargar datos en los nodos del árbol, pero recuerda que no hay archivo
//////////////////////////////////////////////////////// // Delphi 5 MANEJO DE ARBOLES BINARIOS SIN ARCHIVO // Wilo Carpio 31/10/01 //////////////////////////////////////////////////////// procedure TMiFormulario.FormCreate(Sender: TObject); begin UnNuevoNodo:=nil; end; /////////////////////////////// // ALTAS DE NODOS /////////////////////////////// procedure TMiFormulario.BotonAltasClick(Sender: TObject); begin MiFormulario.Caption := 'REGISTRO DE NUEVO NODO EN EL ARBOL'; PanelAltas.caption:='Digita los datos, luego Click en Aceptar'; ActivoPanelAltas; end; procedure TMiFormulario.BotonGrabarClick(Sender: TObject); var FichaLeida:UnRegistro; DatoBuscado:string; begin if BotonGrabar.caption='&Aceptar' then begin CargoNodoConDatosFicha(FichaLeida,UnNuevoNodo); end else if BotonGrabar.caption='&Modificar' then begin ModificoDatoDeNodo(DatoBuscado,UnNuevoNodo); end else if BotonGrabar.caption='&Borrar' then begin HagoPelotaElNodo(DatoBuscado,UnNuevoNodo); end end; procedure TMiFormulario.LeoDatosDeBoxes(var FichaLeida:UnRegistro); begin FichaLeida.CampoNombre:=BoxNombre.text; FichaLeida.CampoEmail:=BoxEmail.text; end; procedure TMiFormulario.CargoNodoConDatosFicha(var FichaLeida:UnRegistro; var UnNuevoNodo:NodoPino); begin LeoDatosDeBoxes(FichaLeida); if FichaLeida.CampoNombre<>'' then // Si NO se clickeo Grabar sin dato en el box begin if UnNuevoNodo=nil then // Si es NO EXISTE un nodo, entonces se begin // se crea new(UnNuevoNodo); // Un crea un NUEVO NODO y luego se UnNuevoNodo^.CampoNombre := FichaLeida.CampoNombre; // Carga con datos de la ficha UnNuevoNodo^.CampoEmail := FichaLeida.CampoEmail; UnNuevoNodo^.RamaIzquierda:= nil; UnNuevoNodo^.RamaDerecha := nil; end else // Si YA EXISTE un nodo, entonces se begin // ORDENA como arbol binario if UnNuevoNodo^.CampoNombre > FichaLeida.CampoNombre then CargoNodoConDatosFicha(FichaLeida,UnNuevoNodo^.RamaIzquierda) else if UnNuevoNodo^.CampoNombre < FichaLeida.CampoNombre then CargoNodoConDatosFicha(FichaLeida,UnNuevoNodo^.RamaDerecha) else showmessage('Ese nombre ya existe'); end; LimpioLosBoxes; end else // Si se clickeo Grabar sin dato en el box nombre showmessage('Para grabar debes digitar un Nombre...!!!'); end; procedure TMiFormulario.LimpioLosBoxes; begin BoxNombre.text:=''; BoxEmail.text:=''; BoxNombre.SetFocus; end;
El amor como la gripe siempre terminan en la cama..!!!
VER CONTENIDO DE LOS NODOS
En este link puedes apreciar los procedimientos para recorrer el árbol
///////////////////////////////////// // VER POR GRILLA ///////////////////////////////////// procedure ActivarPanelGrilla; begin MiFormulario.Caption:='GRILLA DE DATOS GRABADOS'; MiFormulario.PanelGrilla.visible:=True; MiFormulario.PanelABM.visible:=False ; MiFormulario.MiGrilla.cells[0,0]:='NOMBRE'; MiFormulario.MiGrilla.cells[1,0]:='EMAIL'; end; procedure TMiFormulario.BotonGrillaClick(Sender: TObject); var Fila:integer; begin if UnNuevoNodo<>nil then begin ActivarPanelGrilla; Fila:=1; InOrden(UnNuevoNodo,Fila); end else NoHayDatos; end; PROCEDURE tMiFormulario.InOrden (UnNuevoNodo:NodoPino; VAR Fila:Integer); BEGIN IF UnNuevoNodo<>NIL THEN BEGIN InOrden (UnNuevoNodo^.RamaIzquierda,Fila); MiGrilla.Cells[0,Fila]:=UnNuevoNodo^.CampoNombre; MiGrilla.Cells[1,Fila]:=UnNuevoNodo^.CampoEmail; IF Fila=MiGrilla.rowcount THEN MiGrilla.rowcount:=MiGrilla.rowcount+1; Fila:=Fila+1; InOrden (UnNuevoNodo^.RamaDerecha,Fila); END; END; procedure TMiFormulario.CerrarGrillaClick(Sender: TObject); var Fila:integer; begin Fila:=1; LimpioGrillaDatos(UnNuevoNodo,Fila); ActivoPanelABM; end;
Qué cuentan las ovejas para poder dormir..!!!
ELIMINACION DE NODOS
Este link te muestra como sacar de la memoria el contenido del nodo
////////////////////////////////// // BAJAS ////////////////////////////////// procedure TMiFormulario.BotonBajaClick(Sender: TObject); begin if UnNuevoNodo<>nil then begin MiFormulario.Caption:='BORRANDO EL CONTENIDO DEL NODO'; PanelAltas.caption:='Selecciona Nombre en el combo'; ActivoPanelAltas; BotonGrabar.caption:='&Borrar'; CargoComboConCampoNombre(UnNuevoNodo); ComboNombre.visible:=true; DesabilitoBoxDatos; end else NoHayDatos; end; procedure TMiFormulario.HagoPelotaElNodo(var DatoBuscado:string;var UnNuevoNodo:NodoPino); begin if (application.MessageBox('¿Deseas hacerlo?','ESTAS POR HACER PELOTA UN NODO', mb_iconquestion+mb_YESNO+mb_defbutton2)) = idYES then begin DatoBuscado:=ComboNombre.text; delete(DatoBuscado,UnNuevoNodo); ActivoPanelABM; end; end; procedure tMiFormulario.delete(DatoBuscado:string;var UnNuevoNodo:NodoPino); var NodoActivo:NodoPino; procedure del(var NodoCopia:NodoPino); begin if NodoCopia^.RamaDerecha<>nil then del(NodoCopia^.RamaDerecha) else begin NodoActivo^.CampoNombre:=NodoCopia^.CampoNombre; NodoActivo^.CampoEmail:=NodoCopia^.CampoEmail; NodoActivo:=NodoCopia; NodoCopia:=NodoCopia^.RamaIzquierda; end; end; begin if UnNuevoNodo=nil then ShowMessage('No existe') else if DatoBuscadoUnNuevoNodo^.CampoNombre then delete(DatoBuscado,UnNuevoNodo^.RamaDerecha) else if DatoBuscado=UnNuevoNodo^.CampoNombre then begin NodoActivo:=UnNuevoNodo; if NodoActivo^.RamaDerecha=nil then UnNuevoNodo:=NodoActivo^.RamaIzquierda else if NodoActivo^.RamaIzquierda=nil then UnNuevoNodo:=NodoActivo^.RamaDerecha else del(NodoActivo^.RamaIzquierda) end; end;
Me las pagarán..!!! ( FMI )
MODIFICACIONES
Recuerda que solo puedes cambiar el contenido de los campos de datos del nodo, no así el campo llave ni los que contienen los punteros.
////////////////////////////////// // MODIFICACIONES ////////////////////////////////// procedure TMiFormulario.BotonCambiosClick(Sender: TObject); begin if UnNuevoNodo<>nil then begin MiFormulario.Caption:='MODIFICACION DEL CONTENIDO DEL NODO'; PanelAltas.caption:='Selecciona un nombre en el combo'; ActivoPanelAltas; BotonGrabar.caption:='&Modificar'; ComboNombre.visible:=true; CargoComboConCampoNombre(UnNuevoNodo); end else NoHayDatos; end; procedure TMiFormulario.ModificoDatoDeNodo(var DatoBuscado:string;var UnNuevoNodo:NodoPino); begin ComboNombre.visible:=true; DatoBuscado:=ComboNombre.text; if UnNuevoNodo <> nil then begin if UnNuevoNodo^.CampoNombre = DatoBuscado then if (application.MessageBox('¿Deseas guardarlos?','MODIFICACION DE DATOS DEL NODO', mb_iconquestion+mb_YESNO+mb_defbutton2)) = idYES then begin UnNuevoNodo^.CampoNombre:=UnNuevoNodo^.CampoNombre; UnNuevoNodo^.CampoEmail:= BoxEmail.text; end; ModificoDatoDeNodo(DatoBuscado,UnNuevoNodo^.RamaDerecha); ModificoDatoDeNodo(DatoBuscado,UnNuevoNodo^.RamaIzquierda); end; ActivoPanelABM; end;
Soy un quemo..!!! ( Nerón )
BUSCAR y VER TEORIA
Te recomiendo que en este link aprendas a usar el fantástico combo box, que te simplificará tus tareas de modificar y borrar nodos.
////////////////////////////// // BUSQUEDA ////////////////////////////// procedure TMiFormulario.BotonBuscarClick(Sender: TObject); var DatoBuscado:string; begin if UnNuevoNodo<>nil then begin MiFormulario.Caption:='BUSQUEDA DEL CONTENIDO DEL NODO'; DatoBuscado:=ComboNombre.text; BuscoDatoDeNodo(DatoBuscado,UnNuevoNodo); PanelAltas.caption:='Selecciona un nombre en el combo'; ActivoPanelAltas; DesabilitoBoxDatos; BotonGrabar.visible:=false; ComboNombre.visible:=true; CargoComboConCampoNombre(UnNuevoNodo); end else NoHayDatos; end; procedure tMiFormulario.BuscoDatoDeNodo(var DatoBuscado:string;var UnNuevoNodo:NodoPino); begin if UnNuevoNodo <> nil then begin if UnNuevoNodo^.CampoNombre = DatoBuscado then begin BoxNombre.text:=UnNuevoNodo^.CampoNombre; BoxEmail.text:=UnNuevoNodo^.CampoEmail; end; BuscoDatoDeNodo(DatoBuscado,UnNuevoNodo^.RamaIzquierda); BuscoDatoDeNodo(DatoBuscado,UnNuevoNodo^.RamaDerecha); end; end; procedure TMiFormulario.CargoComboConCampoNombre(UnNuevoNodo:NodoPino); begin IF UnNuevoNodo<>NIL THEN BEGIN CargoComboConCampoNombre (UnNuevoNodo^.RamaIzquierda); ComboNombre.items.add(UnNuevoNodo^.CampoNombre); CargoComboConCampoNombre(UnNuevoNodo^.RamaDerecha); end; end; procedure tMiFormulario.LimpioGrillaDatos(UnNuevoNodo:NodoPino; var Fila:integer); BEGIN IF UnNuevoNodo<>NIL THEN BEGIN LimpioGrillaDatos(UnNuevoNodo^.RamaIzquierda,Fila); MiGrilla.Cells[0,Fila]:=''; MiGrilla.Cells[1,Fila]:=''; IF Fila=MiGrilla.rowcount THEN MiGrilla.rowcount:=MiGrilla.rowcount+1; Fila:=Fila+1; LimpioGrillaDatos(UnNuevoNodo^.RamaDerecha,Fila); END; END; procedure TMiFormulario.BotonCerrarClick(Sender: TObject); begin if (BotonGrabar.Visible=True) and (BotonGrabar.caption='&Aceptar') and (BoxNombre.text<>'') then if (application.MessageBox('¿Deseas guardarlos?','DIGITASTE DATOS EN PANTALLA', mb_iconquestion+mb_YESNO+mb_defbutton2)) = idYES then begin LeoDatosDeBoxes(FichaLeida); if FichaLeida.CampoNombre<>'' then CargoNodoConDatosFicha(FichaLeida,UnNuevoNodo); end else begin ActivoPanelABM; end else begin ActivoPanelABM end; end; procedure TMiFormulario.ComboNombreChange(Sender: TObject); var DatoBuscado:string; begin DatoBuscado:=ComboNombre.text; BuscoDatoDeNodo(DatoBuscado,UnNuevoNodo); end; ////////////////////////////////////// // PROCEDIMIENTOS VER POR GRILLA ////////////////////////////////////// PROCEDURE TMiFormulario.NoHayDatos; BEGIN application.messagebox('Aún no ingresaste ningún dato', 'ESTRUCTURA VACIA', mb_iconexclamation+mb_OK+ mb_defbutton1); ActivoPanelABM; END; procedure TMiFormulario.ChauMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if (application.MessageBox('¿Deseas Salir del Programa?','ESTAS POR CERRAR ESTE SISTEMA', mb_iconquestion+mb_YESNO+mb_defbutton2)) = idYES then begin close(); end; end; ////////////////////////////////////// // PROCEDIMIENTOS ACTIVAR PANELES ////////////////////////////////////// PROCEDURE TMiFormulario.ActivoPanelABM; BEGIN MiFormulario.Caption:='PROGRAMA MODELO DELPHI: Arbol sin archivo Wilo Carpio'; PanelABM.visible:=True ; PanelGrilla.visible:=False ; PanelTeoria.visible:=False ; PanelAltas.visible:=False; BoxNombre.enabled:=true; BoxEmail.enabled:=true; ComboNombre.text:=''; END; PROCEDURE TMiFormulario.DesabilitoBoxDatos; BEGIN BoxNombre.enabled:=false; BoxEmail.enabled:=false; END; PROCEDURE TMiFormulario.ActivoPanelAltas; BEGIN PanelABM.visible:=False ; PanelGrilla.visible:=False ; PanelTeoria.visible:=False ; PanelAltas.visible:=True; BoxNombre.enabled:=true; BoxEmail.enabled:=true; ComboNombre.Items.Clear; ComboNombre.text:=''; LimpioLosBoxes; ComboNombre.visible:=false; BotonGrabar.caption:='&Aceptar'; BotonGrabar.visible:=true; END; procedure TMiFormulario.BotonTeoriaClick(Sender: TObject); begin PanelTeoria.visible:=True; PanelABM.visible:=False; Autor.visible:=True; end; procedure TMiFormulario.CerrarAutorClick(Sender: TObject); begin PanelABM.visible:=true; PanelTeoria.visible:=False; end;