Sie sind auf Seite 1von 200

Instituto Tecnolgico de Zacatecas

Estructuras de datos con microsoft VB.NET


Para las carreras de Ingeniera en Sistemas Computacionales e Ingeniera en Informtica retculas 2010.

Ricardo Alfonso Almanza Mrquez 15/01/2013

Estructuras de datos con microsoft VB.NET

INTRODUCCIN.
El presente trabajo pretende servir como referencia a los alumnos (y docentes) de las carreras de Ingeniera en Sistemas Computacionales e Ingeniera en Informtica que oferta la DGEST (retculas 2010). Se asume que el estudiante tiene cierta experiencia en el manejo del lenguaje VB.NET. En esta institucin, cuando he tenido oportunidad, he impartido las materias que son competencias previas a Estructura de Datos (Fundamentos de Programacin y Programacin Orientada a Objetos) usando el lenguaje de programacin Visual Basic .NET . De manera que el trnsito por la materia objeto de este libro es bastante amigable. Se ha usado una extraa mezcla de ingles espaol con el fin de no usar la traduccin literal de las palabras reservadas del lenguaje para tratar de evitar confusiones en los alumnos. Es claro que en la prctica real, las estructuras de datos juegan un papel preponderante, as que la importancia de esta materia en la formacin de futures desarrolladores de software no tiene lugar a dudas. Muchos de los casos aqu expuestos han sido tomados de la prctica profesional personal a lo largo de muchos de los sistemas que he tenido la fortuna de implementar. Otros casos son revisiones del material de varios de los autores clsicos de esta materia. El enfoque por competencias que se ha pretendido dar hace que el enfoque sea mucho ms prctico que terico, el estudiante deber escribir los programas aqu presentados con el fin de alcanzar las competencias especficas que establece el programa de la materia y as mismo, realizar los ejercicios propuestos. Es recomendable, cuando sea posible, que los estudiantes asistan a las exposiciones con una lap, al menos una por grupo de trabajo, dadas las limitaciones, que como en el caso nuestro, existen en los laboratorios de cmputo. En esos equipos debe estar instalado al menos la ltima version VBEE [edicin express] (que es gratuita) disponible en los sitios de Microsoft. La idea es que el estudiante escriba todos los programas que se muestran en este texto, tratando de evitar la nociva prctica de copiar pegar, razn por la cual no se proporciona el cdigo fuente de estos. Habr que teclear lnea por lnea. DEDICATORIAS: El trabajo diario de un programador trae consigo una serie de privaciones sobre todo en la familia, quiero dedicar este trabajo a mi esposa Susana, a mis hijos Ricardo y Sandra quienes soportaron privaciones sobre todo en el tiempo que deb dedicarles. A mi nieta Carolina quien vino a darme una nueva oportunidad de reponer ese tiempo y ha sido una nueva luz en mi vida. Quiz tarde he comprendido la importancia de administrar el tiempo en la tarea del desarrollo de sistemas evitando la obsesion de terminar alguna tarea a como d lugar y nunca quitar tiempo de dedicacin a la familia.
Ricardo Alfonso Almanza Mrquez

Estructuras de datos con microsoft VB.NET

Tabla de contenido
Introduccin a las Estructuras de Datos ................................................................ 5 Definiciones ...................................................................................................... 5 Tipos de datos abstractos (TDA) .................................................................... 6 Arreglos ....................................................................................................... 21 Recursividad....................................................................................................... 67 Estructuras Lineales............................................................................................ 73 Listas .............................................................................................................. 73 Lista ligada simple ....................................................................................... 74 Lista ligada doble ......................................................................................... 82 Lista circular ................................................................................................ 94 Pilas .............................................................................................................. 103 Estructuras No Lineales .................................................................................... 127 rboles ...................................................................................................... 127 rboles Binarios ......................................................................................... 128 rboles balanceados .................................................................................. 139 Grafos........................................................................................................ 141 Mtodos de Ordenamiento ............................................................................... 151 Ordemamiento por seleccin ..................................................................... 153 Ordenamiento de la burbuja ...................................................................... 157 Ordenamiento rpido (Quick Sort ............................................................... 159 Ordenamiento por acumulacin (Heap Sort) ............................................... 162 Ordenamiento por mezcla (Merge Sort) ...................................................... 167 Ordenamiento externo ............................................................................... 169 Mtodos de Bsqueda ...................................................................................... 177 Bsqeda secuencial .................................................................................... 177 3

Estructuras de datos con microsoft VB.NET

Bsqueda binaria ....................................................................................... 179 Bsqueda por funciones Hash .................................................................... 180 Anlisis de algoritmos ...................................................................................... 191

Estructuras de datos con microsoft VB.NET

1 Introduccin a las estructuras de datos.


Competencia especfica a desarrollar:
Representar y aplicar los tipos de datos abstractos por medio de un lenguaje de programacin. DEFINICIONES. Una estructura de datos es un formato especializado para almacenar y organizar datos. Los tipos de estructuras de datos generales incluyen el arreglo, el archivo, la tabla, el rbol, etc. Toda estructura de datos es diseada para organizar datos con un propsito especfico a la que se puede acceder y en la que se puede trabajar de forma adecuada. En programacin, se puede seleccionar una estructura de datos puede seleccionarse o disearse para almacenar datos con el propsito de trabajar sobre ella con varios algoritmos. Por su parte, un algoritmo es un procedimiento o frmula para resolver un problema. La palabra

algoritmo proviene del nombre del matemtico Mohamed ibn-Musa al-Khwarizmi que form parte
de la corte real en Bagdad aproximadamente entre los aos 750 a 850 DC. Es fuente adems de la palabra algebra. Enciclopedia Britnica:

Estructura de datos.-

Forma en la que los datos son almacenados para una bsqueda y

recuperacin eficientes. La estructura de datos ms simple es el arreglo unidimensional (lineal). Enciclopedia de ciencia y tecnologa de McGraw-Hill: Medio para almacenar una coleccin de datos. La ciencia de la computacin es en parte el estudio de los mtodos para usar efectivamente una computadora en la solucin de problemas, o en otras palabras, la determinacin exacta del problema a resolver. Este proceso implica: 1. 2. Comprender el problema. Traducir descripciones vagas, metas y requerimientos contradictorios (y a menudo deseos sin especificar) dentro de una solucin conceptual formulada con precisin con un lenguaje de programacin. Esta solucin generalmente consiste en dos partes: algoritmos y

estructuras de datos.
Relacin con algoritmos. Un algoritmo es una especificacin concisa de un mtodo para resolver un problema. Una estructura de datos puede verse como un conjunto de algoritmos para realizar operaciones sobre los datos que almacena. As, los algoritmos son parte de lo que constituye una estructura de datos. En la construccin de la solucin a un problema, una estructura de datos debe ser elegida de manera que permita que los datos sean manipulados fcilmente de la manera que el algoritmo lo requiere.

Estructuras de datos con microsoft VB.NET


Los datos pueden organizarse en diferentes niveles y la variedad en el diseo de algoritmos generalmente surge de la manera en la cual los datos para el programa son almacenados, esto es: 1. 2. 3. 4. Cmo se organizan los datos en relacin a otros. Cules datos son calculados necesariamente. Cules datos permanecen en memoria. Cules datos deben almacenarse en archivos y la organizacin de estos archivos.

Un algoritmo puede requerir colocar datos nuevos en una coleccin existente de los mismos, removerlos o acceder a una coleccin de datos para propsitos especficos. Tipos de datos abstractos (TDA). Un tipo de dato abstracto (TDA), abstract data type (ADT), es un modelo matemtico que puede usarse para capturar lo esencial del dominio de un problema con el fin de traducirlo a un lenguaje de programacin. Es una entidad matemtica que consiste en un conjunto de valores (el conjunto portador) y una coleccin de operaciones que los manipule. Por ejemplo, el tipo de dato abstracto entero consiste de un conjunto portador que contiene los nmero enteros negativos y positivos adems del 0 y una coleccin de operaciones que los manipula como pueden ser la suma, la resta, la multiplicacin, la comparacin de igualdad y la comparacin de orden (Algebra abstracta).

Abstraccin.
Abstraccin es ignorar el detalle de algunas cosas a favor de otras. La abstraccin es importante en la solucin de problemas porque permite a quien los resuelve enfocarse en los detalles esenciales en tanto ignora los no esenciales, simplificando as el problema y concentrando su atencin en aquellos aspectos del mismo que involucran su solucin. Los tipos de datos abstractos son importantes en ciencias de la computacin porque proporcionan una manera clara y precisa para especificar que datos debe manipular un programa (y cmo debe manejarlos) sin considerar los detalles sobre cmo los datos son representados cmo se implementan las operaciones. Una vez comprendidos los tipos de datos abstractos y documentados, sirven como una especificacin que los programadores pueden usar para guiar su decisin sobre la implementacin y operacin de los datos y como un estndar para asegurar la exactitud del programa. Tales especificaciones de los tipos de datos abstractos proporcionan las bases para su realizacin en programas. Los programadores conocen que valores de datos necesitan ser representados, que operaciones sern requeridas y qu limitaciones deben satisfacerse. El estudio cuidadoso del cdigo desarrollado y la apropiada seleccin de pruebas ayudan a asegurar que el programa est correcto. Finalmente las especificaciones de tipos de datos abstractos pueden usarse para investigar y demostrar de los tipos de datos abstractos mismos, llevando a un mejor entendimiento de los programas y finalmente a un software de alta calidad.

Estructuras de datos con microsoft VB.NET


Relacin con el paradigma orientado a objetos. Una tendencia mayor en la ciencia de la computacin ha sido el paradigma orientado a objetos, un enfoque para programar, disear e implementar que usa colecciones de entidades que interactan entre s llamadas objetos. Los objetos incorporan tanto datos como operaciones, de esta manera imitan cosas del mundo real, las cuales tienen propiedades (datos) y conductas (tambin llamadas

mtodos) las operaciones. Los objetos que manejan el mismo tipo de datos y realizan las mismas
operaciones forman una clase. Los valores de datos abstractos estn separados de sus operaciones. Si los valores del conjunto portador de un tipo de dato abstracto se pueden reconceptualizar para incluir no slo valores de datos sino tambin operaciones abstractas, entonces los elementos del conjunto portador se vuelve una entidad que incorpora tanto datos como operaciones, como objetos, y el conjunto portador en s es mucho ms parecido a una clase. El paradigma orientado a objetos puede verse como una extensin del uso de tipos de datos abstractos. Modularidad. Es la propiedad que permite subdividir una aplicacin en partes ms pequeas llamadas mdulos con el fin de hacerla ms comprensible y manejable. Histricamente es una evolucin de la

programacin estructurada para solucionar problemas de programacin ms grandes y complejos


de lo que sta puede resolver. Un mdulo es cada una de las partes de un programa que resuelve una de las partes en que se divide el problema complejo original. Cada mdulo tiene una tarea bien definida y algunos necesitan de otros para poder operar. En caso de que un mdulo necesite de otro, puede comunicarse con ste mediante una interfaz de comunicacin que debe estar bien definida. Es comn en la prctica tomar el concepto de mdulo como sinnimo de procedimientos procedimiento, ya que el mismo puede contener muchos de ellos. La modularidad es un concepto que se ha aplicado durante muchos aos en el desarrollo de programas, actualmente es casi imposible crear aplicaciones relativamente complejas sin usar mdulos, por esta razn el estudiante que llega a esta materia (Estructuras de Datos) debe estar familiarizado con el concepto desde sus primeros cursos de programacin. y

funciones. Sin embargo no necesariamente ni estrictamente un mdulo es una funcin o un

Uso de TDA. Planteamiento del problema:

Estructuras de datos con microsoft VB.NET


Una lnea recta se define como la unin de dos puntos (P1 y P2) definidos sobre un eje cartesiano XY. Cada punto se define por dos valores x-y: P1(x, y) y P2(x, y) As si ambos puntos tienen valores: P1(1,1) ; P2(5, 5) la recta resultante es:

6 5 4 3 2 1 0 1
. La distancia entre ambos puntos est definida por: [1]

Y la ecuacin que la representa es: [2]

Donde la pendiente m es: [3]

Y en funcin de los dos puntos, la recta puede obtenerse con: [4]

Estructuras de datos con microsoft VB.NET


O en funcin del punto P1 y la pendiente m: [5]

Desarrollar una aplicacin que utilice un TDA que lea los dos puntos, encuentre la distancia entre ambos y muestre la ecuacin de la recta resultante usando el paradigma orientado a objetos. Al principio de esta unidad se estableci que la determinacin exacta de un problema implica, ante todo, la comprensin del mismo. Se puede afirmar que si se es capaz de resolverlo manualmente tal comprensin se ha alcanzado: Solucin (manual):

Pendiente:

Finalmente, de la ecuacin [5]:

Que es la ecuacin de esta recta:

Una vez que se entiende el problema el primer paso es la abstraccin del mismo lo que requiere identificar: 1. 2. 3. 4. Que datos son necesarios (entradas). Que datos se esperan en la solucin. Que valores son calculados en los procesos de solucin. Desarrollar el algoritmo que resuelva el problema.

Estructuras de datos con microsoft VB.NET


Para esto representaremos la recta como un objeto (que es el TDA que la manipular). Datos de Salida: Distancia entre P1 y P2 (d). Pendiente de la recta (m). Ecuacin: y = mx + b

Datos de entrada: P1 y P2 definidos por pares de valores numricos para (x, y) y (x, y)

Recta

Esta es una abstraccin simple, as para el ejemplo considerado la solucin se representa como:

x = 1, y = 1 x = 5, y =5

Recta

d= m=1 y=x

Algoritmos

Definicin del objeto Recta:

Recta Propiedades
Nombre X1 X2 Y1 Y2 Tipo de dato Nmero real simple Nmero real simple Nmero real simple Nmero real simple Nombre Distancia Pendiente Ecuacin (Ec)

Mtodos
Tipo de dato Real simple Real simple Cadena Propsito Calcula distancia Obtiene m Ecuacin resultante

En el diseo de clases de este texto seguimos la metodologa propuesta por Deborah Kurata1 As, una vez creada la clase que representar al objeto Recta, el algoritmo general de solucin puede plantearse de la siguiente manera: 1. Leer datos de entrada (X1, Y1, X2, Y2) Asignacin de propiedades.

Deborah Kurata: Doing Objects in Microsoft VB.NET.

10

Estructuras de datos con microsoft VB.NET


2. 3. 4. 5. Calcular la distancia usando [1]. Calcular la pendiente usando [3]. A partir de las ecuaciones [4] [5] obtener la ecuacin de la recta como una cadena de caracteres. Mostrar resultados.

Clase que representa al TDA:

Imports System.Math Public Class CTDA_Recta Private mvarX1 As Single Private mvarX2 As Single Private mvarY1 As Single Private mvarY2 As Single Private mvarm As Single Property X1() As Single Get Return mvarX1 End Get Set(ByVal value As Single) mvarX1 = value End Set End Property Property X2() As Single Get Return mvarX2 End Get Set(ByVal value As Single) mvarX2 = value End Set End Property Property Y1() As Single Get Return mvarY1 End Get Set(ByVal value As Single) mvarY1 = value End Set End Property Property Y2() As Single Get Return mvarY2 End Get Set(ByVal value As Single) mvarY2 = value End Set End Property

P r o p i e d a d e s

11

Estructuras de datos con microsoft VB.NET


Public Function Distancia() As Single 'De la frmula [1] Dim D As Single = Sqrt((X2 - X1) ^ 2 + (Y2 - Y1) ^ 2)2 Return D End Function Public Function m() As Single 'De la frmula [3] Return (Y2 - Y1) / (X2 - X1) End Function Public Function Ec() As String 'Usando [5] Dim Eq As String = "Y = " & m.ToString("n2") & "X " Dim Temp As Single = -m() * X1 + Y1 'Verificar signo de Temp If Sign(Temp) = 1 Then Eq += " + " + Temp.ToString("n2") ElseIf Sign(Temp) < 0 Then Eq += " - " + Temp.ToString("n2") End If Return Eq End Function End Class

M t o d o s

Uso en consola:
Imports System.Console Module Module1 Private MiTDA As New CTDA_Recta Sub Main() BackgroundColor = ConsoleColor.White ForegroundColor = ConsoleColor.Black Clear() WriteLine("Punto P1:") Write("X1 = ") MiTDA.X1 = ReadLine() Write("Y1 = ") MiTDA.Y1 = ReadLine() WriteLine() WriteLine("Punto P2:") Write("X2 = ") MiTDA.X2 = ReadLine() Write("Y2 = ") MiTDA.Y2 = ReadLine() WriteLine() WriteLine("RESULTADOS") WriteLine("Distancia = " + MiTDA.Distancia.ToString("n4")) WriteLine("Pendiente m = " + MiTDA.m.ToString("n2")) WriteLine("La ecuacin es:") WriteLine() WriteLine(MiTDA.Ec) ReadKey() End Sub End Module

Ejecucin:

El smbolo ^ tambin representa al operador de potencia.

12

Estructuras de datos con microsoft VB.NET

El uso de consolas permite una rpida revisin de la solucin que se trata de implementar. Despus de probar con diferentes valores con resultados conocidos, la solucin se transporta fcilmente al entorno Windows.

Para crear la solucin usando las capacidades de VB.NET se puede crear la siguiente forma bsica:

Objetos en esta ventana (valores sugeridos): Objeto (Name) frmTDA_Recta txtX1, txtY1 txtX1, txtY2 btnResult labD, labM Tipo Form Textbox TextBox Buttton Label Propiedades MaximizeBox = False StartPosition = CenterScreen TextAlign = Center TextAlign = Center AutoSize = False Propsito

Capturar X1 Capturar Y2 Iniciar mtodos Mostrar distancia y

13

Estructuras de datos con microsoft VB.NET


BackColor = White Text = 0 TextAlign = MiddleRight AutoSize = False BackColor = White Text = TextAlign = MiddleCenter Pendiente.

labEc

Label

Mostrar la ecuacin.

Agregar al proyecto la clase TDA desarrollada previamente: Men Proyecto Agregar elemento existente.

El proyecto debe verse as:

Ejecucin:

Public Class frmTDARecta Private MiTDA As New CTDA_Recta Private Sub btnResult_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnResult.Click Try 'Lectura de puntos P1 y P2: MiTDA.X1 = CSng(txtX1.Text) MiTDA.Y1 = CSng(txtY1.Text)

14

Estructuras de datos con microsoft VB.NET


MiTDA.X2 = CSng(txtX2.Text) MiTDA.Y2 = CSng(txtY2.Text) 'Resultados labD.Text = MiTDA.Distancia.ToString("n4") labM.Text = MiTDA.m.ToString("n2") labEc.Text = MiTDA.Ec Catch ex As Exception MsgBox("Se ha ingresado un valor no permitido", MsgBoxStyle.Exclamation) End Try End Sub Private Sub btnNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNew.Click 'Datos nuevos MiTDA = New CTDA_Recta 'Limpia las cajas de texto: For Each oTexto As Control In Me.Controls If TypeOf (oTexto) Is TextBox Then oTexto.Text = "" End If Next labD.Text = "" labM.Text = "" labEc.Text = "" txtX1.Focus() End Sub Private Sub btnClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClose.Click Me.Close() End Sub End Class

Ejercicio #1 para el desarrollo de la competencia especfica: Para un cilindro circular (recto)3 se tienen las frmulas siguientes: Volumen: [1]

rea: [2]

Del Manual de frmulas tcnicas. Gieck 30 Edicin. IPN.

15

Estructuras de datos con microsoft VB.NET


Donde A es el rea, d es el dimetro de la circunferencia, h la altura del cilindro y r el radio. Si se conocen la altura y el dimetro calcular el volumen. Si se conoce la altura y el volumen calcular el dimetro y si se conocen el volumen y el dimetro calcular la altura. Disear la clase que represente al tipo de dato abstracto

Cilindro para realizar lo que se pide (para consola y para una


forma).
NOTA.- En el espacio de nombres Math del .NET Framework est definida la constante (Math.PI). Y la funcin Pow permite elevar cualquier nmero a una potencia. Pow(n, m) donde n es el nmero y m la potencia. Por ejemplo, el pseudocdigo 43 se representa como Pow(4,3).

Casos de prueba: h=4 d=2 Entonces de [1] :

Y de [2]

Si h=4yA= Obteniendo el radio de [2]: r = 1, luego el dimetro es 2r = 2 Por ltimo si se conocen los valores de d y de A: Entonces h 4 . Prueba del programa:

16

Estructuras de datos con microsoft VB.NET

Vista del proyecto:

Solucin para Windows Aprovechando las muchas facilidades de interfaz para el usuario que proporciona VB.NET, una solucin al problema podra verse as: Ventana de base (frmTDACilindro):
Los controles de opciones (RadioButton) tienen asignado un valor numrico consecutivo en su propiedad

Tag (0, 1 y 2) que se mapea


con la misma propiedad de las cajas de texto para los datos: Volumen (Tag = 0) Tag = 2 en la caja texto Dimetro correspondiente.

(Tag = 1) Tag = 0 en la caja de texto. Altura (Tag = 2) Tag = 1 en la caja de texto del dimetro. Todos tienen su propiedad Chcked en False y

17

estn

contenidos

en

un

GroupBox.

Estructuras de datos con microsoft VB.NET


Valores de la propiedad Tag sugeridos

Tag en RadioButton Nombre


rbVol rbV rbAltura

Tag
0 1 2

Cada vez que el usuario selecciona una opcin el valor de la propiedad Tag es asignado a un objeto de tipo entero corto, (iModo), manejando este evento en un solo procedimiento (de evento) y permite conocer que partes del TDA usar.
Public Class frmTDACilindro Private MiTDACil As CTDA_CilindroR 'La clase se importa desde la aplicacin de consola donde fue desarrollada y probada Private iModo As Short Private Sub frmTDACilindro_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 'La carga de la forma establece la primera seleccin y se desencadena el evento: rbVol.Checked = True End Sub Private Sub rbAltura_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles rbAltura.CheckedChanged _ , rbD.CheckedChanged, rbVol.CheckedChanged 'Cualquier evento de seleccin es manejado en este procedimiento Dim oRB As RadioButton = sender If oRB.Checked Then MiTDACil = New CTDA_CilindroR iModo = oRB.Tag SetTextos() btnOK.Enabled = True End If End Sub

As las tres opciones son manejadas en la misma ventana: Caso 1: Altura y dimetro conocidos. Al el seleccionar rea esta opcin, los

objetos de texto para el volumen y son desactivados (propiedad ReadOnly = True) por el mdulo SetTextos. De esta manera, el usuario slo puede ingresar los valores conocidos (propiedades del TDA). El botn mtodos desarrollados en la clase y muestra los resultados faltantes. desencadena los (operaciones)

18

Estructuras de datos con microsoft VB.NET


Cuando se cambia de opcin, la ventana se prepara para recibir los nuevos datos: Caso 2: Altura y rea conocidas. El mismo mdulo SetTextos ahora desactiva los valores que deben ser calculados.

Caso

3:

Dimetro

altura

conocidos.

Private Sub SetTextos() For Each oTexto As Control In Me.Controls If TypeOf (oTexto) Is TextBox Then Dim txt As TextBox = oTexto txt.Clear() txt.ReadOnly = True If iModo = 0 Then txt_h.ReadOnly = False txtD.ReadOnly = False ElseIf iModo = 1 Then txt_h.ReadOnly = False txtArea.ReadOnly = False Else txtD.ReadOnly = False txtArea.ReadOnly = False End If End If Next End Sub

19

Estructuras de datos con microsoft VB.NET


El siguiente cdigo depende de cmo se haya desarrollado la clase que representa al TDA para el manejo de este tipo de cilindro y deber ser completado y probado.
Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click Try Select Case iModo Case 0 'Altura y dimetro conocidos: Case 1 'Altura y rea conocidas: Case Else 'Dimetro y altura conocidos End Select Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.Exclamation) End Try End Sub

Ejercicio #2: Para el cuerpo geomtrico denominado cono circular (recto) se tienen las siguientes frmulas4: [1]

[2]

[3]

[4]

[5]

Disear un TDA (clase) que permita el clculo de:

Manual de frmulas tcnicas. Greck. IPN

20

Estructuras de datos con microsoft VB.NET

Ejercicio #3.- Se desea conocer el volumen de un barril (usando una clase):

Arreglos. El arreglo es la estructura de datos ms comn y existe desde los primeros lenguajes de programacin. Un arreglo permite almacenar un conjunto de elementos ordenndolos por posicin, generalmente la primera posicin tiene el valor de cero y, normalmente, debe conocerse el nmero de elementos N que se van a almacenar.
0 1 2 N

Posiciones Elementos

Ei

En

El uso de esta estructura requiere reservar ubicaciones de memoria RAM contiguas en tiempo de compilacin y esta asignacin puede ser esttica o dinmica. Dependiendo de cmo sea declarado, un arreglo puede existir (ser accesible) en: Todo el programa. En un mdulo En un procedimiento. de forma esttica no se libera sino hasta que la ejecucin del programa

La memoria asignada

termina de otro modo el arreglo deja de existir al terminar la ejecucin del mdulo o el procedimiento donde fue creado. En VB.NET, un arreglo es una instancia de la clase Array misma que proporciona un conjunto de mtodos tales como ordenacin y bsqueda que en el pasado se tenan que desarrollar. Sin embargo eso no impide que se analicen los diferentes algoritmos para tales procesos. Este lenguaje (y todos los que usan el marco .NET) tienen una clase nueva denominada ArrayList que es un arreglo que obtiene ms espacio de forma dinmica a medida que lo requiere. En situaciones donde no se conoce con exactitud el tamao del arreglo o cuando ste puede cambiar durante el ciclo de vida de un programa un ArrayList puede ser una mejor eleccin que un arreglo simple.

Declaracin e inicializacin de arreglos.

21

Estructuras de datos con microsoft VB.NET


Un arreglo (de una dimensin) se declara con un nombre y, opcionalmente su tamao (N valor de

tipo entero) y estableciendo que tipo de datos manejar. Esta accin se representa como A[N], a
cada elemento del arreglo se le asigna un valor (del tipo adecuado) usando un apuntador i. Un arreglo de una dimensin se puede declarar a nivel mdulo como: Private Arreglo(), si no se especifica su tamao N, se dice que el arreglo es dinmico y puede modificar su tamao en cualquier parte del mdulo usando la instruccin ReDim. Ejemplo:
Imports System.Console Module Module1 Private Arreglo() As Integer, N As Short Sub Main() ForegroundColor = ConsoleColor.Black BackgroundColor = ConsoleColor.White Clear() Dim i As Short Write("N = ") N = ReadLine() 'Se forma el arreglo, si existiera uno previo ser reemplazado 'El valor de cada uno de sus elementos es cero ReDim Arreglo(N) For i = 0 To N - 1 Write("A[" + i.ToString + "] = ") Arreglo(i) = ReadLine() Next WriteLine() WriteLine("El arreglo es:") WriteLine() For i = 0 To N - 1 Write(Arreglo(i).ToString + " ") Next WriteLine() ReadKey() End Sub End Module

Se puede modificar el tamao de un arreglo sin perder la informacin almacenada en l usando la instruccin Redim Preserve:
Modificando el programa anterior: Imports System.Console Module Module1 Private Arreglo() As Integer, N As Short Sub Main() ForegroundColor = ConsoleColor.Black

22

Estructuras de datos con microsoft VB.NET


BackgroundColor = ConsoleColor.White Clear() Dim i, U As Short Write("N = ") N = ReadLine() 'Se forma el arreglo, si existiera uno previo ser reemplazado 'El valor de cada uno de sus elementos es cero ReDim Arreglo(N) For i = 0 To N - 1 Write("A[" + i.ToString + "] = ") Arreglo(i) = ReadLine() Next U = i 'La tima posicin en el arreglo WriteLine() WriteLine("El arreglo es:") WriteLine() For i = 0 To N - 1 Write(Arreglo(i).ToString + " ") Next WriteLine() Write("Nuevo Tamao: ") N = ReadLine() 'Se modifica el tamao del arreglo manteniendo sus valores ReDim Preserve Arreglo(N) For i = U To N - 1 Write("A[" + i.ToString + "] = ") Arreglo(i) = ReadLine() Next WriteLine() WriteLine("El arreglo es:") WriteLine() For i = 0 To N - 1 Write(Arreglo(i).ToString + " ") Next WriteLine() ReadKey() End Sub End Module

Ejecucin:

Si se desea usar un arreglo esttico debe usarse la declaracin Static:

23

Estructuras de datos con microsoft VB.NET


Imports System.Console Module Module1 Sub Main() ForegroundColor = ConsoleColor.Black BackgroundColor = ConsoleColor.White Clear() Dim N As Short Write("N = ") N = ReadLine() Static Dim A(N) As Integer LlenaPares(N, A) Write("El Arreglo de pares es:") WriteLine() For i As Short = 0 To N - 1 Write(A(i).ToString + " ") Next ReadKey() End Sub Private Sub LlenaPares(ByVal N As Short, ByRef A() As Integer) Dim i As Short Dim Valor As Short = 2 For i = 0 To N A(i) = Valor Valor += 2 Next End Sub End Module

Este tipo de arreglos consume ms memoria que los dinmicos. Si A[i] k, donde 0<=i <=N-1 (Tipo de datos) As por ejemplo: Si N = 5, A[N] (3, 5, 7, 1, 2) en VB.NET se puede crear de la manera clsica como: El uso de consola es prctico solo para arreglos pequeos para probar procedimientos bsicos. Listado #1.
Imports System.Console Module Module1 Sub Main() ForegroundColor = ConsoleColor.Black BackgroundColor = ConsoleColor.White Clear() Dim N As Short = 5 Dim A(N - 1) As Short '5 posiciones ya que la primera comienza en cero A(0) = 3 A(1) = 5 A(2) = 7 A(3) = 1 A(4) = 2 WriteLine("El arreglo es:") For i As Short = 0 To N - 1 Write(A(i).ToString + " ") Next WriteLine() ReadKey() End Sub End Module

El mismo programa en las versiones de VB.NET 2008 y posteriores se puede escribir as:

24

Estructuras de datos con microsoft VB.NET


Listado #2.
Imports System.Console Module Module1 Sub Main() ForegroundColor = ConsoleColor.Black BackgroundColor = ConsoleColor.White Clear() Dim A() As Short = {3, 5, 7, 1, 2} WriteLine("El arreglo es:") For Each Numero As Short In A Write(Numero.ToString + " ") Next WriteLine() ReadKey() End Sub End Module

El ciclo For-Each itera sobre cada elemento del arreglo comenzando por el primero sin necesidad de apuntadores. mantener

O tambin: Listado #3.


Imports System.Console Module Module1 Sub Main() ForegroundColor = ConsoleColor.Black BackgroundColor = ConsoleColor.White Clear() Dim A() As Short A = New Short() {3, 5, 7, 1, 2} WriteLine("El arreglo es:") For Each Numero As Short In A Write(Numero.ToString + " ") Next WriteLine() ReadKey() End Sub End Module

Todas las ejecuciones producen la misma salida: En todos los casos, el arreglo A[N] fue declarado localmente (dentro del procedimiento Sub Main( ) y de forma dinmica. Por tanto existe slo mientras tal procedimiento es ejecutado.

Manejo de diferentes conjuntos de datos sobre un mismo arreglo. En el siguiente cdigo, el arreglo A[ ] es declarado a nivel del mdulo usando adems la palabra

Priivate, lo que significa que el arreglo permanece durante la ejecucin del mdulo y al ser declarado
inicialmente sin dimensin se dice que es un arreglo dinmico. Cada vez que se establece un valor numrico para N el arreglo se crea usando ReDim que adems inicializa todos sus elementos en cero.

25

Estructuras de datos con microsoft VB.NET


Imports System.Console Module Module1 Private A() As Integer Sub Main() ForegroundColor = ConsoleColor.Black BackgroundColor = ConsoleColor.White Dim A() As Integer Dim N, i, x As Integer Dim Continua As String = "S" Do While Continua.ToUpper = "S" Clear() Write("N = ") N = ReadLine() If IsNumeric(N) Then ReDim A(N - 1) For i = A.GetLowerBound(0)5 To A.GetUpperBound(0)6 Write("A[" + i.ToString + "] = ") A(i) = ReadLine() Next WriteLine() WriteLine("Valorese en el arreglo:") For Each x In A Write(x.ToString + ", ") Next End If WriteLine() WriteLine() WriteLine("Ingresa otro arreglo (S/N)? ") Continua = ReadLine() Loop End Sub End Module

Para el anlisis de algoritmos que involucran arreglos de un tamao relativamente grande, el uso de consolas resulta bastante tedioso. Es conveniente crear una forma general que maneje arreglos de una manera eficiente y permita desarrollar y probar diferentes algoritmos. Forma bsica para arreglos de una dimensin:

5
6

GetLowerBound(k) regresa el lmite inferior del arreglo k = 0 para arreglos de una dimensin. GetUpperBound(k) el lmite superior de un arreglo, k =0 para renglones y k = 1 para columnas en una matriz.

26

Estructuras de datos con microsoft VB.NET

Descripcin de la aplicacin: Permite establecer el valor del tamao del arreglo (N). Al aceptarlo ste ser creado y se prepara su interfaz para la asignacin de sus valores.

Los controles de esta seccin estn contenidos en un GroupBox cuya propiedad Name se establece como GpoN. Un control numrico (NumericUpDown) con propiedades Maximum = 200 y Minimum =

5 y TextAlign =Center y de nombre NumN.


El arreglo resultante es manipulado en un control llamado DataGridView denominado DGVA y con la propiedad AllowUserToAddRows = False. Los procedimientos de evento que este control tiene permiten que la validacin de los datos de entrada sean validados fcilmente. Estos botones permiten guardar y recuperar el arreglo actual en (desde) un archivo secuencial. El botn guardar se ha denominado btnSave y tiene su propiedad Enabled = False. El segundo botn se llama btnOpen sin ningn otro valor de propiedad modificado . Es otro GroupBox llamado GpoAlg en donde se irn insertando botones que resuelvan diferentes problemas usando arreglos.

27

Estructuras de datos con microsoft VB.NET

Es un TextBox de nombre txtSol, con la propiedad

Multiline

establecida

en

True.

SrollBars

Both,

WordWrap = False, Font = Console (8 pts)7.

Cuadros de dilogo para el manejo de archivos de nombre SaveFD y OpenFD respectivamente.

SaveFD.- Control SaveFileDialog, defaultExt = dat, Filter = Archivos de datos (*.dat)|*.dat. OpenFD.- Control OpenFileDialog con las mismas propiedades Filter y defaultExt anteriores y la propiedad FileName = (nada)

La primera fase de desarrollo debe permitir crear arreglos, asignar sus valores (numricos), guardarlo y recuperarlo Este es el primer cdigo a escribir.
Public Class frmArray Private Arreglo() As Integer, N Private Sub frmArray_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim sRuta As String = My.Application.Info.DirectoryPath + "\Arreglos" 'Si esta ruta no existe, se crea If Not My.Computer.FileSystem.DirectoryExists(sRuta) Then My.Computer.FileSystem.CreateDirectory(sRuta) End If 'Ruta inicial para los cuadros de dilogo de archivos SaveFD.InitialDirectory = sRuta OpenFD.InitialDirectory = sRuta End Sub

Creacin de arreglo y de su interfaz:

Aunque puede dejarse el valor por defecto.

28

Estructuras de datos con microsoft VB.NET

Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click CreaArreglo() End Sub

En este procedimiento se asigna el valor de N, se forma un arreglo nuevo y se prepara DGVA para representarlo y manejarlo.
Private Sub CreaArreglo() N = NumN.Value ReDim Arreglo(N) With DGVA .RowCount = 1 'Siempre un slo rengln .ColumnCount = Arreglo.GetUpperBound(0) 'Columnas = Tamao del arreglo For Each Kol As DataGridViewColumn In DGVA.Columns Kol.HeaderText = Kol.Index 'Posicin Kol.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells 'Autoajuste de celdas Kol.DefaultCellStyle.Alignment = DataGridViewContentAlignment.TopCenter 'Alineado al centro Next End With Valores() btnSave.Enabled = True End Sub

Private Sub Valores() 'Muestra el arreglo en DGVA Dim i As Integer For i = 0 To N - 1 DGVA.Rows(0).Cells(i).Value = Arreglo(i) Next End Sub

Validacin de entradas (procedimiento de evento en DGVA):

Si el valor ingresado en la celda actual es numrico lo convierte a tipo entero de otro modo lo establece en cero.
Private Sub DGVA_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DGVA.CellEndEdit If IsNumeric(DGVA.CurrentCell.Value) Then Arreglo(e.ColumnIndex) = CInt(DGVA.CurrentCell.Value) Else MsgBox("Valor no permitido", MsgBoxStyle.Exclamation) DGVA.CurrentCell.Value = 0 End If End Sub

Guardar el arreglo actual: (Doble clic en el botn para generar la plantilla del procedimiento de evento)

29

Estructuras de datos con microsoft VB.NET


Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click 'Guarda el arreglo en un archivo secuencial If SaveFD.ShowDialog = Windows.Forms.DialogResult.OK Then 'Valor para el manejo del archivo Dim FM As Short = FreeFile() 'Abre el archivo para escritura FileOpen(FM, SaveFD.FileName, OpenMode.Output) 'Guarda el tamao de N PrintLine(FM, N) 'Guarda secuencialmente cada valor en el arreglo For Each x As Integer In Arreglo PrintLine(FM, x) Next FileClose(FM) MsgBox("Arreglo guardado", MsgBoxStyle.Information) End If End Sub

Private Sub btnOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpen.Click If OpenFD.ShowDialog = Windows.Forms.DialogResult.OK Then Dim FM As Short = FreeFile() 'Abre el archivo para lectura secuencial FileOpen(FM, OpenFD.FileName, OpenMode.Input) 'Lee el primer valor (N) N = LineInput(FM) NumN.Value = N CreaArreglo() 'Asigna sus valores secuencialmente: Dim x As Integer For i As Integer = 0 To N - 1 x = LineInput(FM) Arreglo.SetValue(x, i) 'Equivale a Arreglo(i) = x Next FileClose(FM) Valores() End If End Sub

Probar la aplicacin creando diferentes arreglos, guardndolos y recuperndolos.

Aplicacin de arreglos.
Ejemplo: La compresin de un arreglo a veces implica eliminar los elementos que se repiten y mostrar los valores que permanecen en la misma secuencia. Si el arreglo es: 15 9 10 4 15 10 3 4 15 20

Al comprimirlo resultara en: 15 9 10 4 3 20

30

Estructuras de datos con microsoft VB.NET


Se asume que el arreglo existe y tiene valores (por lo que N es tambin conocida). Algoritmo: 1. 2. 3. Hacer m 0 (contador de elementos eliminados) Recorrer el arreglo para i 0, 1, , N 2 (hasta el penltimo elemento). Recorrer el arreglo hacia adelante para j i + 1, i + 2, , i + (N 1) (hasta el ltimo elemento) a. 4. 5. 6. Si A[i] no es nada (Si A[j] Nada entonces A[j] Nada: m m + 1 Crear el arreglo temporal de resultados: B[N m] Llenarlo con los valores del arreglo original diferentes de nada. Mostrarlo.

El control DGV permite ingresar y modificar los datos de arreglo directamente.

Nuevo botn agregado.

Arreglo inicial. Es importante expresar el

algoritmo en un lenguaje natural (espaol, por ejemplo) separando los pasos consecutivos que han de seguirse usando expresiones algortmicas para denotar el cmo hacerlo de manera que se pueda resolver cualquier problema similar. Resolver el problema directamente usando papel y lpiz para poder tener una base de comprobacin a la solucin. Arreglo comprimido ( )

Private Sub btnComprimir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnComprimir.Click Dim i, j, m As Integer m = 0 '...[1] '[2]

31

Estructuras de datos con microsoft VB.NET


For i = 0 To Arreglo.GetUpperBound(0) - 1 '[3] For j = i + 1 To Arreglo.GetUpperBound(0) If Not Arreglo(j) Is Nothing Then '[3a] If Arreglo(i) = Arreglo(j) Then Arreglo(j) = Nothing m += 1 End If End If Next Next '[4] Dim B() As Object ReDim B(N - m - 1) j = 0 For i = 0 To Arreglo.GetUpperBound(0) If Not Arreglo(i) Is Nothing Then B(j) = Arreglo(i) j += 1 End If Next 'Establece nuevos valores '[5] NumN.Value = N - m - 1 CreaArreglo() For i = 0 To Arreglo.GetUpperBound(0) Arreglo(i) = B(i) Next '[6] Valores() End Sub

Ejercicio: Dado un polinomio de la forma:

Usando un arreglo para los coeficientes ai, encontrar el valor de una expresin y diferentes valores de X (X1, X2, ) Solucin: Sea

Para valores de X = 1, 2 y 3 la solucin sera:

Para este caso, el arreglo de coeficientes quedara: 0 3 1 4 2 -2 3 2

32

Estructuras de datos con microsoft VB.NET

Lo primero que debe plantearse es que tamao de arreglo usar. Una vez que los coeficientes son asignados usando los valores de sus posiciones se puede resolver la expresin para valores de X dados. La solucin puede presentarse como:

Cada valor de X es ingresado usando un control InputBox:

Algoritmo.
1. 2. 3. 4. 5. Establecer el tamao del arreglo en base al grado del polinomio (m). N m + 1. Crear el arreglo y asignar los coeficientes. A[i] ai Inicializar el valor de la expresin: P 0 Leer un valor para X Iterar sobre el arreglo para cada valor de X (Si X > 0) (A[i], i 0, 1, , N) km-i P P + A([i]*X k 6. Mostrar resultado.

Private Sub btnPoli_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPoli.Click Dim X As Integer = Val(InputBox("Valor de X", "Datos", "1")) If X > 0 Then

33

Estructuras de datos con microsoft VB.NET


P As Long = 0 m, i, k As Integer N - 1 i = 0 To Arreglo.GetUpperBound(0) k = m - i P += Arreglo(i) * X ^ k Next Dim Salida As String = "P(" + X.ToString + ") = " + P.ToString With txtSol .SelectionStart = .Text.Length .SelectedText = Salida + vbCrLf End With End If End Sub Dim Dim m = For

Ejercicios propuestos: 1.- Un nmero entero positivo en base decimal se puede convertir a su base binaria u octal con divisiones sucesivas entre la base (2 u 8) y acumulando los residuos en un arreglo hasta que el cociente se cero. Por ejemplo: Sea Nmero 1024 Dividendo 1024 512 256 178 64 32 16 8 4 2 1 Divisor 2 2 2 2 2 2 2 2 2 2 2 Cociente 512 256 128 64 32 16 8 4 2 1 0 Residuo 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0

Arreglo de residuos 0 0 0 0 0 0 0 0 0 0
1

0 0 0 0 0 0 0 0 0
2

0 0 0 0 0 0 0 0
3

0 0 0 0 0 0 0
4

0 0 0 0 0 0
5

0 0 0 0 0
6

0 0 0 0
7

0 0 0
8

0 0
9

1
10

El nmero binario resultante se obtiene leyendo el arreglo de derecha a izquierda: 10000000000 Escribir el procedimiento de evento para esta tarea (Base 2 u 8). Sugerencia:

34

Estructuras de datos con microsoft VB.NET

Botn nuevo btnBaseN.

RadioButtons
rbBin, propiedad Checked = True rbOctal. Dado que estas conversiones de base son utilizadas frecuentemente en otras soluciones es conveniente crear este procedimiento en una funcin pblica dentro de un mdulo: Agregar un mdulo a esta aplicacin (Men Proyecto Agregar mdulo) dndole un nombre a ste:

Module ModMisMetodos Public Function BaseN(ByVal Num As Long, ByVal Base As Short, ByRef Arr() As Object) As String Dim Salida() As Char Dim N As Short = 16 Dim Cociente As Long = 0, P As Short = -1, Res As Short ReDim Salida(N) 'Solucin al problema: Salida() es un arreglo temporal de tipo Cdigo a desarrollar Do '1.- Obtener el cociente '2.- Obtener el residuo y 'guardarlo en Salida(P) '3.- Num = Cociente '4.- Repetir desde el paso 1 hasta 'que el cociente sea cero. Loop Until Cociente = 0 Dim sTemp As String = "" 'Se lee el arreglo resultante 'de derecha a izquierda para 'formar la cadena de salida For i = P To 0 Step -1 sTemp += Salida(i) Next 'Ajusta el tammao del arreglo Arr() 'conservando el valor de sus elementos ReDim Preserve Arr(P + 1) Return sTemp End Function End Module

Char en donde se almacenarn los


residuos (convirtindolos con el mtodo

ToString.. N representa el tamao del arreglo


anterior y no afecta a los objetos definidos en la forma de origen (por ser un objeto local dentro de un mdulo.

P es un apuntador a los elementos de


arreglo temporal.

Res es el residuo de la divisin entera (\)


del nmero decimal entre la base.

La funcin BaseN recibe la informacin necesaria para convertir un nmero decimal a su equivalente en binario u octal.

35

Estructuras de datos con microsoft VB.NET


Parmetro Tipo Entero largo Uso El nmero decimal que se va a usar. Se pasa como una copia del valor ingresado en la forma principal (ByVal), por lo tanto el valor original no es afectado. Base a la que se convierte (2 u 8). El arreglo principal de esta aplicacin. Al pasarse por referencia ( ByRef) los cambios que se hagan en afectan al arreglo inicial.

Num

Base Arr()

Entero corto Objeto

Tal funcin se invoca desde la aplicacin principal de esta manera:

Private Sub btnBaseN_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBaseN.Click Dim Numero As Long Dim Base As Short = 2 'Base 2 u 8 Numero = Val(InputBox("Nmero decimal", "Cambio de base", "0")) txtSol.Clear() If Numero > 0 Then ReDim Arreglo(64) 'Tamao inicial del arreglo Dim sCurrSel As String = rbBin.Text If rbOctal.Checked Then Base = 8 sCurrSel = rbOctal.Text End If txtSol.Text = Numero.ToString + " -->" + BaseN(Numero, Base, Arreglo) + " (" + sCurrSel + ")" N = Arreglo.GetUpperBound(0) NumN.Value = N CreaArreglo(False) Else MsgBox("Valor no permitido", MsgBoxStyle.Information) End If End Sub

Ejecucin8 :

Usar la calculadora de Windows en modo cientfico para comprobar sus resultados.

36

Estructuras de datos con microsoft VB.NET

2.- Problema de caracteres. La clase ArrayList El uso de instrucciones ReDim y ReDim Preserve consume recursos de la computadora, adems debe incluirse cdigo cuando debe modificarse el tamao de un arreglo. La solucin a este problema es el uso de un tipo de arreglo que se dimensiona automticamente cuando alcanza su lmite de almacenamiento fsico. Este arreglo se llama ArrayList y forma parte de la coleccin del espacio de nombres en System.Collections en la librera del marco .NET. Un objeto ArrayList tiene la capacidad de almacenar su tamao como una propiedad cuyo valor inicial es 16. Cuando el nmero de elementos en un ArrayList alcanza este lmite, la propiedad Capacidad agrega otros 16 elementos. El uso de un ArrayList en situaciones donde el nmero de elementos puede crecer o disminuir, es ms eficiente que usar comandos Redim o Redim Preserve en arreglos estndar.

Estos son algunos de los mtodos y propiedades que incluye la clase ArrayList:

Add() AddRange Capacity Clear() Contains() CopyTo() Count GetEnnumerator GetRange() IndexOf() Insert

Agrega un elemento a la lista Agrega los elementos de una coleccin al fina de un ArrayList Almacena el nmero de elementos que un ArrayList puede manejar Elimina todos los elementos del ArrayList Determina si un tem especfico existe en el arreglo Copia el ArrayList un segmento de ste a un arreglo Es el nmero de elementos actualmente en la lista Regresa un enumerador para iterar sobre un ArrayList Devuelve un subconjunto del ArrayList como otro ArrayList Devuelve el ndice de la primera ocurrencia de un tem especfico Inserta un elemento en un ndice especificado

37

Estructuras de datos con microsoft VB.NET


InsertRange() Item() Remove() RemoveAt() Reverse() Sort() ToArray() TrimToSize()
Inserta los elementos de una coleccin dentro de un ArrayList comenzando en un ndice especfico Obtiene o establece un elemento en el ndice especificado Elimina la primera ocurrencia de un tem especfico Elimina el elemento con el ndice especificado Invierte el orden de los elementos en el ArrayList Ordena alfabticamente los elementos en ele arreglo Copia los elementos de un ArrayList a un arreglo Fija la capacidad del ArrayList al nmero exacto de sus elementos

Ejemplo uso.- Se desea ayudar al profesor con el manejo de su grupo. Donde se requiere un objeto

Alumno con las siguientes caractersticas:


Alumno (Serializable) Propiedades Nombre Apellido Calif Mtodos MiNombre Apellido + Nombre (Texto) Tipo Texto Texto Entero corto (rango 0 a 100)

La lista del curso es una Coleccin de alumnos que luego se pasa a un ArrayList para su mejor manejo. Crear una clase que agregue algunos mtodos al ArrayList para: Ubicar al primer alumno de la lista con mayor y menor calificacin. Mostrar el promedio general del grupo. Crear una lista de alumnos aprobados y otra de alumnos reprobados y mostrar sus promedios. La forma para esto puede ser como se muestra:

38

Estructuras de datos con microsoft VB.NET

Objetos requeridos (Por secciones): GroupBox (Contenedor GpoAlumno): txtApe =Upper) txtNom (igual a la anterior) NumCalif =100) btnOK (Button). txtLoc (igual las anteriores) btnFind (Button ) (NumericUpDown Maximum (TextBox, CharacterCasing

DGV (DataGridView con tres columnas de las cuales la tercera es numrica sin decimales) btnToArrayList Botones btnSave y btnOpen para serializar y deserializar la coleccin
9

(opcionales).

Francesco Balena. Programming Microsoft Visual Basic 2005: The Languaje. Microft Press.

39

Estructuras de datos con microsoft VB.NET


GroupBox (GpoAL)

DGVAL (DataGridViewCol con dos columnas la ltima de las cuales es numrica sin decimales). DGVR (copia de la anterior). btnMayor btnMenor (Button) (Button)

labProm (Label con BorderStyle = Fixed3D y texto 0.0 alineado a la derecha, AutoSize = False) labProm2 (copia de la anterior).

btnRepro (Button) btnApro (Button) labCalMayot (Label, BorderStyle = Fixed3D, AutoSie =False) labCalMento (copia de la anterior) La ventana de propiedades de un DataGridView se abre con un clic en la esquina superior derecha:

El las

valor

numrico

de

la

columna Calif se establece con propiedades

DefaultCellStyle.

Funcionamiento:

40

Estructuras de datos con microsoft VB.NET


Se crea una coleccin de alumnos10:

Luego se llena un ArrayList con el nombre completo del alumno y su calificacin DGVAL

Se muestra el promedio general del grupo.

El botn Selecciona de la lista anterior aquellos alumnos con calificacin menor a 70 (calificacin reprobatoria y los muestra en DGVR.

10

En este ejemplo no se agregaron botones para edicin o para eliminar algn objeto de la coleccin. Puede

agregarlos si lo desea.

41

Estructuras de datos con microsoft VB.NET

Se muestra el promedio de esta lista.

El botn Hace lo mismo pero para los alumnos que aprobaron el curso (Calif >=70).

CODIGO: Clase Alumno:


<System.Serializable()> Public Class CAlumno Private mvarApellido As String Private mvarNombre As String Private mvarCalif As Short Property Apellido() As String Get Return mvarApellido End Get Set(ByVal value As String) mvarApellido = value End Set

42

Estructuras de datos con microsoft VB.NET


End Property Property Nombre() As String Get Return mvarNombre End Get Set(ByVal value As String) mvarNombre = value End Set End Property Property Calif() As Short Get Return mvarCalif End Get Set(ByVal value As Short) mvarCalif = value End Set End Property Public Function MiNombre() As String Return mvarApellido + " " + mvarNombre End Function End Class

Clase para agregar ms funcionalidad al ArrayList:


Public Class CMiListaArreglo Public Function Promedio(ByRef ElArreglo As ArrayList) As Single Dim Alumno As New CAlumno Dim SumCal As Integer = 0 For Each Alumno In ElArreglo SumCal += Alumno.Calif Next Dim Prom As Single = SumCal / ElArreglo.Count Return Prom End Function Public Function CalifMayor(ByRef ElArreglo As ArrayList) As CAlumno Dim Alumno As CAlumno = Nothing Dim Mejor As CAlumno = Nothing Dim Mayor As Short = 0 For Each Alumno In ElArreglo If Alumno.Calif > Mayor Then Mejor = Alumno Mayor = Alumno.Calif End If Next Return Mejor End Function Public Function CalifMenor(ByRef ElArreglo As ArrayList) As CAlumno Dim Alumno As CAlumno = Nothing Dim Peor As CAlumno = Nothing Dim Menor As Short = 100 For Each Alumno In ElArreglo If Alumno.Calif < Menor Then Peor = Alumno Menor = Alumno.Calif End If Next Return Peor End Function Public Function ListaRep(ByRef ElArreglo As ArrayList) As ArrayList Dim Repro As New ArrayList For Each A As CAlumno In ElArreglo If A.Calif < 70 Then Repro.Add(A) End If Next Repro.TrimToSize() Return Repro End Function

43

Estructuras de datos con microsoft VB.NET


Public Function ListaApro(ByVal ElArreglo As ArrayList) As ArrayList Dim Apro As New ArrayList For Each A As CAlumno In ElArreglo If Not A.Calif < 70 Then Apro.Add(A) End If Next Apro.TrimToSize() Return Apro End Function End Class

Forma (frmArrayList):
Public Class frmArrayList Private ColDeAl As Collection, Alumno As CAlumno Private ElArregloL As ArrayList, ObjetoArr As New CMiListaArreglo Public Sub New() ' Llamada necesaria para el Diseador de Windows Forms. InitializeComponent() ' Agregue cualquier inicializacin despus de la llamada a InitializeComponent(). Dim sRuta As String = My.Application.Info.DirectoryPath + "\Colecciones" If Not My.Computer.FileSystem.DirectoryExists(sRuta) Then My.Computer.FileSystem.CreateDirectory(sRuta) End If 'Solo en caso de implementar serializacin (Filter Archivos binarios (*.bi) SaveFD.InitialDirectory = sRuta OpenFD.InitialDirectory = sRuta End Sub Private Sub frmArrayList_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ElArregloL = New ArrayList ColDeAl = New Collection End Sub

Para agregar alumnos a la coleccin:

Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click On Error GoTo Repetido Alumno = New CAlumno With Alumno .Apellido = txtApe.Text.Trim .Nombre = txtNom.Text.Trim .Calif = NumCalif.Value End With 'El nombre completo del alumno se toma como clave, lo que evita que se dupliquen 'en la coleccin ColDeAl.Add(Alumno, Key:=Alumno.MiNombre) AddToGrid(Alumno, DGV) txtNom.Clear() txtApe.Clear() txtApe.Focus() Exit Sub Repetido: If Err.Number = 457 Then MsgBox("Ese alumno ya est en la coleccin", MsgBoxStyle.Information) Resume Next Else

44

Estructuras de datos con microsoft VB.NET


MsgBox(Err.Description, MsgBoxStyle.Exclamation) End If MsgBox(Err.Description + " " + Err.Number.ToString, MsgBoxStyle.Information) End Sub Para agregar el alumno a un rengln de DGV: Private Sub AddToGrid(ByVal Alumno As CAlumno, ByRef ElGrid As DataGridView) ElGrid.Rows.Add() Dim R As DataGridViewRow = ElGrid.Rows(ElGrid.RowCount - 1) R.Cells(0).Value = Alumno.Apellido R.Cells(1).Value = Alumno.Nombre R.Cells(2).Value = Alumno.Calif End Sub

Copiar la coleccin a un ArrayList

Private Sub btnToArrayL_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnToArrayL.Click If ColDeAl.Count > 0 Then For Each A As CAlumno In ColDeAl ElArregloL.Add(A) ToGrid2(A, DGVAL) Next labProm.Text = ObjetoArr.Promedio(ElArregloL).ToString("N1") End If End Sub

Para colocar el alumno en un rengln de DGVAL:


Private Sub ToGrid2(ByVal A As CAlumno, ByRef ElGrid As DataGridView) ElGrid.Rows.Add() Dim R As DataGridViewRow = ElGrid.Rows(ElGrid.RowCount - 1) R.Cells(0).Value = A.MiNombre R.Cells(1).Value = A.Calif End Sub

Para determinar si un alumno ya est en la coleccin:

Private Sub btnFind_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnFind.Click Try Dim sAlumno As String = txtLoc.Text.Trim If sAlumno.Length > 0 Then If ColDeAl.Contains(sAlumno) Then MsgBox("Ese alumno s est en la coleccin", MsgBoxStyle.Information) Else MsgBox("Ese alumno no est en la coleccin", MsgBoxStyle.Information) End If

45

Estructuras de datos con microsoft VB.NET


End If Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.Information) End Try End Sub

Obtener lista de alumnos reprobados y colocar cada objeto en DGVR:


Private Sub btnRepro_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRepro.Click DGVR.Rows.Clear() If ElArregloL.Count > 0 Then Dim Reprobados As ArrayList = ObjetoArr.ListaRep(ElArregloL) For Each A As CAlumno In Reprobados ToGrid2(A, DGVR) Next labProm2.Text = ObjetoArr.Promedio(Reprobados).ToString("N1") End If End Sub

De la misma manera, la lista de alumnos reprobados.


Private Sub btnApro_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnApro.Click DGVR.Rows.Clear() If ElArregloL.Count > 0 Then Dim Aprobados As ArrayList = ObjetoArr.ListaApro(ElArregloL) For Each A As CAlumno In Aprobados ToGrid2(A, DGVR) Next labProm2.Text = ObjetoArr.Promedio(Aprobados).ToString("N1") End If End Sub

Ejercicio: Modificar la clase

CMiListaArreglo para que maneje diferentes cursos y crear una

aplicacin de Windows que la implemente.

Arreglos de dos dimensiones. Un arreglo de dos dimensiones (matriz) es un objeto (del tipo Array) que tiene N renglones y M columnas. En lgebra lineal una matriz es simplemente un arreglo rectangular de elementos y se dice que su orden es N x M. A(N, M) Y cada elemento se indica por A(i, j) donde 0 < = i < = N y 0 < = j < = M.

a11 a21 A= an1

a12 a22 an2

ain a2n ann

46

Estructuras de datos con microsoft VB.NET


Por ejemplo:

En VB.NET para crear arreglos con dos dimensiones se usa la instruccin Dim Matriz( , ) para su manejo dinmico. Una vez conocidos N y M se forma el arreglo:

Dim Matriz(N M, ) As [Tipo] crea una matriz A(N, M) en donde (al igual que en los arreglos de una
dimensin) el primer rengln y la primera columna tienen el ndice 0. As: N=3 y M = 3 0 0 1 2 1 1 1 1 5 0 1 2 2 2 2

Manejo de matrices en VB.NET. Crear un proyecto nuevo y cargar el mdulo desarrollado anteriormente:

Men Proyecto Agregar elemento existente (localizarlo en la carpeta \WinArreglos).

Forma principal (frmMatrix)

47

Estructuras de datos con microsoft VB.NET

Elementos de la forma:

GroupBox (GpoH) sin texto (Text).


Controles forma modificando luego sus propiedades Name a NumM y NumK. Propiedades del control numricos NumN. numricos

(NumericIpDown) de nombre NumN. Crear primero este control y despus copiarlo y pegarlo en la

Propiedad Maximum Minimum TextAlign

Valor 10 2 Center

48

Estructuras de datos con microsoft VB.NET

Tres objetos del tipo DataGridViw en donde primero se agrega el primero con el nombre DGVA, se establecen sus propiedades como se indica en la tabla. Luego se copia (al portapapeles) y se pega modificando sus nombres a DGVB y DGVR. ste ltimo cambia su propiedad ReadOnly

True.

Propiedades comunes de los controles DataGridView. Propiedad AllowUserToAddRows AllowUserToResizeRows AutCellsColumnMode MultiSelect Tag11 Valor False False AllCells False En esta ventana se podrn probar

diferentes algoritmos que muestran el manejo de este tipo de arreglos. Se podrn guardar en archivos y recuperarse

en otro momento. A para DGVA, B para DGVB Esta forma manejar tres matrices: btnSuma btnProd btnInvA A[N, M), B([M, K) y R[ , ] cuyo orden depender del resultado de la operacin que se realice. Suma Multiplicacin Inversa Otros problemas a resolver.

GroupBox
Name = GpoOp Enabled = False

btnGuardar btnAbrir

11

Sin comillas.

49

Estructuras de datos con microsoft VB.NET


btnClose

Operaciones con matrices. Suma de dos matrices (A + B).- Esta operacin slo est definida para matrices del mismo orden, esto es, con el mismo nmero de renglones y columnas y genera otra matriz (la suma) del mismo orden. Cada elemento de la matriz resultante se obtiene por:

Por ejemplo:
12

Es decir, cada elemento de la suma se obtiene sumando los elementos correspondientes en A y B en sus respectivas posiciones. Producto de dos matrices A x B. El producto de dos matrices A y B slo est definido si el nmero de renglones de B es igual al nmero de columnas de A.

En donde cada elemento de R se obtiene por:

Por ejemplo:

Funcionalidad de la forma: En todos los problemas desarrollados a lo largo de este texto se guardarn los datos en archivos que se localizarn siempre en una carpeta especialmente creada dentro del directorio donde reside

12

Es matriz resultante.

50

Estructuras de datos con microsoft VB.NET


la aplicacin. Con el fin agilizar este procedimiento se crea en el mdulo para de esta manera usarlo en otras aplicaciones.
Public Function SetTestPath(ByVal sRuta As String) As String sRuta = My.Application.Info.DirectoryPath + sRuta + My.Application.Info.ProductName If Not My.Computer.FileSystem.DirectoryExists(sRuta) Then My.Computer.FileSystem.CreateDirectory(sRuta) End If Return sRuta End Function

Cdigo inicial de la forma:


Public Class frmMatrix Private MatA(,), MatB(,), MatR(,) As Single Private N, M, K As Short Private Sub frmMatrix_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim Ruta As String Ruta = SetTestPath("\Archivos de Prueba_") SaveFD.InitialDirectory = Ruta OpenFD.InitialDirectory = Ruta End Sub

El siguiente procedimiento ajusta las propiedades de los controles de datos (DataGridView) para usarlos tanto pata ingresar los datos de las matrices A y B como para mostrar resultados en R: El procedimiento CreaGrid recibe por referencia13 el control que se va modificar (DataGridView) as como el nmero de renglones y columnas requeridos; Se pasan como parmetros como ElGrid ,

iRows,e iCols. De esta manera opera sobre los controles DGVA, DGVB y DGVR.
El procedimiento VerMatriz cualquier matriz (LaMatriz) en uno de los DatagridView (ElGrid) de la forma.
Private Sub CreaGrid(ByRef ElGrid As DataGridView, ByVal iRows As Short, ByVal iCols As Short) With ElGrid .RowCount = iRows .ColumnCount = iCols For Each Kol As DataGridViewColumn In ElGrid.Columns Kol.HeaderText = Kol.Index Kol.DefaultCellStyle.Alignment = DataGridViewContentAlignment.TopCenter Next End With End Sub Private Sub VerMatriz(ByRef LaMatriz(,) As Single, ByRef ElGrid As DataGridView) Dim i, j As Short For i = 0 To LaMatriz.GetUpperBound(0) 'Limite de renglones For j = 0 To LaMatriz.GetUpperBound(1) 'Limite de columnas ElGrid.Rows(i).Cells(j).Value = LaMatriz(i, j) Next Next End Sub

13

Esto es, los cambios hechos en el procedimiento afectan al control en la forma.

51

Estructuras de datos con microsoft VB.NET


Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click N = NumN.Value M = NumM.Value K = NumK.Value ReDim MatA(N - 1, M - 1), MatB(M - 1, K - 1) CreaGrid(DGVA, N, M) CreaGrid(DGVB, M, K) VerMatriz(MatA, DGVA) VerMatriz(MatB, DGVB) GpoOp.Enabled = True End Sub

Private Sub btnNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNew.Click 'Prepara la forma para otras matrices DGVA.RowCount = 0 DGVA.ColumnCount = 0 DGVB.RowCount = 0 DGVB.ColumnCount = 0 DGVR.RowCount = 0 DGVR.ColumnCount = 0 GpoOp.Enabled = False ReDim MatA(0, 0), MatB(0, 0), MatR(0, 0) End Sub

Hasta este punto, al ejecutar la aplicacin debe verse as al hacer clic en [Aceptar]:

Validacin de los datos de entrada: Todo valor ingresado debe ser numrico. El procedimiento de evento opera sobre DGVA y/o DGVB y asigna el valor ingresado a la matriz que representa (A B).
Private Sub DGVA_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DGVA.CellEndEdit _ , DGVB.CellEndEdit Dim ElGrid As DataGridView = sender If Not IsNumeric(ElGrid.CurrentCell.Value) Then MsgBox("Valor no permitido", MsgBoxStyle.Exclamation) ElGrid.CurrentCell.Value = 0

52

Estructuras de datos con microsoft VB.NET


ElseIf ElGrid.Tag = "A" Then MatA(e.RowIndex, e.ColumnIndex) = ElGrid.CurrentCell.Value Else MatB(e.RowIndex, e.ColumnIndex) = ElGrid.CurrentCell.Value End If End Sub

Procedimientos para guardar y abrir matrices (en y desde archivos).- Las matrices pueden almacenarse tambin en archivos secuenciales. Ya que el cdigo necesario para guardar las matrices A y B es repetitivo, se crea un procedimiento comn:
Private Sub SaveMatrix(ByRef LaMatriz(,) As Single, ByVal NA As Short) Dim i, j As Short For i = 0 To LaMatriz.GetUpperBound(0) For j = 0 To LaMatriz.GetUpperBound(1) PrintLine(NA, LaMatriz(i, j)) Next Next End Sub

Entonces

Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click Try If SaveFD.ShowDialog = Windows.Forms.DialogResult.OK Then Dim NA As Short = FreeFile() FileOpen(NA, SaveFD.FileName, OpenMode.Output) 'Primero se almacena el orden de la matriz PrintLine(NA, N) PrintLine(NA, M) PrintLine(NA, K) 'Luego cada matriz en recorrido por renglones SaveMatrix(MatA, NA) SaveMatrix(MatB, NA) FileClose(NA) MsgBox("Matrices guardadas", MsgBoxStyle.Information) End If Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.Information) FileClose() End Try End Sub

Private Sub btnAbrir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAbrir.Click Try Dim i, j As Short If OpenFD.ShowDialog = Windows.Forms.DialogResult.OK Then Dim NA As Short = FreeFile() FileOpen(NA, OpenFD.FileName, OpenMode.Input) 'Leer el orden de las matarices N = LineInput(NA) M = LineInput(NA) K = LineInput(NA)

53

Estructuras de datos con microsoft VB.NET


NumN.Value = N NumM.Value = M NumK.Value = K 'Crear arreglos ReDim MatA(N - 1, M - 1), MatB(M - 1, K - 1) CreaGrid(DGVA, N, M) CreaGrid(DGVB, M, K) 'Leer elementos de A For i = 0 To MatA.GetUpperBound(0) For j = 0 To MatA.GetUpperBound(1) MatA(i, j) = LineInput(NA) Next Next 'Leer elementos de B For i = 0 To MatB.GetUpperBound(0) For j = 0 To MatB.GetUpperBound(1) MatB(i, j) = LineInput(NA) Next Next VerMatriz(MatA, DGVA) VerMatriz(MatB, DGVB) FileClose(NA) GpoOp.Enabled = True End If Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.Information) FileClose() End Try End Sub

Probar con diferentes valores en diferentes matrices estos procedimientos. Suma de A + B: Con el fin de generalizarlo y poder usarlo en otras aplicaciones, este procedimiento se crea en el mdulo:
Public Sub SumaAB(ByRef A(,) As Single, ByRef B(,) As Single, ByRef R(,) As Single) Dim i, j As Short For i = 0 To A.GetUpperBound(0) For j = 0 To A.GetUpperBound(0) R(i, j) = A(i, j) + B(i, j) Next Next End Sub

Todas las matrices se pasan por referencia para que los cambios en ellas se reflejen en la ventana desde donde se invoca el procedimiento. En la forma principal:

Private Sub btnSuma_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSuma.Click ReDim MatR(N - 1, M - 1) SumaAB(MatA, MatB, MatR) CreaGrid(DGVR, N, M) VerMatriz(MatR, DGVR) End Sub

Prueba:

54

Estructuras de datos con microsoft VB.NET

Producto A x B. Al igual que la suma, este procedimiento se crea en el mdulo para su uso en el futuro.
Public Sub ProdAB(ByRef A(,) As Single, ByRef B(,) As Single, ByRef R(,) As Single) Dim i, j, c As Short For i = 0 To A.GetUpperBound(0) For c = 0 To B.GetUpperBound(1) For j = 0 To A.GetUpperBound(1) R(i, c) += A(i, j) * B(j, c) Next Next Next End Sub

Y se invoca desde la aplicacin como:

Private Sub btnProd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnProd.Click ReDim MatR(N - 1, K - 1) ProdAB(MatA, MatB, MatR) CreaGrid(DGVR, N, K) VerMatriz(MatR, DGVR) End Sub

55

Estructuras de datos con microsoft VB.NET

Problemas: 1.- Transpuesta. La transpuesta de una matriz se obtiene intercambiando renglones por columas:

Su transpuesta es:

Desarrollar un procedimiento que encuentre la transpuesta de una matriz A.

2.- La inversa de una matriz A(N, M) en donde N = M y denotada como A -1 es una matriz del mismo orden tal que:

56

Estructuras de datos con microsoft VB.NET


En donde I representa a la matriz unidad (cuyos elementos en la diagonal principal tienen el valor de 1 y todos los dems son 0. Ejemplo:

Investigar diferentes mtodos para encontrar la inversa de una matriz A. Implementar uno en el Mdulo. La inversa (si existe) debe guardarse en el arreglo B, de manera que se pueda verificar por medio del producto AxB.

57

Estructuras de datos con microsoft VB.NET


Private Sub btnInvA_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnInvA.Click If N = M Then ReDim MatR(N - 1, M - 1) CreaGrid(DGVR, N, N) 'Procedimiento a desarrollar: InversaA(MatA, MatB, MatR) VerMatriz(MatB, DGVB) End If End Sub

3.- Aplicaciones: Modelo de Regresin Lineal Mltiple. En estadstica, cuando se considera que el resultado de alguna variable (Y) depende del valor de otros valores (X j) es posible desarrollar un modelo que explique esa relacin. El modelo ms sencillo se conoce como el modelo de regresin lineal mltiple. Definido como:

Y un mtodo muy efectivo para obtener esta ecuacin a partir de un conjunto de observaciones (en algn experimento) es usando matrices: Ejemplo: Se tienen los siguientes datos (observados): Y 3 1 8 3 5 X1 3 1 5 2 4 X2 5 4 6 4 6

El mtodo14 consiste en crear una matriz X con los datos Xi,j agregando una columna inicial cuyos valores sern siempre 1. Matriz X: 1 1 1 1 1 3 1 5 2 4 5 4 6 4 6

14

Econometric Methods. J. Johnston. McGrawHill.

58

Estructuras de datos con microsoft VB.NET


Y un arreglo Y(N): 3 1 8 3 5

Luego se obtiene la matriz XX de multiplicar XtX:

Luego el vector Xy de Xt Y:

Las ecuaciones normales son entonces:

Si XX-1 es la inversa de XX, entonces:

Y la ecuacin resultante es:

59

Estructuras de datos con microsoft VB.NET


A partir de la cual se puede estimar Yc conociendo cualesquiera valores de X 1 y X2. Desarrollar un programa15 cuya entrada sea: N= N de observaciones (y, x1, , xm) M = N de variables independientes Xj Y su salida es la ecuacin de regresin resultante: Sugerencia.- Esta forma permite capturar los datos de M variables independientes y los valores de Y. Al mismo tiempo crea los arreglos necesarios y los llena en tiempo de ejecucin cada vez que se ingresa un dato. El programa hace un uso intensivo de varios arreglos tanto bidimensionales como unidimensionales. Utiliza adems los mtodos de multiplicacin de matrices, clculo de transpuesta y de inversa de matrices desarrollados (y probados) en el programa anterior.

Descripcin de la forma: El proyecto de denomin RegresinLinealMultiple, la forma de denomin frmRLM y se import el mdulo ModMisMetodos desarrollado en la aplicacin previa.

Dos controles numricos (NumericUpDow) denominados NumN y

NumM respectivamente con valores Minimum = 5, Maximum =

15

Llevar a este programa al mdulo con las operaciones de multiplicacin, inversa de una matriz desarrollado

en el programa anterior.

60

Estructuras de datos con microsoft VB.NET


10 para el primero y 1 y 10 para el segundo. Adems un botn (btnOK). Control DataGridView: Nombre= DGV AllowUserToAddRows = False AllowUserToReziseRows False AutoSizeColumnMode AllCells MultiSelect = False Aqu se capturan los datos. = =

Control DataGridView: Nombre= DGVX Mismas propiedades que el anterior ms ReadOnly = True Muestra el arreglo X.

Control DataGridView: Nombre = DGVY Propiedades iguales al anterior. Muestra el vector Y.

61

Estructuras de datos con microsoft VB.NET


Controles DataGridView. Los dos primeros son copia de DGVX, los ltimos dos se copian de DGVY. Sus nombres son: DGVXX (muestra el arreglo XX), DGVInv (muestra la inversa de XX), DGVXy (muestra el arreglo XY) y DGVB (para mostrar los resultados el vector B.

Es un TextBox con nombre txtEc, TextAlign = Center y ReadOnly = True. Sirve para mostrar la ecuacin resultante.

1. 2. 3. 4.

btnArreglos.- Muestra los valores de los arreglos X y Y. (Enabled = False). btSave.- Guarda los datos iniciales (los arreglos X y Y). Enabled = False btnOpen.- Recupera el archivo de datos. btnNew.- Prepara la forma para nuevos datos. btnStart.- Inicia el proceso de clculos. Enabled = False. btnClose.

Dilogos para guardar y abrir archivos: DefaultExt = dat, Filter = Archivos de datos (*.dat)|*.dat. Con los nombres que aparecen en la imagen.

Operacin: Se ingresa el nmero de datos observados y el total de variables x. 5 observaciones con dos variables X. Al aceptar se crean los arreglos iniciales y se preparan los DataGridView: Se asignan los valores de 1 en la primera colimna (que adems se establece como slo lectura). Aqu se capturan los datos.

62

Estructuras de datos con microsoft VB.NET

Cuando los datos son ingresados stos son asignado a los arreglos X Y usando el evento CellEndEdit. As, cuando se selecciona se mostrarn los

arreglos X y Y en sus respectivos DataGridView:

Se declaran loa arreglos ms importantes y el constructor de la forma, crea un directorio por defecto para guardar datos:
Public Class frmRLM Private X(,), XX(,) As Single Private Y(), XY(), B() As Single Private N, M As Integer Public Sub New() ' Llamada necesaria para el Diseador de Windows Forms. InitializeComponent() ' Agregue cualquier inicializacin despus de la llamada a InitializeComponent(). Dim sRuta As String = My.Application.Info.DirectoryPath + "\RLM" If Not My.Computer.FileSystem.DirectoryExists(sRuta) Then My.Computer.FileSystem.CreateDirectory(sRuta) End If SaveFD.InitialDirectory = sRuta OpenFD.InitialDirectory = sRuta End Sub

Aqu se dimensionan algunos de los arreglos y se forman los DataGridView para visualizarlos y para capturar los datos:
Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click With DGV N = NumN.Value M = NumM.Value .RowCount = N .ColumnCount = M + 2 ReDim X(N - 1, M), Y(N - 1) Dim i, j As Integer For i = 0 To X.GetUpperBound(0) X(i, 0) = 1 Next For j = 0 To DGV.ColumnCount - 2 .Columns(j).HeaderText = "X" + j.ToString .Columns(j).DefaultCellStyle.Alignment = DataGridViewContentAlignment.TopRight

63

Estructuras de datos con microsoft VB.NET


Next .Columns(j).HeaderText = "Y" .Columns(j).DefaultCellStyle.Alignment = DataGridViewContentAlignment.TopRight .Columns(0).ReadOnly = True End With DGVX.RowCount = N DGVX.ColumnCount = M + 1 DGVY.RowCount = N DGVY.ColumnCount = 1 btnArreglos.Enabled = True VerArreglos() End Sub

Cuando se tienen los arreglos iniciales, pueden guardarse: Los datos se almacenan en un archivo secuencial en e siguiente orden: 1. 2. 3. Valores de N y M. El arreglo X. El arreglo Y.

Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click If SaveFD.ShowDialog = Windows.Forms.DialogResult.OK Then Try Dim NA As Short = FreeFile() FileOpen(NA, SaveFD.FileName, OpenMode.Output) PrintLine(NA, N) PrintLine(NA, M) Dim i, j As Integer For i = 0 To X.GetUpperBound(0) 'se omite la 1a columna For j = 0 To X.GetUpperBound(1) PrintLine(NA, X(i, j)) Next Next For i = 0 To Y.GetUpperBound(0) PrintLine(NA, Y(i)) Next FileClose(NA) MsgBox("Arreglos guardados", MsgBoxStyle.Information) Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.Exclamation) FileClose() End Try End If End Sub

Los datos se leen en la misma secuencia en que se guardaron y se invoca al procedimiento del botn Aceptar para crear los arreglos y formar los DataGridView iniciales. Al leer los datos, stos son asignados a sus arreglos y mostrados en DataGridView de datos (DGV).
Private Sub btnOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpen.Click If OpenFD.ShowDialog = Windows.Forms.DialogResult.OK Then Dim NA As Short = FreeFile() FileOpen(NA, OpenFD.FileName, OpenMode.Input) N = LineInput(NA)

64

Estructuras de datos con microsoft VB.NET


M = LineInput(NA) NumN.Value = N Crea los arreglos y forma los NumM.Value = M DataGridVew iniciales. btnOK.PerformClick() Dim i, j As Short For i = 0 To X.GetUpperBound(0) For j = 0 To X.GetUpperBound(1) X(i, j) = LineInput(NA) DGV.Rows(i).Cells(j).Value = X(i, j) Next Next For i = 0 To Y.GetUpperBound(0) Y(i) = LineInput(NA) DGV.Rows(i).Cells(DGV.ColumnCount - 1).Value = Y(i) Next FileClose(NA) Muestra los btnArreglos.PerformClick() End If arreglos. End Sub

Private Sub btnArreglos_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnArreglos.Click VerArreglo(DGVX, X) VerVector(DGVY, Y) btnSave.Enabled = True btnStart.Enabled = True End Sub Private Sub VerArreglo(ByRef ElGrid As DataGridView, ByRef Arreglo(,) As Single) Dim i, j As Integer For i = 0 To Arreglo.GetUpperBound(0) For j = 0 To Arreglo.GetUpperBound(1) ElGrid.Rows(i).Cells(j).Value = Arreglo(i, j) Next Next End Sub Private Sub VerVector(ByRef ElGrid As DataGridView, ByRef MiArr() As Single) Dim i, j As Integer For i = 0 To MiArr.GetUpperBound(0) ElGrid.Rows(i).Cells(0).Value = MiArr(i) Next End Sub

Inicia todos los procedimientos enfocados a resolver el problema: Obtener la ecuacin de ajuste. 1. 2. 3. 4. 5. 6. Crea la transpuesta de X. La multiplica por X y por Y para obtener XX y Xy. Obtiene la inversa de XX. Multiplica la inversa por el arreglo Xy para obtener el arreglo de resultados, B. Forma los DatagridVew necesarios para mostrar resultados intermedios y el resultado final el arreglo B. Obtiene la ecuacin resultante.

65

Estructuras de datos con microsoft VB.NET

Se asume que los procedimientos utilizados ya fueron creados y probados en la aplicacin anterior. En caso de que falte alguno (por ejemplo la multiplicacin de un arreglo de dos dimensiones por uno de una un vector, habr que desarrollarlo en ese mdulo - ProdMatArr(InvXX, XY, B) Realiza la multiplicacin de la inversa de XX por el vector XY y el resultado lo coloca en B.
Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click 'Transpuesta: Dim XT(M - 1, N - 1) As Single ReDim XX(M, M) Dim InvXX(M, M) As Single ReDim B(M) TranspuestaA(X, XT) 'Producto Transpuesta * arreglo X para obtener XX. ProdAB(XT, X, XX) ReDim XY(M) 'Transpuesta * Y para obtener Xy ProdMatArr(XT, Y, XY) DGVXX.RowCount = M + 1 DGVXX.ColumnCount = M + 1 DGVInv.RowCount = M + 1 DGVInv.ColumnCount = M + 1 'Clculo de la inversa de XX. InversaA(XX, InvXX) VerArreglo(DGVXX, XX) VerArreglo(DGVInv, InvXX) DGVXy.RowCount = M + 1 DGVXy.ColumnCount = 1 DGVB.ColumnCount = 1 DGVB.RowCount = M + 1 'Producto de Inversa * XY para obtener el arreglo B ProdMatArr(InvXX, XY, B) VerVector(DGVXy, XY) VerVector(DGVB, B) 'Mostrar el resultado. ShoResult() End Sub Private Sub ShoResult() Dim sEc As String = "Yc = " + B(0).ToString("N2") Dim i As Short For i = 1 To B.GetUpperBound(0) If Math.Sign(B(i)) = 1 Then sEc += " + " End If sEc += B(i).ToString("N2") + "X" + i.ToString Next txtEc.Text = sEc End Sub

Si se completa esta aplicacin, la competencia especfica de esta unidad queda suficientemente acreditada.

66

Estructuras de datos con microsoft VB.NET

2 Recursividad.
Competencia especifica.- Comprender y aplicar la recursividad como herramienta de programacin en el manejo de las estructuras de datos.
DEFINICIN.- Se denomina recursividad a la capacidad de un procedimiento de llamarse a s mismo. Es el nombre que se da a la tcnica de definir un conjunto o un proceso en trminos de s mismo 16. La funcin factorial cuyo dominio son los nmeros naturales puede ser definida recursivamente como:

En donde Factorial(N) est definida en trminos de Factorial(N-1) que luego se vuelve en trminos de Factorial(N-2), etc., hasta que finalmente se alcanza Factorial (0) y su valor es entonces 1. Una definicin recursiva de un conjunto de procesos debe contener una definicin explcita para los valores particulares de sus argumentos de otro modo la definicin podra nunca converger. La idea bsica es definir una funcin para todos sus argumentos de una manera constructiva usando induccin. El valor de una funcin para un valor especfico de su argumento puede calcularse en un nmero finito de pasos usando la definicin recursiva donde en cada paso de la recursin se acerca ms a la solucin. Ejemplo 1:

Imports System.Console Module Module1 Sub Main() ForegroundColor = ConsoleColor.Black BackgroundColor = ConsoleColor.White Clear() Dim N As Integer, F As Long Write("N = ") N = ReadLine()

16

Jean-Paul Tremblay. An Introduction to Data Structures with applications. McGrawHill.

67

Estructuras de datos con microsoft VB.NET


F = Factorial(N) Write("Factorial = ") WriteLine(F) ReadKey() End Sub Private Function Factorial(ByVal N As Integer) As Long If N = 0 Then Factorial = 1 Else Factorial = N * Factorial(N - 1) End If End Function End Module

Este tipo de recursin de conoce como funcin definida recursivamente ( funciones recursivas

primitivas). Un segundo tipo de recursin es el uso recursivo de un procedimiento (recursin no primitiva). Un ejemplo de esta recursin es la funcin de Ackerman, la cual se define como 1:

Ejemplo 2.

Imports System.Console Module Module1 Sub Main() BackgroundColor = ConsoleColor.White ForegroundColor = ConsoleColor.Black Clear() Dim N, M As Short Write("N =") N = ReadLine() Write("M = ") M = ReadLine() Write("Valor de la funcin A =") WriteLine(Ackerman(M, N)) ReadKey() End Sub Private Function Ackerman(ByVal M As Short, ByVal N As Short) As Integer If M = 0 Then Ackerman = N + 1 ElseIf N = 0 Then Ackerman = Ackerman(M - 1, 1) Else

68

Estructuras de datos con microsoft VB.NET


Ackerman = Ackerman(M - 1, Ackerman(M, N - 1)) End If End Function End Module

Usar valores en el rango 0 3 para M y de 0 5 para N para evitar desbordamiento.

Ejemplo 3. Escribir una funcin recursiva para convertir enteros decimales a su representacin en otra base (B) por medio de divisiones sucesivas. El nombre de esta funcin debe ser CONVERT con dos parmetros formales Nmero y Base donde el primero denota al entero que se va a convertir y el segundo es la base. El resultado se regresa como una cadena (texto). Por ejemplo, para encontrar la representacin en base 6 de 184 implica que se dividir repetidamente entre 6 y los residuos obtenidos son concatenados: 184 6 4 306 0
56 5 El resultado es entonces 504

MaximizeBox = False

69

Estructuras de datos con microsoft VB.NET


Objeto TextBox NumericUpDown Button Button Label Propiedades Name = txtNum, TextAlign = Center, Text =0 Name = NumB, Maximum =9, TextAlign =Center Name = btnConvert Name = btnNew Name = labResult, BorderStyle = Fixed3D, BackColor = Honeydew, TextAlign = TopCenter. Inicia el clculo. Nuevo cmputo. Minimum =2, Descripcin Captura el nmero a convertir La base.

Public Class frmConvert Private Numero, Base As Integer Private Sub btnConvert_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConvert.Click If IsNumeric(txtNum.Text) Then Numero = CInt(txtNum.Text) Base = NumBase.Value labResult.Text = StrReverse(Convert(Numero, Base)) End If End Sub Private Function Convert(ByVal N As Integer, ByVal B As Integer) As String Dim Cociente, Residuo As Integer Cociente = Math.DivRem(N, B, Residuo) If Cociente > 0 Then Convert = Residuo.ToString + Convert(Cociente, Base) Else Convert = (N Mod B).ToString End If End Function Private Sub btnNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNew.Click txtNum.Clear() labResult.Text = "" txtNum.Focus() End Sub End Class

Ejercicios: 1.- El mximo comn divisor de dos enteros se define como (Algoritmo de Euclides):

Donde MOD (m, n) es el mdulo aritmtico17, esto es, el residuo de dividir m n. Escribir la funcin recursiva para este caso.

17

En VB.NET esta operacin puede ejecutarse como m Mod n.

70

Estructuras de datos con microsoft VB.NET


El mximo comn divisor de 27 y 9 es 9. Por ejemplo.

2.- Escribir una funcin recursiva para calcular la raz cuadrada de un nmero. Leer una tripleta de de nmeros N, A y E, donde N es el nmero para el cual debe encontrarse la raz cuadrada, A es una aproximacin de la raz cuadrada y E es el error permitido en el resultado.

Usar las siguientes tripletas de nmeros para pruebas: N 2 3 8 225 A 1.0 1.5 2.5 14.2 E 0.001 0.001 0.001 .001

3.- En muchas aplicaciones es necesario conocer el nmero de particiones diferentes de un entero N dado, es decir, de cuantas formas diferentes se puede expresar a N como una suma de sumandos enteros. Si se denota como QMN al nmero de formas en las cuales un entero M puede ser expresado como una suma, cada uno de estos sumandos no es mayor que N, particiones de N pude definirse en trminos de la siguiente funcin: entonces el nmero de

71

Estructuras de datos con microsoft VB.NET


Escribir una funcin recursiva y usar los valores N = 3, 4, 5 y 6 como datos.
El nmero 5 se puede expresar de tres maneras con sumandos no mayores que 2.

72

Estructuras de datos con microsoft VB.NET

3 Estructuras Lineales.
Competencia especifica.- Conocer, Identificar y aplicar as estructuras no lineales en la solucin de problemas del mundo real.
LISTAS. Lista Ligada Simple.- Coleccin de una clase de objetos llamados nodos. Cada nodo est ligado a su nodo sucesor en la lista usando una referencia (apuntador). Un nodo consiste en un campo para almacenar datos y el campo para la referencia del nodo (apuntador liga).

Encabezado

Alicia

Juan

Olga

Nada

El arreglo es la estructura natural que se usa cuando se trabaja con listas. Los arreglos proporcionan un acceso rpido a los elementos almacenados y se puede iterar fcilmente sobre ellos. No obstante, el arreglo no es la estructura perfecta ya que la bsqueda de un tem en un arreglo desordenado puede tomar tiempo ya que deben visitarse cada uno de lo elementos del arreglo. Los arreglos ordenados son mucho ms eficientes para las bsquedas, pero las inserciones y remociones toman ms tiempo porque deben cambiarse los elementos hacia arriba hacia abajo para obtener el espacio para una insercin o eliminar espacio en una remocin. Adems en un arreglo ordenado debe buscarse el espacio apropiado para insertar un elemento. La mayor diferencia entre un arreglo y una lista ligada es que mientras que en arreglo los elementos se referencian por su posicin (un ndice) los elementos de una lista ligada lo hace por una referencia (apuntador) a otros elementos en el arreglo, as se dice que Juan sigue de Alicia y no que Juan est en la segunda posicin. Moverse a travs de una lista ligada involucra seguir las ligas desde el principio hasta el final (nodo inicial, nodo final). Adems las listas son marcadas al final apuntando a un valor especial que se llama Nothing (nada). Dado que se trabaja con clases de objetos en memoria, se utiliza el objeto equivalente nulo Nothing, para denotar el final de una lista. Tambin es recomendable marcar el inicio de una lista con un nodo llamado encabezado (Header). La insercin en una lista ligada se vuelve muy eficiente ya que todo lo que implica es cambiar la liga del nodo previo al nodo insertado y establecer la liga del nodo nuevo al punto que el nodo previo apuntaba antes de la insercin.

73

Estructuras de datos con microsoft VB.NET


Header Alicia Juan Olga Nothing

Carolina

La remocin de un nodo es igualmente sencilla ya que implica direccionar la liga del nodo antes de removerlo al nodo que apunta actualmente y establecer la liga del nodo removido a Nothing.

Header

Alicia

Juan

Carolina

Olga

Nothing

Listas Ligadas Orientadas a Objetos. La clase Nodo: Un nodo est compuesto de dos datos miembros. Elemento que almacena el dato del nodo y Liga que almacena la referencia al siguiente nodo. Puesto que se puede usar el tipo de dato Object para el tipo de dato de Elemento no importar que clase de dato sea almacenado en la lista18. Proyecto MDI para Estructuras Lineales: Es la aplicacin (Windows) en donde se analizarn las estructuras lineales Listas, Pilas y Colas. La forma inicial es un contenedor MDI. Nombre MDIELineales, propiedad IsMDIContainer = True con un men como el que se muestra enseguida y un mdulo llamado ModEL.

18

Michael McMillan. DataStructures and Algorithms Using Visual Basic .NET. Cambridge.

74

Estructuras de datos con microsoft VB.NET

Luego se crea la clase Nodo.

La clase Lista Ligada: Esta clase incluye algunos mtodos para agregar o remover nodos en la lista, recorrer la lista y encontrar un nodo en particular. Tambin se requiere un constructor que instancie una lista. El nico miembro dato en una lista en la clase es el nodo de encabezado (Header).

Public Class CNodo Public Elemento As Object Public Liga As CNodo Public Sub New() Elemento = Nothing Liga = Nothing End Sub 'Sobrecarga Public Sub New(ByVal ElElemento As Object) Elemento = ElElemento Liga = Nothing End Sub End Class

75

Estructuras de datos con microsoft VB.NET


Public Class CListaLigada Private mvarHeader As CNodo Property Header() As CNodo Get Return mvarHeader End Get Set(ByVal value As CNodo) mvarHeader = value End Set End Property Public Sub New() Header = New CNodo("Header") End Sub Private Function Buscar(ByVal Item As Object) As CNodo Dim Actual As New CNodo Actual = Header If Not Actual.Liga Is Nothing Then Do While (Actual.Elemento <> Item) Actual = Actual.Liga Loop End If Return Actual End Function Public Sub Insertar(ByVal ItemNuevo As Object, ByVal DespuesDe As Object) Dim Actual As New CNodo Actual = Header Dim NodoNuevo As New CNodo(ItemNuevo) Actual = Buscar(DespuesDe) NodoNuevo.Liga = Actual.Liga Actual.Liga = NodoNuevo End Sub Private Function BuscarPrevio(ByVal x As Object) As CNodo Dim Actual As CNodo = Header Dim Prev As CNodo = Header Do While Not (Actual.Liga Is Nothing) And Actual.Elemento <> x Prev = Actual Actual = Actual.Liga Loop Return Prev End Function Public Sub Remover(ByVal x As Object) Dim P As CNodo = BuscarPrevio(x) If Not P.Liga Is Nothing Then P.Liga = P.Liga.Liga End If End Sub Public Sub VerLista(ByRef ListaO As ListBox) Dim Actual As New CNodo Actual = Header ListaO.Items.Clear() Do While Not Actual.Liga Is Nothing ListaO.Items.Add(Actual.Liga.Elemento) Actual = Actual.Liga Loop End Sub 'Esto es evaluacin y no pasa al texto del libro: Public Function CuentaItems() As Integer Dim Actual As New CNodo Dim Cuenta As Integer = 0 Actual = Header Do While Not Actual.Liga Is Nothing Cuenta += 1 Actual = Actual.Liga Loop Return Cuenta End Function Public Sub Cambiar(ByVal x As Object, ByVal y As Object) 'Buscar a X: Dim Actual As CNodo = Header Do While Not (Actual.Liga Is Nothing) And Actual.Elemento <> x Actual = Actual.Liga

76

Estructuras de datos con microsoft VB.NET


Loop Actual.Elemento = y End Sub End Class

Ejemplo de implementacin: Agregar al proyecto actual una forma:

77

Estructuras de datos con microsoft VB.NET

Objeto inters TextBox Button ListBox Button Button Button Button Button Label

de

Propiedades Name = txtDato Name = btnInserta Name = LaLista Name=btnRemove Name=New Name=btnSave Name=btnOpen Name=btnClose Name=labTL Name=SaveFD, (*.dat)|*.dat DefaultExt=dat Filter=Archivo de datos

Descripcin Captura de datos Insertar el dato en la lista Desplegar la lista actual Quita el elemento seleccionado de la lista. Prepara una lista nueva Guarda la lista actual Abre una lista Cierra la ventana Para mostrar el total de elementos en la lista.

OpenFileDialog

Ubicacin del archivo a crear.

SaveFileDialog

Name=SaveFD e iguales propiedades que el anterior.

Selecciona almacenada.

una

lista

Public Class frmListaSimple Public oLista As New CListaLigada Public oActual As Object Public Sub New() ' Llamada necesaria para el Diseador de Windows Forms. InitializeComponent() ' Agregue cualquier inicializacin despus de la llamada a InitializeComponent(). Dim sRuta As String = My.Application.Info.DirectoryPath + "\ListaLigadaS" If Not My.Computer.FileSystem.DirectoryExists(sRuta) Then My.Computer.FileSystem.CreateDirectory(sRuta) End If SaveFD.InitialDirectory = sRuta OpenFD.InitialDirectory = sRuta End Sub Private Sub frmListaSimple_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load oActual = oLista.Header End Sub Private Sub btnInserta_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnInserta.Click Dim Item As Object If txtDato.Text.Trim.Length > 0 Then Item = txtDato.Text oLista.Insertar(Item, oActual) oActual = Item VerLista() labTL.Text = LaLista.Items.Count txtDato.Clear() txtDato.Focus() End If End Sub Private Sub VerLista() LaLista.Items.Clear() oLista.VerLista(LaLista) End Sub

78

Estructuras de datos con microsoft VB.NET


Private Sub btnNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNew.Click txtDato.Clear() LaLista.Items.Clear() oLista = New CListaLigada oActual = oLista.Header txtDato.Focus() End Sub Private Sub LaLista_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles LaLista.DoubleClick If Not LaLista.SelectedItem Is Nothing Then oActual = LaLista.SelectedItem MsgBox("siguiente insercin despus de" + vbCr + oActual.ToString) End If End Sub Private Sub btnClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClose.Click Close() End Sub Private Sub btnRemove_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRemove.Click If Not LaLista.SelectedItem Is Nothing Then Dim Item As Object = LaLista.SelectedItem oLista.Remover(Item) VerLista() labTL.Text = LaLista.Items.Count End If End Sub Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click If LaLista.Items.Count > 0 Then If SaveFD.ShowDialog = Windows.Forms.DialogResult.OK Then Dim NA As Short = FreeFile() FileOpen(NA, SaveFD.FileName, OpenMode.Output) For Each Item As Object In LaLista.Items PrintLine(NA, Item) Next FileClose(NA) MsgBox("Lista guardada", MsgBoxStyle.Information) End If End If End Sub Private Sub btnOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpen.Click If OpenFD.ShowDialog = Windows.Forms.DialogResult.OK Then Dim NA As Short = FreeFile() Dim Item As Object FileOpen(NA, OpenFD.FileName, OpenMode.Input) oLista = New CListaLigada oActual = oLista.Header Do While Not EOF(NA) Item = LineInput(NA) oLista.Insertar(Item, oActual) oActual = Item Loop FileClose(NA) VerLista() labTL.Text = LaLista.Items.Count End If End Sub

Este cdigo realiza la insercin cuando se pulsa ENTER al capturar un dato:

79

Estructuras de datos con microsoft VB.NET


Private Sub txtDato_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles txtDato.KeyPress If e.KeyChar = Microsoft.VisualBasic.ChrW(Keys.Return) Then btnInserta.PerformClick() End If End Sub End Class

Por ahora, el cdigo en la forma MDI es el siguiente:


Public Class MDIELineales Private Sub ListaLigadaSimpleToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListaLigadaSimpleToolStripMenuItem.Click Dim F As Form = New frmListaSimple F.MdiParent = Me F.Show() End Sub Private Sub FinToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FinToolStripMenuItem.Click Close() End Sub End Class

Ejecucin: Las inserciones se hacen en el orden de captura, pero si se hace un clic doble sobre cualquier elemento de la lista ste se vuelve el elemento actual y la siguiente insercin colocar al dato despus de tal elemento. Para eliminar un elemento de la lista, debe seleccionarse (con un clic) en la lista y luego seleccionar .

Se pueden usar cualquier tipo de datos ya que la clase CListaLigada utiliza datos tipo Object.

Caso de evaluacin de competencias adquiridas: Realizar los cambios necesarios a la clase CListaLigada para que: a. Cuente lo elementos en la lista (no debe usarse el control LaLista (ListBox)) de la aplicacin.

80

Estructuras de datos con microsoft VB.NET


b. Crear un mtodo (en la misma clase) que permita modificar la informacin de un nodo por otro valor (z)19. Por ejemplo que cambie la informacin del nodo Juan por Diana. Tales cambios pueden probarse en misma forma:

Y el cdigo resultante puede verse as:


Private Sub btnCuenta_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCuenta.Click labCuenta.Text = oLista.CuentaItems End Sub Private Sub btnCambio_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCambio.Click Dim oItem1 As Object = txtItem1.Text Dim oItem2 As Object = txtItem2.Text oLista.Cambiar(oItem1, oItem2) VerLista() End Sub

Pero puede hacerse como se quiera siempre y cuando los cambios en el cdigo se hagan en la clase.

19

Z es un parmetro.

81

Estructuras de datos con microsoft VB.NET


Listas Ligadas Dobles.- Aunque recorrer una lista desde el primer nodo hasta el ltimo es muy sencillo, no resulta fcil hacerlo a la inversa (del final al principio). Se puede facilitar esta tarea si se agrega un campo a la clase Nodo para almacenar la liga al nodo previo. Cuando se inserta un nodo a la lista tienen que realizarse ms operaciones para asigna un dato al campo nuevo, sin embargo se gana eficiencia cuando debe removerse un nodo de la lista ya que no se tiene que buscar el nodo previo.

Header

Alicia

Juan

Olga

Nothing

Nothin g

Para esto se agrega una clase nueva al proyecto:

Se copia el cdigo de CNodo al la clase recin creada y se hacen las siguientes modificaciones: Public Class CNodoDoble Public Elemento As Object Public LigaS As CNodo 'Liga al siguiente Public LigaA As CNodo 'Liga al anterior Public Sub New() Elemento = Nothing LigaS = Nothing LigaA = Nothing End Sub 'Sobrecarga Public Sub New(ByVal ElElemento As Object) Elemento = ElElemento LigaS = Nothing LigaA = Nothing End Sub End Class

Y la insercin en este tipo de lista es parecida a la que se hace en una lista simple excepto que se tienen que establecer dos apuntadores: Agregar una clase nueva al proyecto:

82

Estructuras de datos con microsoft VB.NET


Algoritmo de insercin20: 1. 2. 3. 4. Obtener un nodo nuevo y establecer sus campos. Si la lista est vaca entonces insertar el nodo y actualizar sus ligas derecha e izquierda. Si el nodo a insertar est al frente de la lista, entonces insertar el nodo y actualizar sus apuntadores. Insertar el nodo en medio de la lista.

Usando programacin orientada a objetos, este algoritmo puede establecerse de la siguiente manera: Algoritmo Insertar (Nuevo).- Donde Nuevo es el valor que se desea insertar en la lista y sus apuntadores al nodo anterior y al nodo siguiente son LigaA y LigaS respectivamente.
1. Si se va a insertar al final de la lista, entonces: a. b. c. Crear un nodo nuevo y ubicar el ltimo elemento de la lista (U). Crear otro nodo nuevo con la informacin de Nuevo [NodoNuevo(Nuevo)]. Actualizar ligas: NodoNuevo.LigaS U.LigaS NodoNuevo.LigaA U U.LigaS NodoNuevo 2. Insercin despus de un elemento en la lista (Nuevo, DespuesDe).- Donde los parmetros Nuevo y DespuesDe son objetos: a. b. c. d. Crear un nodo nuevo para ubicar al elemento despus del cual se insertar el nodo nuevo (U). Crear otro nodo nuevo con la informacin de Nuevo. (NodoNuevo). Buscar U. Actualizar apuntadores: NodoNuevo.LigaS U.LigaS NodoNuevo.LigaA U NodoNuevo.LigaS.LigaA NodoNuevo U.LigaS NodoNuevo

As, la clase NodoDoble, tendr dos sobrecargas en su constructor: Clase Nodo Doble (agregarla al proyecto):
Public Class CNodoDoble Private mvarElemento As Object Private mvarLigaS As CNodoDoble 'Liga al siguente Private mvarLigaA As CNodoDoble 'Liga al anterior Public Sub New() mvarElemento = Nothing mvarLigaA = Nothing mvarLigaS = Nothing End Sub

20

Tremblay.- Algoritmo modificado al paradigma orientado a objetos.

83

Estructuras de datos con microsoft VB.NET


Public Sub New(ByVal Objeto As Object) mvarElemento = Objeto mvarLigaA = Nothing mvarLigaS = Nothing End Sub Property Elemento() As Object Get Return mvarElemento End Get Set(ByVal value As Object) mvarElemento = value End Set End Property

Property LigaS() As CNodoDoble Get Return mvarLigaA End Get Set(ByVal value As CNodoDoble) mvarLigaA = value End Set End Property Property LigaA() As CNodoDoble Get Return mvarLigaS End Get Set(ByVal value As CNodoDoble) mvarLigaS = value End Set End Property

Y la clase para manipular una lista doble sera como sigue: Clase Lista con doble liga (agregarla al proyecto):
Public Class CListaD Protected Header As CNodoDoble Public Sub New() Header = New CNodoDoble("Header") End Sub Private Function Buscar(ByVal Item As Object) As CNodoDoble Dim Actual As New CNodoDoble Actual = Header If Not Actual.LigaS Is Nothing Then Do While (Actual.Elemento <> Item) Actual = Actual.LigaS Loop End If Return Actual End Function Public Function BuscarPrevio(ByVal a As Object) As CNodoDoble Dim Actual As CNodoDoble = Header Dim Prev As CNodoDoble = Header Do While Not (Actual.LigaS Is Nothing) And Actual.Elemento <> a Prev = Actual Actual = Actual.LigaS Loop Return Prev End Function Public Sub Insertar(ByVal Nuevo As Object, ByVal DespuesDe As Object) 'Insercin en medio de la lista: Dim Actual As New CNodoDoble Dim NodoNuevo As New CNodoDoble(Nuevo) 'Ubicar DespuesDe Actual = Buscar(DespuesDe)

84

Estructuras de datos con microsoft VB.NET


'Actualizar apuntadores NodoNuevo.LigaS = Actual.LigaS NodoNuevo.LigaA = Actual NodoNuevo.LigaS.LigaA = NodoNuevo Actual.LigaS = NodoNuevo End Sub Public Sub Insertar(ByVal Nuevo As Object) 'Insercin al final de la lista: Dim U As CNodoDoble = Ultimo() 'Crear dos nodos Dim NodoNuevo As New CNodoDoble(Nuevo) NodoNuevo.LigaS = U.LigaS NodoNuevo.LigaA = U U.LigaS = NodoNuevo End Sub Public Sub RemoverD(ByVal a As Object) Dim Nodo As CNodoDoble = Buscar(a) If Not Nodo.LigaS Is Nothing Then Nodo.LigaA.LigaS = Nodo.LigaS Nodo.LigaS.LigaA = Nodo.LigaA Nodo.LigaS = Nothing Nodo.LigaA = Nothing Else Nodo.LigaA.LigaS = Nothing Nodo.LigaS = Nothing Nodo.LigaA = Nothing End If End Sub Public Function Ultimo() As CNodoDoble Dim Actual As New CNodoDoble Actual = Header Do While Not Actual.LigaS Is Nothing Actual = Actual.LigaS Loop Return Actual End Function Public Function Primero() As CNodoDoble Dim Actual As New CNodoDoble Actual = Header If Not Actual.LigaS Is Nothing Then Return Actual Else Return Nothing End If End Function Public Sub VistaListaD(ByRef oLista As ListBox) 'Vista hacia adelante Dim Actual As New CNodoDoble Actual = Header oLista.Items.Clear() Do While Not Actual.LigaS Is Nothing Actual = Actual.LigaS oLista.Items.Add(Actual.Elemento) Loop End Sub Public Sub VistaRev(ByRef oLista As ListBox) 'Vista hacia atrs Dim Actual = New CNodoDoble Actual = Ultimo() oLista.Items.Clear() Do While Not Actual.LigaA Is Nothing oLista.Items.Add(Actual.Elemento) Actual = Actual.LigaA Loop End Sub Public Sub GuardaDatos(ByVal sArchivo As String) Dim NA As Short = FreeFile() FileOpen(NA, sArchivo, OpenMode.Output) Dim Actual As New CNodoDoble Actual = Header Do While Not Actual.LigaS Is Nothing

85

Estructuras de datos con microsoft VB.NET


Actual = Actual.LigaS PrintLine(NA, Actual.Elemento) Loop FileClose(NA) End Sub Public Sub AbreDatos(ByVal Arhivo As String, ByRef LaLista As CListaD) Dim NA As Short = FreeFile() FileOpen(NA, Arhivo, OpenMode.Input) Dim Objeto As Object Do While Not EOF(NA) Objeto = LineInput(NA) Insertar(Objeto) Loop FileClose(NA) End Sub 'EVALUACION Public Function CuentaItems() As Integer End Function End Class Ejercicio: Escribir el cdigo necesario para contar los elementos en la lista.

Al inicializar una instancia de la lista doble: Header Inserciones consecutivas:

Header

Alicia

Header

Alicia

Juan

Y una insercin despus de Alicia:


Header Alicia Carolina Juan

Ejemplo: Agregar una forma nueva al proyecto21:

21

La propiedad image de los controles es opcional y no necesariamente con las imgenes mostradas, en su

lugar puede establecerse Text.

86

Estructuras de datos con microsoft VB.NET

Etiquetas labTotal y labTotFiles, mostrarn el total de elementos en la lista doble y el total de archivos (con elementos de una lista) almacenados-

txtDato btnDel btnModificar

btnSave

btnOpen Tres cuadros de dilogo. btnNew btnClose Las tres listas son controles ListBox. Vista del proyecto:

87

Estructuras de datos con microsoft VB.NET


Private ListaD As New CListaD, oActual As Object Public sRuta, RutaPal As String Public Sub New() ' Llamada necesaria para el Diseador de Windows Forms. InitializeComponent() ' Agregue cualquier inicializacin despus de la llamada a InitializeComponent(). sRuta = My.Application.Info.DirectoryPath + "\ListaLigadaD" If Not My.Computer.FileSystem.DirectoryExists(sRuta) Then My.Computer.FileSystem.CreateDirectory(sRuta) End If RutaPal = sRuta + "\Palindromos" 'Crea ruta para ejercicio If Not My.Computer.FileSystem.DirectoryExists(RutaPal) Then My.Computer.FileSystem.CreateDirectory(RutaPal) End If SaveFD.InitialDirectory = sRuta OpenFD.InitialDirectory = sRuta End Sub Private Sub frmListaDoble_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load oActual = Nothing VerArchivos() End Sub Private Sub VerArchivos() ListArchivos.Items.Clear() For Each sFile As String In My.Computer.FileSystem.GetFiles(sRuta) ListArchivos.Items.Add(My.Computer.FileSystem.GetName(sFile)) Next labTotFiles.Text = ListArchivos.Items.Count End Sub

Insercin de datos en secuencia despus de un elemento de la lista, seleccionado con doble clic den ListaA (ListBox). La insercin se realiza al pulsar ENTER en txtDato.
Private Sub txtDato_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles txtDato.KeyPress If e.KeyChar = Microsoft.VisualBasic.ChrW(Keys.Return) Then If txtDato.Text.Trim.Length > 0 Then Dim Elemento As New Object Elemento = txtDato.Text.Trim If oActual Is Nothing Then ListaD.Insertar(Elemento) Else ListaD.Insertar(Elemento, oActual) oActual = Nothing End If ListaD.VistaListaD(ListaA) ListaD.VistaRev(ListaR) labTotal.Text = ListaD.CuentaItems txtDato.Clear() Else MsgBox("Falta dato", MsgBoxStyle.Information) End If End If End Sub Private Sub ListaA_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListaA.DoubleClick _ , ListaR.DoubleClick Dim Lista As ListBox = sender If Not Lista.SelectedItem Is Nothing Then oActual = Lista.SelectedItem MsgBox("La siguiente insercin ser despus de: " + oActual.ToString) txtDato.Focus() End If End Sub

88

Estructuras de datos con microsoft VB.NET


Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click SetDialogo("dat") SaveFD.InitialDirectory = sRuta If SaveFD.ShowDialog = Windows.Forms.DialogResult.OK Then Dim Archivo As String = SaveFD.FileName ListaD.GuardaDatos(Archivo) VerArchivos() End If End Sub

Este procedimiento cambia algunas propiedades de los cuadros de dilogo de acuerdo al tipo de archivo requerido. Ms adelante, los agregados a esta forma como ejercicio, requieren guardar los datos como texto, las listas normales se guardan en archivos de datos (.dat).
Private Sub SetDialogo(ByVal sExt As String) SaveFD.DefaultExt = sExt If sExt = "txt" Then SaveFD.Filter = "Archivos de texto (*.txt)|*.txt" SaveFD.InitialDirectory = RutaPal Else SaveFD.Filter = "Archivos de datos (*.dat)|*.dat" SaveFD.InitialDirectory = sRuta End If SaveFD.FileName = "" OpenFD.InitialDirectory = SaveFD.InitialDirectory OpenFD.DefaultExt = sExt OpenFD.Filter = SaveFD.Filter End Sub Private Sub btnOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpen.Click SetDialogo("dat") If Not ListArchivos.SelectedItem Is Nothing Then OpenFD.FileName = ListArchivos.SelectedItem End If OpenFD.InitialDirectory = sRuta If OpenFD.ShowDialog = Windows.Forms.DialogResult.OK Then Dim sFile As String = OpenFD.FileName Dim FI As System.IO.FileInfo FI = My.Computer.FileSystem.GetFileInfo(sFile) If FI.Length > 0 Then ListaD = New CListaD ListaD.AbreDatos(sFile, ListaD) ListaD.VistaListaD(ListaA) ListaD.VistaRev(ListaR) labTotal.Text = ListaD.CuentaItems End If End If End Sub Para remover un elemento de la lista: Private Sub btnRem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRem.Click 'Elemento seleccionado en ListaA (a remover) If Not ListaA.SelectedItem Is Nothing Then Dim Borra As Object = ListaA.SelectedItem ListaD.RemoverD(Borra) ListaD.VistaListaD(ListaA) ListaD.VistaRev(ListaR) labTotal.Text = ListaD.CuentaItems End If End Sub

89

Estructuras de datos con microsoft VB.NET


Adicionalmente, puede abrirse una lista seleccionando el archivo en la lista que los muestra (ListArchivos), con un clic doble:
Private Sub ListArchivos_MouseDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListArchivos.MouseDoubleClick If Not ListArchivos.SelectedItem Is Nothing Then btnNew.PerformClick() Dim sFile As String = sRuta + "\" + ListArchivos.SelectedItem If My.Computer.FileSystem.FileExists(sFile) Then ListaD.AbreDatos(sFile, ListaD) ListaD.VistaListaD(ListaA) ListaD.VistaRev(ListaR) labTotal.Text = ListaD.CuentaItems End If End If End Sub

As por ejemplo al insertar la siguiente secuencia de datos: Alicia, Juan Carolina, Ricardo, Roxana, las listas hacia adelante y hacia atrs se vern as:

Al hacer clic doble en un dato de la primera lista:

90

Estructuras de datos con microsoft VB.NET

Y al pulsar ENTER:

Public Sub ModificaNodo(ByVal Item As Object, ByVal OModifca As Object) Dim Nodo = Buscar(Item) If Not Nodo.Elemento Is Nothing Then Nodo.Elemento = OModifca Else MsgBox(Item + " no existe en la lista", MsgBoxStyle.Information) End If End Sub

Ejemplo: Si se selecciona Juan en la primera lista (con un clic):

91

Estructuras de datos con microsoft VB.NET


Resultado:

Ejercicio.- Un palndromo es una frase o palabra que se le igual de izquierda a derecha que de derecha a izquierda. Estos son algunos ejemplos: Somos o no somos Luz azul Anita lava la tina La ruta natural Yo hago yoga hoy. No traces en ese cartn

Modificar la ventana de listas ligadas dobles para determinar si una palabra frase es no un palndromo usando la clase CListaD. Sugerencias: Ampliar el ancho de la forma y agregar un control contenedor Panel con las siguientes propiedades: Name = pnlEj Border Style = Fixed 3D

Dentro del este contenedor, se agregan los elementos que se muestran: Los controles de inters(para el programa) son: txtWord.- TextBox con su propiedad CaracterCasong =

lower, as solo se mostrarn letras minsculas.


btnPal.- Command button. labP1.- Label con BorderStyle = Fixed3D, BackColor =HonewDew labP2.- Label con las mismas propiedades de la

92

Estructuras de datos con microsoft VB.NET


anterior salvo el color que debe ser otro. btnSave, btnOpen y btnNew. La ejecucin del ejercicio en la ventana ampliada se vera as:

Como se observa, es necesario quitar espacios en la frase y escribirla sin acentos, por ejemplo, la frase dbale arroz a la zorra el abad, se escribe sin acentos. Adems sus letras son slo minsculas (el control de texto est configurado as).

El cdigo del evento Clic del botn

sera el siguiente:

Private Sub btnPal_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPal.Click Dim Palabra As String = txtWord.Text.Trim If Palabra.Length > 1 Then btnNew.PerformClick() Dim L As Char, i As Short For i = 1 To Palabra.Length L = Mid(Palabra, i, 1) If CStr(L) <> " " Then ListaD.Insertar(L) End If Next With ListaD .VistaListaD(ListaA) .VistaRev(ListaR) End With If EsPalindrome() Then MsgBox("Es un palndrome", MsgBoxStyle.Information) Else MsgBox("No es palndrome", MsgBoxStyle.Information)

93

Estructuras de datos con microsoft VB.NET


End If End If End Sub

Aqu, primero se verifica que la palabra sea de longitud mayor 1. Luego se prepara la forma para una lista doble nueva ejecutando programticamente un clic al botn btnNew. El proceso comienza extrayendo cada letra de la palabra o frase ingresada recorrindola letra por letra como se muestra en el ciclo for del procedimiento y usando la funcin Mid de VB.NET. La instruccin:
L = Mid(Palabra, i, 1)

Extrae la letra del objeto Palabra que se encuentra en la posicin i y tomando nicamente 1 carcter. Para insertar nicamente letras sin espacios en blanco en la frase:
If CStr(L) <> " " Then ListaD.Insertar(L) End If

Finalmente se muestran las listas hacia adelante y hacia atrs y se ejecuta el procedimiento
EsPalindrome objeto del ejercicio. Para guardar y abrir frases que demuestren la validez del cdigo escrito, se crea un directorio especial:

Private Sub btnSavePal_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSavePal.Click SetDialogo("txt") If SaveFD.ShowDialog = Windows.Forms.DialogResult.OK Then My.Computer.FileSystem.WriteAllText(SaveFD.FileName, txtWord.Text.Trim, False) MsgBox("Frase/Palabra guardada", MsgBoxStyle.Information) End If End Sub Private Sub btnOpenPal_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpenPal.Click SetDialogo("txt") If OpenFD.ShowDialog = Windows.Forms.DialogResult.OK Then Dim sWord As String = My.Computer.FileSystem.ReadAllText(OpenFD.FileName) txtWord.Text = sWord End If End Sub

94

Estructuras de datos con microsoft VB.NET


Listas Circulares.- Una lista circular es una lista simple o en donde el apuntador del ltimo nodo apunta al primer elemento de la lista (encabezado). Cuando se inicia una lista circular se tiene entonces:

Header

Y cuando esta lista contiene nodos:

Header

Alicia

Olga

Laura

El modelo usado para la lista ligada simple puede usarse como base para crear una clase para este tipo de listas: En el proyecto actual, agregamos una clase nueva:

Public Class CListaC Protected NodoA As CNodo Protected Header As CNodo Public CuentaNodos As Integer = 0 Public Sub New() Header = New CNodo("Header") Header.Liga = Header End Sub

95

Estructuras de datos con microsoft VB.NET


Mtodos:
Public Function ListaVacia() As Boolean If Header.Liga.Elemento = Header.Elemento Then Return True Else Return False End If End Function Public Sub VaciarLista() Header.Liga = Header CuentaNodos = 0 End Sub Private Function BuscaPrev(ByVal X As Object) As CNodo Dim Actual As CNodo = Header Do While Not Actual.Liga Is Nothing And Actual.Liga.Elemento <> X Actual = Actual.Liga Loop Return Actual End Function Private Function Buscar(ByVal X As Object) As CNodo Dim Actual As CNodo Actual = Header.Liga Do While Actual.Elemento <> X Actual = Actual.Liga Loop Return Actual End Function Public Function Mover(ByVal N As Integer) As CNodo Static Actual As CNodo = Header.Liga Dim Temp As CNodo For i As Integer = 1 To N Actual = Actual.Liga Next If Actual.Elemento = "Header" Then Actual = Actual.Liga End If Temp = Actual Return Temp End Function

La insercin puede hacerse al principio de la lista o despus de algn otro elemento, por defecto el ltimo.
Public Sub Insertar(ByVal X As Object, ByVal DespuesDe As Object) Dim Actual As New CNodo Dim NodoN As New CNodo(X) Actual = Buscar(DespuesDe) NodoN.Liga = Actual.Liga Actual.Liga = NodoN CuentaNodos += 1 End Sub Public Sub InsertarPrimero(ByVal X As Object) Dim Actual As New CNodo(X) Actual.Liga = Header Header.Liga = Actual CuentaNodos += 1 End Sub

Remocin:
Public Sub Remover(ByVal X As Object) Dim NodoP As CNodo = BuscaPrev(X) If Not NodoP.Liga Is Nothing Then NodoP.Liga = NodoP.Liga.Liga End If CuentaNodos -= 1

96

Estructuras de datos con microsoft VB.NET


End Sub

La lista se muestra en un ListBox:


Public Sub VerLista(ByRef UnaLista As ListBox) UnaLista.Items.Clear() Dim Actual As New CNodo Actual = Header Do While Not Actual.Liga.Elemento = "Header" UnaLista.Items.Add(Actual.Liga.Elemento) Actual = Actual.Liga Loop End Sub

Para localizar al ltimo elemento de la lista:


Public Function Ultimo() As CNodo Dim Nodo As CNodo = Header.Liga Dim NTemp As New CNodo Do While Not Nodo.Elemento = "Header" NTemp = Nodo Nodo = Nodo.Liga Loop Return NTemp End Function

Uso: Agregar una forma al proyecto actual (frmListaCircular): Los controles de inters en orden descendente son: txtDato (TextBox) chkDespuesDe (CheckBox) LaLista (ListBox) NumNodo (NumericUpDown, Minimum =0,

Maximum = 10) txtArchivo (TextBox) ListaArchivos (ListBox) Los botones son: btnDel btnMove btnSave btnOpen

97

Estructuras de datos con microsoft VB.NET


En esta ventana se omiten los cuadros de dilogo para guardar y abrir con el fin de mostrar otra opcin para el registro de la informacin de los nodos en una lista circular. Esta ventana opera de la siguiente manera: Siempre que se inicia se crea una instancia de la clase de la lista circular y se crea un directorio para los archivos de listas circulares que, en caso de existir son mostrados:
Public Class frmListaCircular Private ListaC As New CListaC Private Dato As Object, RutaC, sFile As String Private UDato As Object = Nothing Public Sub New() ' Llamada necesaria para el Diseador de Windows Forms. InitializeComponent() ' Agregue cualquier inicializacin despus de la llamada a InitializeComponent(). RutaC = My.Application.Info.DirectoryPath + "\Listas Circulares\" If Not My.Computer.FileSystem.DirectoryExists(RutaC) Then My.Computer.FileSystem.CreateDirectory(RutaC) End If End Sub Private Sub VerArchivos() ListArchivos.Items.Clear() For Each Archivo As String In My.Computer.FileSystem.GetFiles(RutaC, FileIO.SearchOption.SearchTopLevelOnly, "*.*") ListArchivos.Items.Add(My.Computer.FileSystem.GetName(Archivo)) Next End Sub Private Sub frmListaCircular_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load VerArchivos() End Sub

Los datos de la lista se ingresan en txtDatos al pulsar ENTER:


Private Sub txtDato_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles txtDato.KeyPress If e.KeyChar = Microsoft.VisualBasic.ChrW(Keys.Return) Then If txtDato.Text.Trim.Length > 0 Then Dato = txtDato.Text.Trim If ListaC.ListaVacia Then ListaC.InsertarPrimero(Dato) UDato = Dato Else ListaC.Insertar(Dato, UDato) If chkDespuesDe.Checked Then chkDespuesDe.Checked = False Else UDato = Dato End If End If End If ListaC.VerLista(LaLista) NumNodo.Maximum = ListaC.CuentaNodos txtDato.Clear() End If End Sub

98

Estructuras de datos con microsoft VB.NET


Cuando la lista tiene nodos y se desea hacer una insercin despus de un nodo especfico, se marca con un clic en la lista y se activa que se usa para validar: Si el control es activado usamos el evento CheckStateChanged para validar y estalbecer el elemento despus del cual se realizar la insercin, al desactivarse se establece el ltimo elemento de lista para continuar insertando. lo que desencadena un evento

Private Sub chkDespuesDe_CheckStateChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles chkDespuesDe.CheckStateChanged If chkDespuesDe.Checked Then If Not LaLista.SelectedItem Is Nothing Then UDato = LaLista.SelectedItem MsgBox("Siguiente insercin despus de: " + UDato, MsgBoxStyle.Information) txtDato.Focus() Else MsgBox("No se ha seleccionado un elemento en la lista", MsgBoxStyle.Information) chkDespuesDe.CheckState = CheckState.Unchecked End If Else UDato = ListaC.Ultimo.Elemento End If End Sub

Para moverse a un nodo (determinado por el control numrico):


Private Sub btnMove_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMove.Click Dim Nodo As CNodo = ListaC.Mover(NumNodo.Value) If LaLista.Items.Count > 0 Then LaLista.SelectedIndex = NumNodo.Value End If MsgBox("El nodo " + NumNodo.Value.ToString + " es: " + Nodo.Elemento, MsgBoxStyle.Information) End Sub

Para vaciar la lista actual para eliminar el nodo seleccionado:


Private Sub btnClear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClear.Click LaLista.Items.Clear() ListaC.VaciarLista() NumNodo.Value = ListaC.CuentaNodos End Sub Private Sub btnRem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRem.Click If Not LaLista.SelectedItem Is Nothing Then Dim D As Object = LaLista.SelectedItem ListaC.Remover(D) NumNodo.Value = ListaC.CuentaNodos ListaC.VerLista(LaLista) End If End Sub

Finalmente, para guardar una lista, debe introducirse el nombre del archivo, el cual si existe ser reemplazado con la lista actual.

99

Estructuras de datos con microsoft VB.NET

Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click If ListaC.CuentaNodos > 0 Then sFile = txtArchivo.Text.Trim If sFile.Length > 0 Then sFile = RutaC + sFile 'Si el archivo existe lo elimina If My.Computer.FileSystem.FileExists(sFile) Then My.Computer.FileSystem.DeleteFile(sFile) End If Dim NA As Short = FreeFile() FileOpen(NA, sFile, OpenMode.Output) For Each D As Object In LaLista.Items PrintLine(NA, D) Next FileClose(NA) VerArchivos() End If End If End Sub

Y para abrir una lista almacenada:


Private Sub btnOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpen.Click If Not ListArchivos.SelectedItem Is Nothing Then txtArchivo.Text = ListArchivos.SelectedItem sFile = RutaC + txtArchivo.Text Dim NA As Short = FreeFile() FileOpen(NA, sFile, OpenMode.Input) Dim D As Object ListaC.VaciarLista() Do While Not EOF(NA) D = LineInput(NA) If ListaC.ListaVacia Then ListaC.InsertarPrimero(D) Else ListaC.Insertar(D, UDato) End If UDato = D Loop FileClose(NA) ListaC.VerLista(LaLista) NumNodo.Value = 1 End If End Sub

As: La siguiente insercin se har despus de Alicia, por ejemplo.

100

Estructuras de datos con microsoft VB.NET

Y si deseamos movernos al 3er nodo (que estn numerados desde el cero):

Un ejercicio interesante es el siguiente22: De acuerdo a la leyenda, el historiador judo Flavius Josephus fue capturado junto con otros 40 compatriotas por legionarios romanos durante la guerra judeo romana. Los soldados judos decidieron que era preferible suicidarse en lugar de ser capturados (lo que se parece a la saga de Masada) para lo cual disearon un plan para ello. Formaron entonces un crculo para asesinar a cada tercer soldado hasta que todos estuviesen muertos. Jos y otro decidieron que no formaran parte de esto y rpidamente calcularon que era necesario colocarse ellos mismos en el crculo y sobrevivir ambos. Escribir un programa que permita colocar N personas en un crculo y especificar cada M persona debe ser eliminada. El programa debe especificar el nmero de la ltima persona a la izquierda del crculo. Usar una lista ligada circular para resolver el problema. Para resolverlo:

22

McMillan Michael.- Data Structures and Algorithms using Visual Basic.NET.

101

Estructuras de datos con microsoft VB.NET


1. 2. 3. Crear una lista circular de N elementos (N>10) con los nombres de los que sern ejecutados. Establecer cada cuantos son eliminados (M). Repetir mientras el tamao de la lista sea >M. a. b. c. d. e. 4. FIN Recorrer la lista cada m-simo elemento agregarlo a un ListBox Agregar ese nombre a otra lista (yo utilic un ArrayList) Al terminar el recorrido eliminar la seleccin de la lista circular (que est en el ArrayList) Vaciar el ArrayList. Mostrar la lista circular restante

Puede usarse la ventana actual agregando una seccin para resolver el ejercicio: Panel1

NumM

(NumericUpDown

Maximum = 100, Minimum =2) btnInicio (Button) ListaJ (ListBox)

102

Estructuras de datos con microsoft VB.NET


Prueba 1: En el primer recorrido se sealan a Pedro, Judas, Flavio Jacob y Jeremas que luego son eliminados, quedando al principio Abraham. El segundo recorrido de la lista restante se elimina a Jos, Barrabs y a Toms y vuelve a quedar Abraham al principio de la lista. Finalmente el 2 elemento es Dimas que se elimina y slo queda Abraham. La conclusin es que el que quiera sobrevivir al final, deber colocarse al principio de la lista. La nica validacin que se realiza es M < N aunque deberan ingresarse valores entre 2 y N/M. Prueba 2:

PILAS La Pila es una de las estructuras lineales de tamao variable ms importantes. De forma general, en una lista lineal se pueden realizar inserciones o remociones en cualquier parte esta. Una clase importante de listas permite que la insercin y remocin de un elemento se realice nicamente al final de la lista. Este tipo de clase se conoce como una Pila. A la operacin de insertar un elemento al final de la lista se le conoce como PUSH y a la operacin de eliminar el elemento al final de la lista como POP. El primer y ltimo elemento de una pila debe ser accesible y se conocen como el fondo y el tope de la pila. As la remocin se hace siempre en el orden inverso a como fueron agregados los elementos de una pila.

103

Estructuras de datos con microsoft VB.NET

POP

Pila Vaca Tope 0

PUSH1 Tope 1

PUSH2 Tope 2 1

PUSH3 Tope 3 2 1 2 Tope 1

Puesto que como generalmente no se conoce el tamao de una pila, lo mejor es usar una estructura dinmica como el ArrayList. La Clase PILA (Agregar al proyecto actual) :
Public Class CPila Private Tope As Integer Private L As New ArrayList Public Sub New() Tope = -1 End Sub ReadOnly Property Count() As Integer Get Return L.Count End Get End Property Public Sub PUSH(ByVal X As Object) L.Add(X) Tope += 1 End Sub Public Function POP() As Object If L.Count > 0 Then Dim x As Object = L.Item(Tope) L.RemoveAt(Tope) Tope -= 1 Return x Else Return Nothing End If End Function Public Sub CLEAR() L.Clear() End Sub Public Function PEEK() As Object 'Regresa el elemento en el tope de la pila If Not Tope = -1 Then Return L.Item(Tope) Else 'Pila vaca Return Nothing End If End Function Public Sub VerPila(ByRef LB As ListBox) LB.Items.Clear() If L.Count > 0 Then L.Reverse() For Each X As Object In L LB.Items.Add(X) Next

104

Estructuras de datos con microsoft VB.NET


L.Reverse() End If End Sub End Class

Uso: Agregar una forma nueva al proyecto:

txtDato (TextBox) btnPush (Button) LaPila (ListBox) btnPop (Button) btnTope (Button) btnCLS (Button) ListaPOP (ListBox) labCount (Label).

Implementacin de la clase Pila:


Public Class frmPILA Private Pila As CPila Private Sub frmPILA_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Pila = New CPila End Sub

105

Estructuras de datos con microsoft VB.NET


Private Sub btnPush_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPush.Click If Not txtDato.Text Is Nothing Then Dim Dato As Object = txtDato.Text.Trim Pila.PUSH(Dato) Pila.VerPila(LaPila) txtDato.Clear() txtDato.Focus() labCount.Text = Pila.Count End If End Sub Private Sub POP_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles POP.Click Dim Dato As Object = Pila.POP If Not Dato Is Nothing Then ListaPOP.Items.Add(Dato) Pila.VerPila(LaPila) labCount.Text = Pila.Count Else MsgBox("Pila vaca", MsgBoxStyle.Information) End If End Sub Private Sub btnTope_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTope.Click Dim Dato As Object = Pila.PEEK If Not Dato Is Nothing Then MsgBox("El tope es " + Dato.ToString, MsgBoxStyle.Information) Else MsgBox("Pila vaca", MsgBoxStyle.Information) End If End Sub Private Sub btnCLS_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCLS.Click Pila.CLEAR() LaPila.Items.Clear() ListaPOP.Items.Clear() End Sub End Class

Ejecucin: Secuencia de insercin: 150, 417, 515, 800, 90:

Tope de la pila:

106

Estructuras de datos con microsoft VB.NET

Operaciones POP (retirar 3 elementos):

Aplicacin: El problema del Palndromo23 puede resolverse usando una pila y usando esta misma forma:

Panel1: txtFrase (TextBox, CharacterCasing = Lower) btnPal (Button):


23

Ejercicio de la pgina 19.

107

Estructuras de datos con microsoft VB.NET

Private Sub btnPal_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPal.Click Pila = New CPila Dim sFrase As String = txtFrase.Text.Trim If sFrase.Length > 0 Then Dim x As Integer, Letra As Char Dim sW1 As String = "" Dim EsPalindromo As Boolean = True For x = 0 To sFrase.Length - 1 Letra = sFrase.Substring(x, 1) If Letra <> " " Then sW1 += Letra Pila.PUSH(Letra) End If Next Pila.VerPila(LaPila) labCount.Text = Pila.Count x = 0 Do While Pila.Count > 0 Letra = Pila.POP ListaPOP.Items.Add(Letra) If Letra <> sW1.Substring(x, 1) Then EsPalindromo = False Exit Do End If x += 1 Loop If EsPalindromo Then MsgBox("Es palndromo", MsgBoxStyle.Information) Else MsgBox("No es palndromo", MsgBoxStyle.Information) End If End If End Sub

La Clase Stack. La clase Stack es una implementacin de la interfaz ICollection que representa a una pila. Esta clase est implementada como un buffer circular que permite obtener espacio dinmicamente para los elementos insertados en la pila. Esta clase forma parte del marco (Framework) .NET. La clase Stack incluye mtodos Push, Pop y Peek. Tiene tambin mtodos para determinar el nmero de elementos en la pila, limpiarla y regresar los valores en la pila como un arreglo. Mtodos Constructores de la clase Stack. Existen tres maneras de instanciar un objeto Stack. El constructor por defecto instancia una pila vaca que inicialmente tiene una capacidad de 10 elementos y puede invocarse como:

Dim LaPila As New Stack 108

Estructuras de datos con microsoft VB.NET


Cada vez que la pila se llena, su capacidad es duplicada. El segundo mtodo constructor permite crear un objeto pila de otra coleccin. Por ejemplo se puede pasar al constructor un arreglo y apilar los sus elementos:

Dim Nombres() As String = {"Laura", "Ana", "Juan", "Carolina"} Dim Pila As New Stack(Nombres)
El mtodo POP quitara a Carolina de la pila. El tercer mtodo, permite especificar la capacidad inicial de la pila y se usa si se conoce de antemano cuantos elementos debe contener la pila. Ejemplo:

Dim P As New Stack(20)


Ejemplo de uso: Conversin de nmeros en base 10 a cualquier otra base24: Agregar forma al proyecto: txtNum (TextBox, TextAlign =_Right, Text=0 NumBase (NumericUpDown, Minimu = 2, Maximum=8) btnConvet (Button) labRes (Label, BorderStyle = Fixed 3D, AutoZise = False, TextAlign = Center

Ejemplo:

24

Mtodo descrito en Arreglos.

109

Estructuras de datos con microsoft VB.NET

Comprobacin:

Public Class frmSTACK Private Sub btnConvert_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConvert.Click Dim Num As Integer = txtNum.Text Dim Base As Short = NumBase.Value labRes.Text = ToBase(Num, Base) End Sub Private Function ToBase(ByVal n As Integer, ByVal b As Short) As String Dim Digitos As New Stack Dim sR As String = "" Do While n > 0 Digitos.Push(n Mod b) n \= b Loop Do While Digitos.Count > 0 sR += Digitos.Pop.ToString Loop Return sR End Function End Class

110

Estructuras de datos con microsoft VB.NET


Notacin Polaca. Sistema para especificar expresiones matemticas desarrollado en 1920 por el matemtico de origen polaco Jan Lukasiewicz. Esta expresin se conoce como notacin prefija o polaca (en honor a l) y consiste en situar al operador antes que los operandos. Por ejemplo, la expresin infija A * B/(C-D) se representa en notacin prefija (prefija) como /*AB+AC. La notacin posfija o polaca inversa es una variacin de la notacin prefija de forma que el operador se coloca despus de los operandos. Por ejemplo, la expresin infija A*B/(C-D) se representara en notacin posfija como AB*AC+/. Conversin de expresiones infijas sin parntesis a notacin polaca inversa: Si se asignan valores de precedencia para los cuatro operadores bsicos: Tabla 1. Smbolo +, *, / a, b, c, # Precedencia F 1 2 3 0 Rango R -1 -1 1 0

Se asume que el contenido de la pila para evaluar esta expresin se inicializa con el smbolo # que tiene un valor de precedencia menor que los dems smbolos dados en la tabla. El algoritmo general para esta tarea sera: 1. 2. 3. 4. 5. 6. Inicializar el contenido de la pila con # Extraer el smbolo ms a la izquierda de expresin infija (smbolo de entrada actual). Repetir hasta el paso 6 mientras el smbolo de entrada <># Remover y sacar todos los smbolos en la pila cuya precedencia sea mayor o igual al valor de precedencia del valor del smbolo actual. Colocar en la pila el smbolo actual. Extraer el siguiente smbolo ms a la izquierda en la expresin infija ( smbolo de entrada

actual).
Algoritmo Expresiones si parntesis
25

25

J.P. Tremblay (modificado)

111

Estructuras de datos con microsoft VB.NET


Dada una cadena de entrada INFIJA que representa a una expresin infija donde sus smbolos tienen la precedencia mostrada en la tabla 1, una PILA y una funcin denominada SIGUIENTE la cual, cuando es invocada regresa el siguiente carcter (de izquierda a derecha) de la cadena de entrada, este algoritmo convierte INFIJA a su correspondiente cadena POLACA. RANGO contiene el valor de cada smbolo en la expresin polaca. ACTUAL contiene el smbolo actualmente examinado y TEMP es el elemento que se saca de la pila. Se asume que la cadena de entrada termina con el smbolo especial #. 1. 2. Inicializar la PILA: PILA.PUSH(#) Inicializar la cadena de salida y el contador de rangos: POLISH Rango 0 3. 4. 5. Obtener el primer smbolo: Actual SIGUIENTE(INFIJA) Traducir la expresin infija: Repetir hasta el paso 6 mientras Actual # Sacar de la pila los smbolos con precedencia mayor o igual. Repetir mientras F(Actual) <=F(Pila.Tope) TEMP PILA.POP POLISH POLISH + TEMP Rango Rango + R(TEMP) Si Rango < 1 entonces Error Expresin invlida [FIN] 6. Colocar el smbolo actual en la pila: PILA.PUSH(Actual) Actual SIGUIENTE(INFIJA) 7. Quitar los elementos remanentes de la pila: Repetir mientras PILA(Tope) # TEMP PILA.POP POLACA POLACA + TEMP Rango Rango + R(TEMP) Si Rango < 1 entonces Error Expresin invlida [FIN] 8. Es vlida la expresin? Si Rango = 1, entonces Expresin es vlida De otro modo Expresin no es vlida

112

Estructuras de datos con microsoft VB.NET


FIN

Implementacin:
Public Class CPolaca Public POLACA As String = "" Private mvarINFIJA As String = "" Private Actual As String = "" Private TEMP As String = "" Private X As Short Public Sub New() X = 0 End Sub Property INFIJA() As String Get Return mvarINFIJA End Get Set(ByVal value As String) mvarINFIJA = value + "#" End Set End Property Private Function RSP(ByVal C As Char) As Short 'Expresin sin parntesis Select Case C Case "+", "-" Return -1 Case "*", "/" Return -1 Case "a" To "z" Return 1 Case "#" Return 0 Case Else Return 0 End Select End Function Private Function FSP(ByVal C As Char) As Short 'Expresin sin parntesis Select Case C Case "+", "-" Return 1 Case "*", "/" Return 2 Case "a" To "z" Return 3 Case "#" Return 0 Case Else Return 0 End Select End Function Private Function SIGUIENTE() As Char If X < mvarINFIJA.Length Then Dim L As Char = mvarINFIJA.Substring(X, 1) X += 1 Return L Else Return vbNullChar End If End Function Public Function POLACASP() As String Dim Pila As New Stack Pila.Push("#") '...........................................[1] Dim Rango As Short = 0 '...................................[2] POLACA = "" INFIJA += "#"

113

Estructuras de datos con microsoft VB.NET


Actual = SIGUIENTE() '.....................................[3] Do While Actual <> "#" '...................................[4] Do While FSP(Actual) <= FSP(Pila.Peek) '...............[5] TEMP = Pila.Pop POLACA += TEMP Rango += RSP(TEMP) If Rango < 1 Then POLACASP = "EXPRESION NO ES VALIDA" Exit Function End If Loop Pila.Push(Actual) '....................................[6] Actual = SIGUIENTE() Loop Do While Pila.Peek <> "#" '................................[7] TEMP = Pila.Pop POLACA += TEMP Rango += RSP(TEMP) Loop If Rango = 1 Then '........................................[8] POLACASP = POLACA Else POLACASP = "EXPRESION NO VALIDA" Exit Function End If End Function End Class

Uso.- Agregar una forma al proyecto:

txtExp (TextBox, CaracterCasing = Lower) btnPolaca (Button)

Public Class frmPolaca Private Sub btnPolish_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPolish.Click If txtExp.Text.Trim.Length > 0 Then Dim Polaca As New CPolaca Polaca.INFIJA = txtExp.Text.Trim

114

Estructuras de datos con microsoft VB.NET


If InStr(Polaca.INFIJA, "(") = 0 Then labPolaca.Text = Polaca.POLACASP End If End If End Sub

Algoritmo Expresiones con parntesis (y operador de potencia). Tabla 226. Smbolo +, *, a,b,c, ( ) Precedencia de entrada F 1 3 6 7 9 0 Funcin de precedencia en la pila G 2 4 5 8 0 0 Funcinde Rango R -1 -1 -1 1 0 0

Dada una cadena infija de entrada (INFIJA) que representa a una expresin infija la cual termina con ) y cuyos smbolos tienen los valores de precedencia que se muestran en la tabla 2, una PILA y una funcin SIGUIENTE que cuando es invocada regresa el siguiente carcter a ser evaluado, este algoritmo convierte la expresin infija a su polaca equivalente. La variable entera Rango acumula el rango de la expresin. Finalmente TEMP almacena temporalmente el elemento apilado. 1. 2. Inicializar PILA: PILA.PUSH(() Inicializar la cadena de salida y contador de rangos. POLACA

26

Tremblay

115

Estructuras de datos con microsoft VB.NET


Rango 0 3. 4. 5. Obtener smbolo de entrada: Actual SIGUIENTE Traducir la expresin infija: Repetir hasta el paso 7 mientras Actual Quitar de la pila los smbolos con mayor precedencia: Si Pila vaca entonces Error Expresin invlida [FIN] Repetir mientras F(Actual) < G(PILA.Tope) TEMP PILA.POP POLACA POLACA + TEMP Rango Rango + R(TEMP) Si Rago < 1 entonces Error Expresin invlida [FIN] 6. Se encuentran parntesis? Si Actual PILA.TOPE entonces PILA.PUSH(Actual) De otro modo PILA.POP 7. 8. Obtener siguiente smbolo de entrada: Actual SIGUIENTE Es vlida la expresin? Si PILA.TOPE 0 Rango 1 entonces Error Expresin invlida [FIN] De otro modo, RETURN POLACA Mtodos nuevos a la clase (para expresiones con parntesis):
Private Function FCP(ByVal c As Char) As Short Select Case c Case "+", "-" Return 1 Case "/", "*" Return 3 Case "^" Return 6 Case "a" To "z" Return 7 Case "(" Return 9 Case ")" Return 0 Case Else Return 0 End Select End Function

116

Estructuras de datos con microsoft VB.NET


Private Function RCP(ByVal C As Char) As Short Select Case C Case "+", "-" Return -1 Case "*", "/" Return -1 Case "^" Return -1 Case "a" To "z" Return 1 Case "(" Return 0 Case ")" Return 0 Case Else Return 0 End Select End Function Private Function G(ByVal C As Char) As Short Select Case C Case "+", "-" Return 2 Case "*", "/" Return 4 Case "^" Return 5 Case "a" To "z" Return 8 Case "(" Return 0 Case ")" Return 0 Case Else Return 0 End Select End Function

Public Function POLACACP() As String Dim PILA As New Stack INFIJA += ")" PILA.Push("(") POLACA = "" Dim Rango As Short = 0 Actual = SIGUIENTE() Do While Actual <> vbNullChar If PILA.Count = 0 Then POLACACP = "Expresin invlida" Exit Function End If Do While FCP(Actual) < G(PILA.Peek) TEMP = PILA.Pop POLACA += TEMP Rango += RCP(TEMP) If Rango < 1 Then POLACACP = "Expresin invlida" Exit Function End If Loop If FCP(Actual) <> G(PILA.Peek) Then PILA.Push(Actual) Else PILA.Pop() End If Actual = SIGUIENTE() Loop If PILA.Count <> 0 Or Rango <> 1 Then POLACACP = "Expresin no vlida"

'[1] '[2] '[2] '[3] '[4]

'5]

'[6]

'[7] '[8]

117

Estructuras de datos con microsoft VB.NET


Else POLACACP = POLACA End If End Function

Cambios en la forma:

Private Sub btnPolish_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPolish.Click If txtExp.Text.Trim.Length > 0 Then Dim Polaca As New CPolaca Polaca.INFIJA = txtExp.Text.Trim If InStr(Polaca.INFIJA, "(") = 0 Then labPolaca.Text = Polaca.POLACASP Else labPolaca.Text = Polaca.POLACACP End If End If End Sub

Ejecucin:

Como evaluar las expresiones polacas: Una expresin simple: a + b * c d / e * h (1)

Representa a la expresin algebraica (2) Que al convertirse a su forma polaca queda como: abc*+de/h*(3)

Donde z es el resultado numrico final y las variables a, b, c,, z son valores numricos.

118

Estructuras de datos con microsoft VB.NET


La notacin polaca (1) se calcula de la siguiente manera: 1. 2. 3. Se inicializa una pila Se recorre la expresin polaca de izquierda a derecha Si el smbolo actual representa a un numero se apila , de otro modo (es un operador) se sacan dos elementos de la pila y se realiza la operacin cuyo resultado se apila: Ejemplo: a = 5, b =3, c =1, d = 4, e = 2, h =5
Antes de llegar al smbolo *, la pila tendra los valores numricos: c b a 1 3 5

Se extraen dos elementos de la pila (c y d) y se ejecuta la operacin <c><operdor><b> R1 b * c (3 * 1 = 3) y este resultado se apila R1 a 3 5

El siguiente smbolo es tambin un operador, luego se extraen dos elemento y se realiza la operacin: R2 a + R1 (5 + 3 = 8) y se apila: R2 e d R2 8 2 4 8 Siguientes smbolos que se extraen:

R1 d e (4 2 = 2) y se apila R1 R2 2 8

Siguiente smbolo (h) se apila: h R1 R1 5 2 8

Operador * R2 R1 * h (2 * 5 = 10) R2 R1 10 8

El ltimo smbolo es un operador (-), luego: R3 R1 - R2 (8 10 = -2) y se apila: R3 -2

119

Estructuras de datos con microsoft VB.NET

4.

El resultado de esta expresin es el elemento en el tope de la pila.

Ejercicio: Construir una calculadora de expresiones algebraicas infijas que las convierta a su equivalente polaca, y sea capaz de asignar valores numricos a las variables para mostrar el resultado numrico final. Algo como esto:

TxtINIFJA (TextBox, CharacterCasing = Lower) permite ingresar una expresin infija directamente o desde el teclado alfanumrico. Ejemplo:

Cuando se hace clic en

el resultado se muestra en otro TextBox (txtRes, ReadOnly = True) y, si

es una expresin vlida se activa el botn (btnRes, Enabled = False como valor inicial).

Al hacer clic en ste se extraes las variables de la expresin polaca y se muestran en el DataGridView (DGV que se cre con dos columnas: cVar Variable ReadOnly = True, cValue, ReadOnly = False HeaderText= Valor - Numrica entera).

120

Estructuras de datos con microsoft VB.NET


Se asignan entonces los valores de cada variable en la expresin directamente en DGV.

Obtiene el resultado numrico y lo muestra en txtINFIJA.

Ingreso desde el teclado: El conjunto de botones alfanumricos: Estn nombrados como btn1, btn2, btn3,., btn0. Se usa la propiedad Tag de cada botn para asignar la letra: btn1: Text 1a, Tag = a, bt2: Text 2b, Tag = b, etc.

El conjunto de operadores:

Botones nombrados btnX, btnDiv, btnSum, btnMinus, btnPot, btnPA (, btnPC ) y btnEq (=) Se usa tambin la propiedad Tag para establecer cada operador: btnX, Tag =*, btnDiv, Tag =/, etc, Para ingresar valores desde el teclado de la calculadora se usa un solo evento Clic:

121

Estructuras de datos con microsoft VB.NET


Private Sub btn1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn1.Click, btn2.Click _ , btn3.Click, btn4.Click, btn5.Click, btn6.Click, btn7.Click, btn8.Click, btn9.Click, btn0.Click Dim oButton As Button = sender txtINFIJA.SelectionStart = txtINFIJA.Text.Length txtINFIJA.SelectedText = oButton.Tag End Sub Private Sub btnX_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnX.Click _ , btnDiv.Click, btnSum.Click, btnMinus.Click, btnPot.Click, btnPA.Click, btnPC.Click Dim oButton As Button = sender txtINFIJA.SelectionStart = txtINFIJA.Text.Length txtINFIJA.SelectedText = oButton.Tag End Sub

Private Sub btnEq_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEq.Click If txtINFIJA.Text.Trim.Length > 0 Then Dim bValida As Boolean = False Dim Polaca As New CPolaca Dim Infija As String = txtINFIJA.Text.Trim Polaca.INFIJA = Infija If InStr(Infija, "(") = 0 Then txtRes.Text = Polaca.POLACASP(bValida) Else txtRes.Text = Polaca.POLACACP(bValida) End If btnRes.Enabled = bValida End If End Sub

En donde se hizo una ligera modificacin a la clase CPolaca con el fin de saber si la expresin fue o no vlida.
Public Function POLACACP(Optional ByVal bValid As Boolean = False) As String Dim PILA As New Stack INFIJA += ")" PILA.Push("(") '[1] POLACA = "" '[2] Dim Rango As Short = 0 '[2] Actual = SIGUIENTE() '[3] Do While Actual <> vbNullChar '[4] If PILA.Count = 0 Then POLACACP = "Expresin invlida" Exit Function End If Do While FCP(Actual) < G(PILA.Peek) '5] TEMP = PILA.Pop POLACA += TEMP Rango += RCP(TEMP) If Rango < 1 Then POLACACP = "Expresin invlida" Exit Function End If Loop If FCP(Actual) <> G(PILA.Peek) Then '[6] PILA.Push(Actual) Else PILA.Pop() End If Actual = SIGUIENTE() '[7] Loop If PILA.Count <> 0 Or Rango <> 1 Then '[8]

122

Estructuras de datos con microsoft VB.NET


POLACACP = "Expresin no vlida" Else bValid = True POLACACP = POLACA End If End Function Public Function POLACASP(Optional ByRef bValid As Boolean = False) As String Dim Pila As New Stack Pila.Push("#") '...........................................[1] Dim Rango As Short = 0 '...................................[2] POLACA = "" INFIJA += "#" Actual = SIGUIENTE() '.....................................[3] Do While Actual <> "#" '...................................[4] Do While FSP(Actual) <= FSP(Pila.Peek) '...............[5] TEMP = Pila.Pop POLACA += TEMP Rango += RSP(TEMP) If Rango < 1 Then POLACASP = "EXPRESION NO ES VALIDA"

Exit Function
End If Loop Pila.Push(Actual) '....................................[6] Actual = SIGUIENTE() Loop Do While Pila.Peek <> "#" '................................[7] TEMP = Pila.Pop POLACA += TEMP Rango += RSP(TEMP) Loop If Rango = 1 Then '........................................[8] POLACASP = POLACA bValid = True Else POLACASP = "EXPRESION NO VALIDA" bValid = False Exit Function End If End Function

Para extraer las variables de una expresin polaca vlida usamos una coleccin que est declarada como privada y las muestra en el DGV:
Public Class frmCalc Private Variables As New Collection

Private Sub xVariables(ByVal Infija As String) On Error Resume Next 'Omite valores duplicados Variables.Clear() DGV.Rows.Clear() Dim L As Char, x As Integer For i As Short = 0 To Infija.Length - 1 L = Infija.Substring(i, 1) Select Case L Case "a" To "z" Variables.Add(L, Key:=L) End Select Next

123

Estructuras de datos con microsoft VB.NET


For Each L In Variables DGV.Rows.Add() Dim R As DataGridViewRow = DGV.Rows(DGV.RowCount - 1) R.Cells(0).Value = L Next End Sub

Luego deben introducirse directamente los valores numricos de cada variable en la celda correspondiente:

Finalmente: Calcula el resultado final numrico y lo muestra: Escribir este procedimiento de evento siguiendo la metodologa descrita antes para obtenerlo.
Private Sub btnCalc_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCalc.Click 'Ejercicio de evaluacin End Sub

Esta solucin no es la nica, puede intentar otra para alcanzar este objetivo usando cualquier otra estructura de datos que considere pertinente. Resultado:

Prepara la calculadora para ingresar otra expresin infija:

Private Sub btnCls_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCls.Click

124

Estructuras de datos con microsoft VB.NET


txtINFIJA.Clear() txtRes.Clear() DGV.Rows.Clear() btnRes.Enabled = False btnCalc.Enabled = False End Sub

Recursin con ayuda de pilas: Los procedimientos recursivos 27 siguiente ejemplo: En la unidad II se mostr el algoritmo recursivo para la funcin Factorial: pueden construirse con ayuda de pilas como lo muestra el

Este mismo procedimiento puede establecerse de la siguiente manera28: FACTORIAL.- Dado un entero N, este algoritmo calcula N!. La pila P se usa para almacenar un registro de activacin asociado con cada llamada recursiva. Cada registro de activacin contiene el valor actual de N y la direccin actual retornada RET_ADDR. TEMP_REC es tambin un registro que contiene dos variables: PARM y ADDRESS. Este registro temporal es necesario para simular la apropiada transferencia de control desde un algoritmo de control del algoritmo FACTORIAL a otro. Siempre que un TEMP_REC es colocado en la pila P, copias de PARM y ADDRESS son apiladas en A y asignadas a N y a RET_ADDR respectivamente. Inicialmente la direccin de retorno se establece a la llamada principal (por ejemplo: (ADDRESS direccin principal). PARM se establece con el valor inicial de N.
27 28

Unidad II. J.P. Tremblay.

125

Estructuras de datos con microsoft VB.NET

1. 2.

Guardar N y regresar direccin: P.PUSH(TEMP_REC) Se alcanz el criterio base? Si N =0 entonces FACTORIAL 1 Ir al paso 4 De otro modo ADDRESS Paso 3 Ir al paso 1

3. 4.

Calcular N! FACTORIAL N * FACTORIAL Restablecer el valor previo de N y regresar direccin: TEMP_REC P.POP (Ejemplo: PARM N, ADDRESS RET_ADDR, P.POP) Ir a ADDRESS

126

Estructuras de datos con microsoft VB.NET

4 Estructuras no lineales.
Competencia especifica.- Conocer y aplicar las estructuras no lineales en solucin de problemas del mundo real.
rboles. Definicin.- Un rbol es una estructura de datos no lineal que se usa para almacenar datos de una manera jerrquica. Un rbol es una estructura jerrquica que se aplica sobre una coleccin de de elementos u objetos llamados nodos, uno de los cuales es llamado Raz. Adems se crea una relacin de parentesco entre los nodos dando lugar a trminos como padre, hijo, hermano, sucesor,

ancestro, etc.29
Un rbol es pues un conjunto de nodos conectados por ramas. Un ejemplo de un rbol es el organigrama de organizacin de una empresa.
Raz

Gerente General

Director de Finanzas F Fig. 4. 1

Director de Produccin

Direccin de Ventas

Jefe de operaciones

Soporte tcnico

29

Cair/Guardati. Estructuras de datos. McGraw Hill.

127

Estructuras de datos con microsoft VB.NET

Otro tipo de rboles puede definirse en otros trminos: Nodo Raz M

T C

F E Fig 4.2 H

Sub-rbol

Si un nodo est conectado a otros nodos por debajo de l, se denomina nodo padre y a los nodos por debajo de l se les denomina nodos hijos. Un nodo puede tener cero, uno ms nodos conectados a l. Existe una clase especial de rboles llamados rboles Binarios que restringen el nmero de hijos a no ms de dos. Los rboles binarios tienen ciertas propiedades computacionales que los hacen muy eficientes para muchas operaciones En la figura 2 se puede observar que se pueden visitar ciertos nodos que no estn directamente conectados siguiendo una Ruta de conexiones. Por ejemplo para llegar al nodo R, la ruta sera M T R. El visitar todos los nodos de un rbol se denomina travesa. Un rbol puede dividirse en dos niveles. El nodo raz es el nivel 0, su hijo el nivel 1, sus hijos seran el nivel 3 y as sucesivamente. Un nodo en cualquier nivel se considera la raz de un sub-rbol el cual consiste de esa raz y sus hijos y los hijos de sus hijos. Se define la profundidad de un rbol como nmero de capas en l. Por ltimo, cada nodo en el rbol tiene un valor algunas veces referido como el valor clave. ARBOLES BINARIOS. Un rbol binario se define como un rbol en el cual cada nodo no tiene ms de dos hijos. Los nodos hijos de un nodo padre son referidos como nodo izquierdo y nodo derecho. Para ciertas

128

Estructuras de datos con microsoft VB.NET


implementaciones de rboles binarios los valores de los datos slo pueden almacenarse en nodos izquierdos y otros en nodos derechos. Por ejemplo:

53

30

80

17

40

75

90

Fig. 4.3 En este rbol los valores menores (a la raz) se almacenan a la izquierda y los mayores a la derecha. Recorridos en un rbol binario. Se llama recorrido del rbol al procedimiento de visitar todos los nodos del mismo de diferentes maneras. Existen tres mtodos de recorridos sobre el rbol: inorder, preorder y postorder. El recorrido inorder visita todos los nodos en orden ascendente de sus valores. Un recorrido en preorder primero visita la raz seguido de los nodos en los sub rboles del hijo izquierdo de la raz. Este procedimiento puede escribirse de manera recursiva. Puesto que el mtodo visita cada nodo de manera ascendente, debe adems visitar tanto el hijo izquierdo como el derecho de cada sub rbol siguiendo con los rboles a la izquierda de la raz antes de continuar con los de la derecha. En el recorrido en preorder la nica diferencia entre ambos son tres lneas de cdigo. La llamada al procedimiento para visualizar un nodo est colocada entre las dos llamadas recursivas del mtodo

inorder.
En el mtodo postorder la diferencia con los dos anteriores es donde se coloca la llamada al

procedimiento para visualizar un nodo y las llamadas recursivas al procedimiento. En el recorrido en postorder, el mtodo primero hace recursin sobre los sub rboles izquierdos y luego sobre los sub rboles derechos. Valores mnimos y mximos en un rbol binario. Para encontrar los valores mximo y mnimo en un rbol binario es casi trivial, en ambos casos debido a las propiedades del mismo. El valor mnimo siempre se encontrar a la izquierda del hijo izquierdo de un sub rbol comenzando con el hijo izquierdo de la raz. Por otro lado, el valor mximo se encuentra en el ltimo nodo a la derecha del sub rbol comenzando con el hijo derecho de la raz.

129

Estructuras de datos con microsoft VB.NET


Para encontrar el valor mnimo el mtodo comienza creando un objeto nodo y establecindolo al nodo raz. Luego verifica que el valor en el hijo izquierdo sea nada. Si no lo es el programa establece ese nodo al nodo actual. Esto contina hasta encontrar un nodo cuyo hijo izquierdo sea nada. Esto significa que no existe un valor menor debajo, y el valor mnimo ha sido localizado. El mtodo para localizar el valor mximo en un rbol binario luce similar al anterior excepto que se mueve a travs del hijo derecho. Mtodo de bsqueda en un rbol binario. Permite determinar si un valor especfico existe en el rbol. Primero se crea un nodo y se iguala a la raz, luego prueba donde se encontrara el valor buscado (izquierda derecha). Si lo encuentra el mtodo simplemente regresa el nodo actual. De otro modo si no se encuentra en el nodo raz, el dato se compara con el nodo actual. Si el valor buscado es menor que el del nodo actual entonces el nodo actual se establece al hijo izquierdo o al hijo derecho si es mayor. El ltimo segmento del mtodo regresar el valor de nada indicando el final de la bsqueda. Cuando termina el ciclo el valor almacenado en el nodo actual (si no es nulo) es el valor encontrado. Eliminar un nodo simple en una bsqueda binaria de un rbol a travs de un recorrido. En algunos casos la remocin de un nodo es generalmente trivial, en otros debe tenerse especial cuidado con el cdigo o se corre el riesgo de destruir la correcta estructura jerrquica del rbol binario.

4 0

Nodo a eliminar (No se puede eliminar 5 0 el sub-rbol).

4 8 4 5 4 9 5 2

5 5 5 8

Fig. 4.4 Otro caso especial es la remocin de un nodo con dos hijos: En el primer caso la solucin es mover el sucesor inorder al lugar del nodo que se elimina (50). Esto funciona bien a menos que el sucesor mismo tenga hijos. Para encontrar al sucesor del nodo original hay que ir al nodo derecho original. Por definicin, este nodo no debera ser mayor que el nodo original. Luego se comienzan a seguir las rutas del hijo izquierdo. Puesto que el valor ms

130

Estructuras de datos con microsoft VB.NET


pequeo del rbol debe estar al final de esta ruta, al final de la misma se marca el nodo ms pequeo que es ms grande que el nodo original. (Por ejemplo si se elimina el 52). Dos casos especiales requieren de especial atencin, cuando el sucesor es el hijo derecho del nodo que se va a remover y el otro cuando el sucesor es el hijo izquierdo del nodo a remover. Primero el nodo ha de marcarse como el nodo actual. Remover este nodo del hijo derecho de su padre y apuntar al nodo sucesor del hijo derecho y asignar el apuntador al nodo sucesor. Luego se elimina el nodo actual y se asigna al nodo hijo izquierdo del nodo sucesor. Por ltimo, est el caso en que el nodo sucesor es el hijo izquierdo del nodo a remover. El algoritmo que debe seguirse es: 1. 2. 3. 4. Asignar el hijo derecho al nodo sucesor izquierdo del padre. Asignar el hijo derecho del nodo a remover al nodo hijo derecho del nodo sucesor. Remover el nodo actual del hijo derecho de su padre y apuntarlo al nodo sucesor. Remover el nodo hijo izquierdo del nodo actual y asignarlo al nodo hijo izquierdo del nodo sucesor. Aplicacin: Crear un proyecto de Windows (con el nombre WinBTree).

Crear las clases:


Public Class CNodoAB Public oDato As Object Public IZQ As CNodoAB Public DER As CNodoAB Public Function VerNodo() As String Return oDato.ToString & " " End Function End Class Public Class CArbolB Public Raiz As CNodoAB Public Sub New() Raiz = Nothing End Sub Public Sub Inserta(ByVal x As Object) Dim NodoNvo As New CNodoAB NodoNvo.oDato = x If Raiz Is Nothing Then Raiz = NodoNvo Else Dim Actual As CNodoAB = Raiz Dim Padre As CNodoAB

131

Estructuras de datos con microsoft VB.NET


Dim Insertado As Boolean = False Do While Not Insertado Padre = Actual If x < Actual.oDato Then Actual = Actual.IZQ If Actual Is Nothing Then Padre.IZQ = NodoNvo Insertado = True End If Else Actual = Actual.DER If Actual Is Nothing Then Padre.DER = NodoNvo Insertado = True End If End If Loop End If End Sub Public Sub InOrder(ByVal LaRaiz As CNodoAB, ByRef Salida As String) If Not LaRaiz Is Nothing Then InOrder(LaRaiz.IZQ, Salida) Salida += LaRaiz.VerNodo InOrder(LaRaiz.DER, Salida) End If End Sub Public Sub PreOrder(ByVal LaRaiz As CNodoAB, ByRef Salida As String) If Not LaRaiz Is Nothing Then Salida += LaRaiz.VerNodo() PreOrder(LaRaiz.IZQ, Salida) PreOrder(LaRaiz.DER, Salida) End If End Sub Public Sub PostOrder(ByVal LaRaiz As CNodoAB, ByRef Salida As String) If Not LaRaiz Is Nothing Then PostOrder(LaRaiz.IZQ, Salida) PostOrder(LaRaiz.DER, Salida) Salida += LaRaiz.VerNodo() End If End Sub Public Function Busca(ByVal k As Integer) As CNodoAB Dim Actual As CNodoAB = Raiz Do While Actual.oDato <> k If k < Actual.oDato Then Actual = Actual.IZQ Else Actual = Actual.DER End If If Actual Is Nothing Then Return Nothing End If Loop Return Actual End Function Public Function BuscaMin() As Object Dim Actual As CNodoAB = Raiz Do While Not Actual.IZQ Is Nothing Actual = Actual.IZQ Loop Return Actual.oDato End Function Public Function BuscaMax() As Object Dim Actual As CNodoAB = Raiz Do While Not Actual.DER Is Nothing Actual = Actual.DER Loop Return Actual.oDato End Function Public Function ObtenSucesor(ByVal Nodo As CNodoAB) As CNodoAB Dim PadreSucesor As CNodoAB = Nodo Dim Sucesor As CNodoAB = Nodo

132

Estructuras de datos con microsoft VB.NET


Dim Actual As CNodoAB = Nodo.DER Do While Not Actual Is Nothing PadreSucesor = Sucesor Sucesor = Actual Actual = Actual.IZQ Loop If Not Sucesor Is Nodo.DER Then PadreSucesor.IZQ = Sucesor.DER Sucesor.DER = Nodo.DER End If Return Sucesor End Function Public Function Borra(ByVal K As Object) As Boolean Dim Actual As CNodoAB = Raiz Dim Padre As CNodoAB = Raiz Dim EsHijoIzq As Boolean = True Do While Actual.oDato <> K Padre = Actual If K < Actual.oDato Then EsHijoIzq = True Actual = Actual.IZQ Else EsHijoIzq = False Actual = Actual.DER End If If Actual Is Nothing Then Return False End If Loop If Actual.IZQ Is Nothing And Actual.DER Is Nothing Then If Actual Is Raiz Then Raiz = Nothing ElseIf EsHijoIzq Then Padre.IZQ = Nothing Else Padre.DER = Nothing End If ElseIf Actual.DER Is Nothing Then If Actual Is Raiz Then Raiz = Actual.IZQ ElseIf EsHijoIzq Then Padre.IZQ = Actual.IZQ Else Padre.DER = Actual.DER End If ElseIf Actual.IZQ Is Nothing Then If Actual Is Raiz Then Raiz = Actual.DER ElseIf EsHijoIzq Then Padre.IZQ = Padre.DER Else Padre.DER = Actual.DER End If Else Dim Sucesor As CNodoAB = ObtenSucesor(Actual) If Actual Is Raiz Then Raiz = Sucesor ElseIf EsHijoIzq Then Padre.IZQ = Sucesor Else Padre.DER = Sucesor End If Sucesor.IZQ = Actual.IZQ End If Return True End Function End Class

La forma (frmBTree):

133

Estructuras de datos con microsoft VB.NET

Fig. 4.5 Controles en la forma: Nombre


txtDato btnOK

Tipo
TextBox. ReadOnly = True CaracterCasing = Upper Button CheckBox ListBox

Descripcin
Permite el ingreso de datos. Acepta el dato. Indica que los datos que se ingresan son nmeros. Muestra los datos del rbol.

lstDatos

txtSalida

btnDel btnCLS btnSave btnOpen

TextBox Multiline, ScrollBars = Both, WordWrap = False Button Button Button Button Button

Muestra diferentes recorridos del rbol.

Elimina el nodo seleccionado (en la lista). Limpia el rbol. Guarda la secuencia de datos de entrada. Abre un archivo de datos de entrada. Recorre el rbol en Postorden.

btnPostOrder Button btnInOrder Button btnPreOrder btnClose btnMax btnMin Button Cierra la aplicacin. Recorre el rbol en pre orden. Recorre el rbol en orden.

Button Button SaveFileDialog. DefaultExt = dat, Filter = Archivos de datos (*.dat)|*.dat OpenFileDialog, con las mismas especificaciones que el anterior.

Encuentra el nodo mayor Encuentra el nodo menor Dilogo para guardar archivos.

Dilogo para abrir archivos.

134

Estructuras de datos con microsoft VB.NET


Cdigo de la forma:
Public Class frmBTree Private Ruta As String, A As Integer Private Arbol As CArbolB Private Sub frmBTree_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Ruta = My.Application.Info.DirectoryPath + "\datosBT" If Not My.Computer.FileSystem.DirectoryExists(Ruta) Then My.Computer.FileSystem.CreateDirectory(Ruta) End If Ruta += "\" SaveFD.InitialDirectory = Ruta Arbol = New CArbolB End Sub Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click Dim Dato As Object Dato = txtDato.Text If chkNum.Checked Then Dato = CInt(Dato) End If Arbol.Inserta(Dato) lstDatos.Items.Add(Dato) txtDato.Clear() txtDato.Focus() End Sub Private Sub btnCLS_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCLS.Click lstDatos.Items.Clear() txtSalida.Clear() Arbol = New CArbolB txtDato.Clear() End Sub Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click If lstDatos.Items.Count > 0 Then Dim sFile As String A = SaveFD.ShowDialog If A = vbOK Then sFile = SaveFD.FileName Dim N As Short = FreeFile() FileOpen(N, sFile, OpenMode.Output) For Each Dato As Object In lstDatos.Items PrintLine(N, Dato) Next FileClose(N) MsgBox("Datos de entrada guardados", MsgBoxStyle.Information) End If End If End Sub Private Sub btnOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpen.Click A = OpenFD.ShowDialog() If A = vbOK Then Dim sFile As String = OpenFD.FileName btnCLS.PerformClick() Dim N As Short = FreeFile() FileOpen(N, sFile, OpenMode.Input) Dim Dato As Object Do While Not EOF(N) Dato = LineInput(N) If IsNumeric(Dato) Then Dato = CInt(Dato) chkNum.Checked = True

135

Estructuras de datos con microsoft VB.NET


End If Arbol.Inserta(Dato) lstDatos.Items.Add(Dato) Loop FileClose(N) End If End Sub Private Sub btnClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClose.Click Close() End Sub Private Sub btnInOrder_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnInOrder.Click txtSalida.Clear() Dim Salida As String = "" Arbol.InOrder(Arbol.Raiz, Salida) txtSalida.Text = Salida End Sub Private Sub btnPostOrder_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPostOrder.Click txtSalida.Clear() Dim Salida As String = "" Arbol.PostOrder(Arbol.Raiz, Salida) txtSalida.Text = Salida End Sub Private Sub btnPreorder_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPreorder.Click txtSalida.Clear() Dim Salida As String = "" Arbol.PreOrder(Arbol.Raiz, Salida) txtSalida.Text = Salida End Sub Private Sub txtDato_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles txtDato.KeyPress If e.KeyChar = Microsoft.VisualBasic.ChrW(Keys.Return) Then btnOK.PerformClick() End If End Sub Private Sub btnDel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDel.Click If Not lstDatos.SelectedItem Is Nothing Then Dim x As Object = lstDatos.SelectedItem Arbol.Borra(x) btnInOrder.PerformClick() lstDatos.Items.Remove(x) End If End Sub Private Sub btnMax_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMax.Click MsgBox(Arbol.BuscaMax.ToString, MsgBoxStyle.OkOnly, "MAYOR") End Sub Private Sub btnMin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMin.Click MsgBox(Arbol.BuscaMin.ToString, MsgBoxStyle.OkOnly, "MENOR") End Sub End Class

Ejecucin:

136

Estructuras de datos con microsoft VB.NET


Secuencia de entrada. (Fig. 4.4)

Fig. 4.6.

Dato no numricos:

137

Estructuras de datos con microsoft VB.NET


Secuencia de entrada.

Fig. 4.7. Aplicacin en ejecucin.

FERNANDE Z

ALVAREZ

LOPEZ

DIAZ

BERNAL

CANALES

Fig. 4.8.

138

Estructuras de datos con microsoft VB.NET

Ejercicios: 1. 2. 3. Agregar una funcin a la clase CArbolB que cuente el nmero de ramas en el rbol. Escribir un programa que lea un archivo de texto que almacene en el rbol y despliegue todas las palabras en el archivo y encuentre el nmero de veces que aparecen en el archivo. Una expresin aritmtica como 3 + 4 * 5 / 6 puede ser evaluada usando la correcta precedencia de operadores. Modifique la clase CArbolB para hacer esto.

rboles Balanceados (AVL Trees). Nombrada as (en ingls) por los dos cientficos de la computacin quienes descubrieron esta estructura da datos: G.M. Alelson-Velskii y E.M. Lands en 1962. Los rboles balanceados proporcionan otra solucin para mantener balanceados los rboles binarios. La caracterstica que define a un rbol balanceado es que la diferencia entre la altura de los sub rboles derecho e izquierdo no puede ser nunca mayor que una. Fundamentos de rboles balanceados: Para garantizar que un rbol permanece balanceado, ste compara continuamente las alturas de los sub rboles derecho e izquierdo usando una tcnica llamada rotacin para mantenerlo en balance. Para entender cmo trabaja la rotacin, considrese el ejemplo siguiente:

4 0

3 0

139

Estructuras de datos con microsoft VB.NET


Fig. 4.9. Si se inserta un valor intermedio (como 10):

4 0 3 0 1

Fig. 4.10.

El sub rbol izquierdo tiene un tamao de 2 pero el derecho lo tiene de cero, violando las reglas de los rboles balanceados. El rbol se balancea realizando una rotacin simple derecha, moviendo 40 abajo a la derecha y el 30 arriba a la derecha resultando:

3 0 1 4 0

Fig. 4.11. rbol balanceado. Otro caso:


3 0 4 3 0 4 0 2 5 0

Fig. 4.12. rbol balanceado


3 0 2 5 4 0

140

Estructuras de datos con microsoft VB.NET


Fig. 4.13. rbol balanceado. GRAFOS. Introduccin.- El estudio de redes se ha vuelto uno de los grandes temas cientficos de estudio en este milenio, an y cuando matemticos y otros han estado estudiando redes durante cientos de aos. Los recientes avances en las tecnologas de informacin (por ejemplo el internet) y en las redes sociales, popularmente concebidas en el concepto de seis grados de separacin han colocado en el foco de la atencin su estudio. DEFINICIONES. Un grafo consiste en una coleccin de vrtices y un conjunto de ramificaciones. Si se piensa en el mapa de los estados Mxico, cada poblacin est conectada con otras a travs de algn tipo de camino. Un mapa es un tipo de grafo, cada poblacin es un vrtice y el camino que conecta a dos poblaciones es una rama. Los nodos que son especificados como un par (v1 y v2), donde v1 y v2 son dos vrtices en el grafo. Un vrtice puede tambin tener adems un peso algunas veces llamado tambin costo. Un grafo cuyos pares estn ordenados se llama un grafo directo o simplemente un dgrafo. Si el grafo no est ordenado se llama un grafo desordenado o simplemente un grafo.

Fig. Grafo directo (digrafo).

Fig.

Grafo desordenado (indirecto no direccionado).

141

Estructuras de datos con microsoft VB.NET


Una ruta es una secuencia de vrtices en un grafo de manera que todos los vrtices estn conectados por ramas. El tamao (longitud) de una ruta es el nmero de ramas desde el primer al ltimo vrtice en la ruta. Una ruta puede tambin ser un vrtice en s mismo, el cual se llama un

lazo. Los lazos tienen una longitud de cero.


Un ciclo es una ruta de al menos 1 en un grafo directo para que el vrtice de inicio sea tambin el vrtice final. En un grafo directo las ramas pueden ser tambin una misma rama, pero en un grafo indirecto las ramas pueden ser distintas. Un grafo indirecto se considera conectado si existe una ruta desde cualquier vrtice a cualesquiera otros vrtices. En un grafo directo (o direccionado) a esta condicin se le llama altamente conectado. Un grafo directo que no est altamente conectado, pero es considerado conectado, se denomina

poco conectado. Si un grafo tiene una rama entre cada conjunto de vrtices se dice que es un grafo completo.
Sistemas del Mundo Real modelados con Grafos. Los grafos son usados para modelar diferentes tipos de sistemas del mundo real. Un ejemplo es el flujo de trfico. Los vrtices representan intersecciones entre calles y las ramas representan a las calles mismas. Grafos ponderados pueden usarse para representar los lmites de velocidad o el nmero de carriles o callejones. Los modeladores pueden usar el sistema para determinar las mejores rutas y las mejores calles alternas para navegar en trfico denso. Cualquier tipo de sistema de transporte puede modelarse usando un grafo. Por ejemplo, una lnea area puede modelar su sistema de vuelos usando un grafo. Cada aeropuerto en un vrtice y cada vuelo de un vrtice a otro es una rama. Una rama ponderada puede representar el costo de un vuelo desde un aeropuerto a otro, o la distancia entre uno y otro. LA CLASE GRAFO. Representacin de Vrtices: Matriz adyacente. Donde se representan los vrtices visitados (valores booleanos).- Arreglo de dos dimensiones (matriz) donde los elementos indican si existe una rama entre dos vrtices.

142

Estructuras de datos con microsoft VB.NET

V0 V0 V1 V2 V3 V4 0 0 1 0 0

V1 0 0 1 0 0

V2 1 1 0 1 1

V3 0 0 1 0 0

V4 0 0 1 0 0

Public Class CVertice Public Visitado As Boolean Public Etiqueta As String Public Sub New(ByVal Texto As String) Etiqueta = Texto Visitado = False End Sub End Class Public Class CGrafo Private Const NUM_V As Integer = 20 Private Vertices() As CVertice Private AdjMatrix(,) As Integer Private NumV As Integer Public Sub New() ReDim Vertices(NUM_V) ReDim AdjMatrix(NUM_V, NUM_V) NumV = 0 Dim i, j As Integer For i = 0 To NUM_V - 1 For j = 0 To NUM_V - 1 AdjMatrix(i, j) = 0 Next Next End Sub Public Sub AddVertex(ByVal Texto As String) Vertices(NumV) = New CVertice(Texto) NumV += 1 End Sub Public Sub AddEdge(ByVal iStart As Integer, ByVal iEnd As Integer) AdjMatrix(iStart, iEnd) = 1 AdjMatrix(iEnd, iStart) = 1 End Sub Public Sub ShoVertex(ByVal v As Integer) Console.Write(Vertices(v).Etiqueta) End Sub End Class

143

Estructuras de datos con microsoft VB.NET


Aplicacin: Clasificacin Topolgica: Una clasificacin topolgica involucra desplegar el orden especifico en el cual una secuencia de vrtices debe ser seguido en un grafo direccionado. La secuencia de cursos que un estudiante de licenciatura debe tomar para obtener el grado puede modelarse con un grafo direccionado.
Para cursar la materia de Estructuras de Datos, un estudiante debe haber cursado (y aprobado) : computadora Fundamentos Matemticas de para

Programacin

Programacin Orientada a Objetos.

En el caso de la retcula de ISC:

Fundamentos Fundamentos de Programacin de Bases de Programacin OO Datos Estructuras de Datos

Matemticas para Comp.

Lenguaje Ensamblador

144

Estructuras de datos con microsoft VB.NET


Algoritmo bsico de clasificacin topolgica: 1. 2. 3. 4. Encontrar un vrtice sin sucesores. Agregar el vrtice a la lista de los mismos. Remover el vrtice del grafo. Repetir desde el paso #1 hasta que todos los vrtices sean removidos.

FP FP OOP ED LE

OOP 1

ED 1

LE
0 1

2 3

A(0, 1) = 1 A(1, 2) = 1 A(2, 3) = 1 Vrtices: FP OOP ED LE

A(0, 1) Rama Se quita: OOP ED LE LE

FP

MoveRow y MoveCol en Del Vertex30:


0 1 2 3

OOP

ED

LE

LE

30

Mover rengln y mover columna del vrtice.

145

Estructuras de datos con microsoft VB.NET


OOP ED LE LE 1 1 1 1
0 1 2 3

BUSQUEDA EN PROFUNDIDAD (Depth-First Search)31. Esta bsqueda involucra el segur una ruta desde el vrtice inicial hasta alcanzar el ltimo vrtice, luego se regresa para seguir la siguiente ruta hasta alcanzar el ltimo vrtice y as sucesivamente hasta que no existan rutas que seguir.

Fig. En un alto nivel, la bsqueda en profundidad trabaja as: Primero se marca un punto de inicio el cual puede ser cualquier vrtice. Visitar el vrtice, apilarlo y marcarlo como visitado. Luego ir al siguiente vrtice no visitado, apilarlo y marcarlo. Esto contina hasta alcanzar el ltimo vrtice. Luego se verifica si el vrtice en el tope tiene algunos vrtices adyacentes no visitados. Si no lo hay entonces se vaca la pila y se verifican los siguientes vrtices. Si se encuentra uno, se comienzan a visitar vrtices adyacentes hasta que no existan ms sin ser visitados. Cuando finalmente se alcanza el ltimo vrtice en la pila y no hay ms vrtices adyacentes no visitados se ha completado una bsqueda en profundidad.

Public Class CGrafo Private Const NUM_V As Integer = 25 Private Vertices() As CVertice

31

McMillan.-Data Structures and Algortithms Using Visual Basic .NET.

146

Estructuras de datos con microsoft VB.NET


Private AdjMatrix(,) As Integer Private NumV As Integer . Private Function getAdjUnvisitedVertex(ByVal v As Integer) As Integer Dim j As Integer For j = 0 To NumV - 1 If AdjMatrix(v, j) = 1 And Not Vertices(j).Visitado Then Return j End If Next Return -1 End Function Public Sub DepthFirstSearch() Dim Pila As New Stack Vertices(0).Visitado = True ShoVertex(0) Pila.Push(0) Dim v As Integer Do While Pila.Count > 0 v = getAdjUnvisitedVertex(Pila.Peek) If v = -1 Then Pila.Pop() Else Vertices(v).Visitado = True ShoVertex(v) Pila.Push(v) End If Loop Dim j As Integer For j = 0 To NumV - 1 Vertices(j).Visitado = False Next End Sub 'Bsqueda a lo ancho: Public Sub BreadthFirstSearch() Dim GQ As New Queue Vertices(0).Visitado = True ShoVertex(0) GQ.Enqueue(0) Dim Vert1, Vert2 As Integer Do While GQ.Count > 0 Vert1 = GQ.Dequeue Vert2 = getAdjUnvisitedVertex(Vert1) Do While Vert2 <> -1 Vertices(Vert2).Visitado = True ShoVertex(Vert2) GQ.Enqueue(Vert2) Vert2 = getAdjUnvisitedVertex(Vert1) Loop Loop Dim I As Integer For I = 0 To NumV - 1 Vertices(I).Visitado = False Next End Sub End Class Imports System.Console Module Module1 Sub Main() ForegroundColor = ConsoleColor.Black BackgroundColor = ConsoleColor.White Clear() Dim Grafo As New CGrafo With Grafo .AddVertex("A") .AddVertex("B")

147

Estructuras de datos con microsoft VB.NET


.AddVertex("C") .AddVertex("D") .AddVertex("E") .AddVertex("F") .AddVertex("G") .AddVertex("H") .AddVertex("I") .AddVertex("J") .AddVertex("K") .AddVertex("L") .AddVertex("M") .AddEdge(0, 1) .AddEdge(1, 2) .AddEdge(2, 3) .AddEdge(0, 4) .AddEdge(4, 5) .AddEdge(5, 6) .AddEdge(0, 7) .AddEdge(7, 8) .AddEdge(8, 9) .AddEdge(0, 10) .AddEdge(10, 11) .AddEdge(11, 12) End With Grafo.DepthFirstSearch() '==== BUSQUEDA A LO ANCHO 'Grafo.BreadthFirstSearch() WriteLine() ReadKey() End Sub End Module

Otro ejemplo:

Public Class CGrafo Private Const NUM_V As Integer = 6 Private Vertices() As CVertice Private AdjMatrix(,) As Integer Private NumV As Integer Public Sub New() ReDim Vertices(NUM_V) ReDim AdjMatrix(NUM_V, NUM_V) NumV = 0 Dim i, j As Integer

148

Estructuras de datos con microsoft VB.NET


For i = 0 To NUM_V - 1 For j = 0 To NUM_V - 1 AdjMatrix(i, j) = 0 Next Next End Sub Public Sub AddVertex(ByVal Texto As String) Vertices(NumV) = New CVertice(Texto) NumV += 1 End Sub Public Sub AddEdge(ByVal iStart As Integer, ByVal iEnd As Integer) AdjMatrix(iStart, iEnd) = 1 AdjMatrix(iEnd, iStart) = 1 End Sub Public Sub ShoVertex(ByVal v As Integer) Console.Write(Vertices(v).Etiqueta) End Sub Public Function SinSucesor() As Integer Dim EsRama As Boolean Dim R, C As Integer For R = 0 To NumV - 1 EsRama = True For C = 0 To NumV - 1 If AdjMatrix(R, C) > 0 Then EsRama = True Exit For End If Next If Not EsRama Then Return -1 Else Return R End If Next End Function Private Sub MoveRow(ByVal Dim C As Integer For C = 0 To L - 1 AdjMatrix(R, C) = Next End Sub Private Sub MoveCol(ByVal Dim R As Integer For R = 0 To L - 1 AdjMatrix(R, C) = Next End Sub R As Integer, ByVal L As Integer) AdjMatrix(R + 1, C) C As Integer, ByVal L As Integer) AdjMatrix(R, C + 1)

Public Sub DelVertex(ByVal v As Integer) Dim j, R, C As Integer If v <> NumV - 1 Then For j = v To NumV - 1 Vertices(j) = Vertices(j + 1) Next For R = v To NumV - 1 MoveRow(R, NumV) Next 'NumV -= 1 For C = v To NumV - 1 'MoveCol(C, NumV - 1) MoveCol(NumV - 1, C) Next End If End Sub Public Sub TopSort() Dim OV As Integer = NumV Dim gStack As New Stack Dim sTemp As String Do While OV > 0

149

Estructuras de datos con microsoft VB.NET


Dim CurrV As Integer = SinSucesor() If CurrV = -1 Then Console.WriteLine("Error: El Grafo tiene ciclos") Exit Sub End If sTemp = Vertices(CurrV).Etiqueta gStack.Push(Vertices(CurrV).Etiqueta) DelVertex(CurrV) OV -= 1 Loop Console.WriteLine("Orden Toplogico:") Do While gStack.Count > 0 sTemp = gStack.Pop Console.Write(sTemp & " ") Loop End Sub Public Function TopSorting() As String Dim sTopS As String = "" Dim OV As Integer = NumV Dim gStack2 As New Stack Do While OV > 0 Dim CurrV As Integer = SinSucesor() If CurrV = -1 Then sTopS = "Error: El Grafo tiene ciclos" Return sTopS Exit Function End If gStack2.Push(Vertices(CurrV).Etiqueta) DelVertex(CurrV) OV -= 1 Loop '============================================ Dim Salida() As String ReDim Salida(gStack2.Count) Dim i As Short = 0 '============================================ Do While gStack2.Count > 0 Salida(i) = gStack2.Pop + " " i += 1 Loop For i = Salida.GetUpperBound(0) To 0 Step -1 sTopS += Salida(i) Next Return sTopS End Function End Class

Plan reticular.

150

Estructuras de datos con microsoft VB.NET

5 Mtodos de Ordenamiento.
Competencia especifica.- Aplicar el mtodo de ordenamiento pertinente en la solucin de un problema real.
Definicin.- Se denomina ordenamiento (sort) al proceso de ordenar una serie de datos que generalmente estn en un arreglo. Este proceso y la bsqueda (search) de algn dato en particular son probablemente las operaciones ms estudiadas en la Ciencia de la Computacin desde el principio de su era. Muchas de las estructuras que se han desarrollado en este libro fueron diseadas principalmente para ordenar y buscar datos y hacer ms eficiente el almacenamiento de datos en ellas. Aunque los investigadores en esta ciencia han desarrollado varios algoritmos sofisticados para ordenar datos, existen algunos muy simples que el estudiante debe analizar. Estos son: El sort de la burbuja y el sort por seleccin. Para probar estos algoritmos, se propone construir la siguiente aplicacin:

151

Estructuras de datos con microsoft VB.NET


Donde se puede crear un arreglo de gran tamao (relativamente) y mostrar la eficiencia de los algoritmos para ordenar y otra para probarlos analizndolos en arreglo pequeos.

152

Estructuras de datos con microsoft VB.NET


Control (nombre) frmSort NumN (1), NumM (2) Forma NumericUpDown Tipo MaximizeBox = False 1.- Maximum = 5000, Minimum = 100 (determina el Propiedades

tamao del arreglo)


2.- Maximum = 50, Minimum = 20 (el nmero de

columnas a desplegar en la caja de texto).


btnOK Button TextBox txtMin, txtMax NumTest NumericUpDown

Crea el arreglo y lo llena aleatoriamente con nmeros en el rango especificado (por defecto 1000 9999. Especifica el rango en que se generarn los nmeros en el arreglo.
Maximum = 20 (Limita a20 el tamao del arreglo de

prueba).
Minimum = 10 (El tamao mnimo del arreglo). chkTest btnCrear DGVA PB txtArreglo Button btnBSort, btnSSel Button btnQSort, btnShell PregressBar TextBox CheckBox Button DataGridView.

Determina el tipo de arreglo a crear (pequeo o grande). Crea un arreglo pequeo y lo muestra en el DataGridView.
AllowUserToAddRows = False, AutosizeColumnsMode = AllCells Visible = False BackColor = White, Multiline = True, ScrollBars = Both, WordWrap = False.

Ejecuta los mtodos de ordenamiento burbuja y seleccin.

Ejecuta los procedimientos sealados.

Ordenamiento por Seleccin. Este procedimiento se basa en la manera en se ordenan dato manualmente. Por ejemplo si se tienen las credenciales de los estudiantes de un grupo en principio desordenadas stas pueden ordenarse por apellidos (por ejemplo).
Garca Canales Puente Lpez Acevedo Bernal

Se forma una pila con estas credenciales: Garca Canales Puente Lpez Acevedo Bernal

Se toma la credencial en el tope (Garca) y se forma otra pila con ella:

153

Estructuras de datos con microsoft VB.NET


Garca

Luego se toma la siguiente (de la pila original), que en este caso es Prez y se acomoda en la segunda pila de manera que queden ordenadas:

Canales

Canales Garca Puente

Canales Garca Lpez Puente

Acevedo Canales Garca Lpez Puente

Acevedo Bernal Canales Garca Lpez Puente

Las credenciales estn ordenadas. Ejemplo con nmeros: N = 9 (10 elementos).


i 0 64 j 49 27 3 i 3 j 3 i 3 3 I 3 3 3 j i 3 j 3 i 3 j 3 3 23 23 49 49 27 27 28 64 28 29 i 6 23 49 27 28 23 49 27 23 49 27 23 23 23 49 49 49 23 23 23

1 49 64 64 64 64

2 53 53 23 23

3 27 27 49 49

4 28 28 28 28

5 70 70 70 70

6 3 3 3 27

7 29 29 29 29

8 69 59 59 59

9 64 64 64 64

En el primer recorrido (i 0) se hacen intercambios para las posiciones (j 1, 3, y 6. Para el siguiente valor de i (i 1), ocurren un slo intercambio en j 2. Para i 2, tambin ocurre un intercambio en j 3.

Siguiente recorrido de i (i 1) 23 64 64 49 49 64 64 28 27 28 64 64 70 70 70 27 27 28 29 29 29 69 69 69 64 64 64 28 70 27 27 29 29 59 69 64 64 49 49 28 70 27 27 29 29 59 59 64 64

En i 3, ocurren intercambios en j 4 y 6. Para i 4 se hace un intercambio en j 5, y en i 5 slo se intercambia para j 6. En i 6 se intercambia para j 7 y 8 y para i 7 en j 8.

28 70 i 2

28 70 i 3

i 4 64 70 28 70 i 5 70

28 64

29 29

59 59

64 64

64 70 70

29 29 64

59 59 59

64 64 64

154

Estructuras de datos con microsoft VB.NET


i 3 j 3 3 i 3 j 3 3 23 23 49 49 27 27 28 28 29 29 59 59 64 64 23 49 27 28 29 59 23 23 49 49 27 27 28 29 64 59 28 29 i 7 23 49 27 28 29 70 64 70 70 70 64 70 64 64 64 70 59 59 64 64 64 64

Implementacin:

Imports System.Console Module Module1 Sub Main() BackgroundColor = ConsoleColor.White ForegroundColor = ConsoleColor.Black Clear() Dim Arreglo() As Integer = {64, 49, 53, 27, 28, 70, 3, 29, 59, 64} Dim i, j, Temp, N As Integer N = 9 WriteLine("Arreglo desordenado:") VerArreglo(Arreglo, N) WriteLine("Valores intermedios en el arreglo:") ReadKey() For i = 0 To N - 1 For j = i + 1 To N If Arreglo(j) < Arreglo(i) Then Temp = Arreglo(i) Arreglo(i) = Arreglo(j) Arreglo(j) = Temp End If Next VerArreglo(Arreglo, N) Next WriteLine() WriteLine("Arreglo ordenado:") VerArreglo(Arreglo, N) ReadKey() End Sub Private Sub VerArreglo(ByRef Arr() As Integer, ByRef N As Integer) For i As Integer = 0 To N Write(Arr(i).ToString.PadLeft(2) & " ") Next WriteLine() End Sub End Module

Ejecucin:

155

Estructuras de datos con microsoft VB.NET

As con algunas ligeras modificaciones (quitando las relativas a la consola), se pasa este procedimiento al la forma de Windows .

Private Sub btnSSel_Click(ByVal sender Handles btnSSel.Click SortSel() End Sub Private Sub SortSel() Dim i, j, Temp As Integer

As

System.Object,

ByVal

As

System.EventArgs)

For i = 0 To N - 1 For j = i + 1 To N If Arreglo(j) < Arreglo(i) Then Temp = Arreglo(i) Arreglo(i) = Arreglo(j) Arreglo(j) = Temp End If Next Next If chkTest.Checked Then VerEnGrid() VerArreglo() Else VerArreglo() End If End Sub

156

Estructuras de datos con microsoft VB.NET

Ordenamiento de la burbuja (Bubble Sort): Este mtodo es una mejora al de seleccin en donde no siempre es necesario hacer N 1 iteraciones ya que cada vez hay un decremento en el recorrido del arreglo y cada vez que termina una iteracin, el elemento mayor queda en su lugar por lo que ya no requiere ser evaluado.

Imports System.Console Module Module1 Sub Main() BackgroundColor = ConsoleColor.White ForegroundColor = ConsoleColor.Black Clear() Dim Arreglo() As Integer = {64, 49, 53, 27, 28, 70, 3, 29, 59, 64} Dim N As Integer N = Arreglo.GetUpperBound(0) WriteLine("Arreglo desordenado:") VerArreglo(Arreglo, N) WriteLine("Valores intermedios en el arreglo:") ReadKey() Bubble(Arreglo, N) WriteLine() WriteLine("Arreglo ordenado:") VerArreglo(Arreglo, N) ReadKey() End Sub Private Sub Bubble(ByRef Arr() As Integer, ByVal N As Integer) Dim U, i, Temp, Cta As Integer

157

Estructuras de datos con microsoft VB.NET


Dim bSorted As Boolean = False U = N : Cta = 0 Do While Not bSorted For i = 0 To U - 1 If Arr(i) > Arr(i + 1) Then Temp = Arr(i) Arr(i) = Arr(i + 1) Arr(i + 1) = Temp Cta += 1 End If Next VerArreglo(Arr, N) If Cta = 0 Then bSorted = True Else Cta = 0 U -= 1 End If Loop End Sub Private Sub VerArreglo(ByRef Arr() As Integer, ByRef N As Integer) For i As Integer = 0 To N Write(Arr(i).ToString.PadLeft(2) & " ") Next WriteLine() End Sub End Module

Y en la forma:

Private Sub btnBSort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBSort.Click Burbuja() End Sub Private Sub Burbuja() 'Modificado: Dim bSorted As Boolean = False Dim U = N Dim iCta, iTemp As Integer Do While Not bSorted

158

Estructuras de datos con microsoft VB.NET


iCta = 0 For i As Integer = 0 To U - 1 If Arreglo(i) > Arreglo(i + 1) Then iTemp = Arreglo(i) Arreglo(i) = Arreglo(i + 1) Arreglo(i + 1) = iTemp iCta += 1 End If Next If iCta = 0 Then bSorted = True Else U -= 1 Cta = 0 End If Loop VerArreglo() If chkTest.Checked Then VerEnGrid() End If End Sub

Quick Sort (Ordenamiento rpido). Este mtodo tiene una merecida reputacin de ser el algoritmo ms rpido de los vistos en este captulo lo cual es verdad slo para la mayora de grandes conjuntos de datos desordenados. Si los datos son cuando mucho 100 o menos es recomendable usar cualquiera de los mtodos analizados antes. Para visualizar como opera este algoritmo, imagine que debe ordenar alfabticamente los trabajos de los estudiantes de su grupo. Se selecciona una letra intermedia del alfabeto, por ejemplo M, luego se colocan los trabajos de los estudiantes cuyos apellidos comiencen con las letras A-M en una pila y los apellidos N-Z en otra. Luego se repite el mismo proceso pero haciendo pilas ms pequeas, por ejemplo A-C, D-F, , X-Z que despus son ms fciles de ordenar. Puede verse que este es un proceso recursivo.

159

Estructuras de datos con microsoft VB.NET


Algoritmo QickSort 32 .- Dado un arreglo A[N] el siguiente algoritmo lo ordena en forma ascendente. Se asume un registro ficticio en A[N + 1] que es mayor que los dems elementos del arreglo: A[i] A[N + 1] (para toda 0 i N)
33 .

Se tienen dos parmetros LI y LS que denotan los lmites

inferior y superior de la particin que est siendo procesada. La variable K contiene el valor que ha de colocarse en su posicin final dentro de una particin. F es una variable lgica que indica el final del proceso que coloca un registro en su posicin final. Cuando se hace falso, la tabla de entrada ha sido particionada en dos partes desunidas. 1. 2. Inicio. F Verdadero Efectuar ordenamiento: Si LI LS, entonces i LI j LS + 1 K A[LI] Repetir mientras F i i + 1 Repetir mientras A[i] < K (moverse de izquierda a derecha) i i + 1 [Fin Mientras] j j -1 Repetir mientras A[j] > K j j- 1 [Fin Mientras] Si i < j entonces A[i] A[j] (se intercambian registros) De otro modo F Falso [Fin Si] [Fin Mientras] A[LI] A[j] (intercambio de registros) Llamada recursiva QuicSort(LI, j -1) Llamada recursiva QuickSort(j+1, LS) 3. Termina.

Con algunas modificaciones, este es el cdigo:

Private Sub btnQSort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnQSort.Click Dim LI As Integer = Arreglo.GetLowerBound(0) Dim LS As Integer = Arreglo.GetUpperBound(0) QSort(LI, LS) VerArreglo() End Sub Private Sub QSort(ByVal LI As Integer, ByVal LS As Integer) Dim F As Boolean, j, i, K As Integer Dim T As Integer = 0 F = True If LI < LS Then

32 33

Tremblay. Asumiendo que el arreglo comienza desde la posicin cero.

160

Estructuras de datos con microsoft VB.NET


i = LI j = LS + 1 K = Arreglo(LI) Do While F i += 1 Do While Arreglo(i) < K And i < LS i += 1 Loop j -= 1 Do While Arreglo(j) > K And j > LI j -= 1 Loop If i < j Then 'Intercambio T = Arreglo(i) Arreglo(i) = Arreglo(j) Arreglo(j) = T Else F = False End If Loop T = Arreglo(LI) Arreglo(LI) = Arreglo(j) Arreglo(j) = T QSort(LI, j - 1) QSort(j + 1, LS) End If End Sub

Arreglo desordenado:

Arreglo ordenado (con Quick Sort):

161

Estructuras de datos con microsoft VB.NET

Ordenamiento por acumulacin (heap sort). Este mtodo hace uso de una estructura de datos llamada heap (acumulacin) que es muy similar a un rbol binario pero con algunas diferencias importantes. A diferencia de los rboles binarios esta estructura es generalmente usa arreglos en lugar de nodos. Existen dos importantes condiciones para crear una acumulacin: 1. 2. Un heap debe estar completo, lo que significa que cada rengln debe estar lleno. Cada nodo contiene datos que son mayores o iguales que los datos en los nodos hijos. Por ejemplo:

10

162

Estructuras de datos con microsoft VB.NET


Heap:
5

10 00

Fig. 5.1.- Acumulacin (heap) para el arreglo

Para construir este acumulamiento34: 1. 2. 3. 4. 5. 6. 7. Repetir hasta el paso 7 mientras an exista un registro que deba ser colocado en el acumulamiento (heap). Obtener el hijo a colocar en la rama. Obtener la posicin del padre de este hijo. Repetir hasta el paso 6 mientras el hijo tenga un padre y el valor clave del hijo se mayor que su padre. Mover al padre debajo de la posicin del hijo. Obtener la posicin de un padre nuevo para el hijo. Copiar al hijo en su posicin apropiada.

Este es el cdigo:
Private Sub CrearHeap() Dim i, j, Q, K As Integer For Q = 1 To N i = Q K = Arreglo(Q) j = i \ 2 Do While i > 0 And K > Arreglo(j) Swap(i, j) i = j j = i \ 2 If j < 0 Then j = 0 End If Loop

'[1] '[2] '[3] '[4] '[5] '[6]

34

Tremblay.

163

Estructuras de datos con microsoft VB.NET


Arreglo(i) = K Next End Sub '[7]

El algoritmo Heap Sort es el siguiente: 1. 2. 3. 4. 5. 6. 7. 8. Crear el acumulamiento inicial (CrearHeap). Repetir hasta el paso 8 un total de N 1 veces. Intercambiar el primer registro con el ltimo registro no ordenado. Obtener el ndice del hijo ms grande del nuevo registro. Repetir hasta el paso 8 para los elementos desordenados en al acumulamiento (heap) y mientras el elemento actual sea mayor que el primer elemento. Intercambiar registro y obtener el hijo izquierdo siguiente. Obtener el ndice del siguiente hijo ms grande. Copiar el registro en el lugar apropiado.

Private Sub btnHeap_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnHeap.Click HeapSort() End Sub Private Sub HeapSort() Dim i, j, K, Q, T As Integer CrearHeap() For Q = N To 1 Step -1 Swap(0, Q) i = 0 K = Arreglo(i) j = 1 If (j + 1) < Q Then If Arreglo(j + 1) > Arreglo(j) Then j += 1 End If End If Do While j <= (Q - 1) And Arreglo(j) > K Swap(i, j) i = j j = 2 * i If (j + 1) < Q Then If Arreglo(j + 1) > Arreglo(j) Then j += 1 End If ElseIf j > N Then j = N End If Loop Arreglo(i) = K Next VerArreglo() End Sub

Arreglo desordenado:

164

Estructuras de datos con microsoft VB.NET


Heap Sort:

Arreglo grande:

Ordenado (Heap Sort):

Eficiencia de los diferentes mtodos de ordenamiento: Se agregan los siguientes controles a la forma:
labT1

165

Estructuras de datos con microsoft VB.NET

Ejemplo:

Private Sub Burbuja() 'Modificado: Dim Tiempo As New Stopwatch Tiempo.Start() Dim bSorted As Boolean = False Dim U = N Dim iCta, iTemp As Integer Do While Not bSorted iCta = 0 For i As Integer = 0 To U - 1 If Arreglo(i) > Arreglo(i + 1) Then iTemp = Arreglo(i) Arreglo(i) = Arreglo(i + 1) Arreglo(i + 1) = iTemp iCta += 1 End If Next If iCta = 0 Then bSorted = True Else U -= 1 iCta = 0 End If Loop Tiempo.Stop() labT1.Text = Tiempo.Elapsed.Milliseconds VerArreglo() If chkTest.Checked Then VerEnGrid() End If End Sub

As, corriendo los diferentes mtodos para arreglos de tamao 5000 y agregando las instrucciones mostradas arriba en cada uno: Burbuja:

Seleccin:

Quick Sort:

Heap Sort:

Se concluye que el Heap Sort es el ms eficiente35.

35

La velocidad de cada mtodo depende de las capacidades del equipo donde se ejecuta.

166

Estructuras de datos con microsoft VB.NET


Finalmente, para incrementar la velocidad en la visualizacin de grandes arreglos, se puede modificar el procedimiento:
Private Sub VerArreglo(Optional ByVal bCLS As Boolean = True) Dim x, i, L As Integer L = LSup.ToString.Length If bCLS Then txtArreglo.Clear() ElseIf Not chkTest.Checked Then txtArreglo.Clear() End If txtArreglo.Focus() PB.Value = 0 PB.Visible = True Dim sLine As String = "" For i = 0 To N x = Arreglo.GetValue(i) sLine += x.ToString.PadLeft(L) + " " If (i + 1) Mod C = 0 Then SendKeys.SendWait(sLine + vbCr) sLine = "" End If PB.Value += 1 Next SendKeys.SendWait(vbCr) PB.Visible = False If chkTest.Checked Then VerEnGrid() End If End Sub

Merge Sort (Mezcla). Dados dos arreglos A[N] y B[M] ordenados. 1 2 3 4 5 6 7 8 9

El ordenamiento por mezcla produce un tercer arreglo C con tamao N + M: C[N + M] que contiene los elementos de A y B ordenados: 1 2 3 4 5 6 7 8 9

167

Estructuras de datos con microsoft VB.NET


Deben recorrerse los dos arreglos (A[i], B[j], i 0,1, 2, ,N; j 0,1,2,, M) e iniciar un apuntador (k) al primer registro de C.
1. A[N] 0 1 2 1 i B[M] 0 1 2 j 4 6 3 5 2. 3 7 Iniciar ndices: (i 0, j 0, k 0 Repetir mientras no se alcancen los lmites superiores de los arreglos: Repetir Mientras i < = N Y j <= M Si A[i] < B[j] entonces C[k] A[i] De otro modo C[k] B[j] 2 8 3. 4. 5 6 5. K Fin Si K k +1 Si el arreglo A no ha completado su recorrido, pasar los elementos restantes a C[k]. C[N + M] 1 2 3 4 Si, por el contrario, el arreglo B no ha completado su recorrido, pasar los elementos restantes a C[k]. Fin

Imports System.Console Module Module1 Sub Main() BackgroundColor = ConsoleColor.White ForegroundColor = ConsoleColor.Black Clear() Dim A1() As Integer = {1, 3, 5, 7, 9, 11} Dim A2() As Integer = {2, 4, 6, 8, 10} Dim M As Integer = A1.GetUpperBound(0) + A2.GetUpperBound(0) + 1 Dim B(M) As Integer WriteLine("Arreglo 1:") VerArreglo(A1) WriteLine("Arreglo 2:") VerArreglo(A2) MergeSort(A1, A2, B) WriteLine("Mezcla:") VerArreglo(B) ReadKey() End Sub Private Sub MergeSort(ByRef Arr1() As Integer, ByVal Arr2() As Integer, ByVal ArrM() As Integer) Dim i, j, k As Integer Dim N1, N2, M As Integer N1 = Arr1.GetUpperBound(0) N2 = Arr2.GetUpperBound(0) M = ArrM.GetUpperBound(0) i = 0 : j = 0 k = 0 Do While i <= N1 And j <= N2 If Arr1(i) < Arr2(j) Then ArrM(k) = Arr1(i) i += 1 Else ArrM(k) = Arr2(j) j += 1 End If k += 1 Loop If i <= N1 Then

168

Estructuras de datos con microsoft VB.NET


Do While i <= N1 'El Arreglo 1 ArrM(k) = Arr1(i) i += 1 k += 1 Loop ElseIf j <= N2 Then 'El resto del arreglo 2 Do While j <= N2 ArrM(k) = Arr2(j) j += 1 k += 1 Loop End If End Sub Private Sub VerArreglo(ByRef Arr() As Integer) Dim i As Integer For i = 0 To Arr.GetUpperBound(0) Write(Arr(i).ToString.PadLeft(2) & " ") Next WriteLine() End Sub End Module

Ordenamiento Externo. Son algoritmos que se aplican para ordenar datos que estn almacenados en la memoria secundaria del equipo. Puede usarse cualquiera de los mtodos vistos aqu ya que un archivo puede considerarse como un arreglo en la memoria secundaria. Para mostrar estos procedimientos, se usarn archivos directos que tienen como principal caracterstica que sus registros pueden leerse o escribirse directamente en cualquier rengln.

Archivo desordenado N de Registro 1 2 3 4 5 Valor 10 4 9 3 1


Sort Externo

169

Estructuras de datos con microsoft VB.NET


Archivo Ordenado N de Registro 1 2 3 4 5 Proyecto: Valor 1 3 4 9 10

Objeto NumN1 NumN2 lstSerieA lstSerieB labN1 labN2 lamM

Tipo NumericUpDown NumericUpDown ListBox ListBox Label Label Label

Propiedades Maximun = 5000, Minimum=10, Increment =10 Maximun = 5000, Minimum=10, Increment =10

Uso Establecer el tamao del primer archivo. Establecer el tamao del segundo archivo. Mostrar archivo 1 Mostrar archivo 2 datos del datos del

Text=0 Text=0 Text=0

Muestra el n de datos del archivo 1 Datos en el archivo 2 Muestra el n de datos de la mezcla

170

Estructuras de datos con microsoft VB.NET


resultante. lstMerge txtFileA ListBox TextBox Muestra la mezcla de archivos. Para nombre archivo. txtFileB btnO K TextBox Button Para establecer el nombre del 2 archivo. Valida los nombre de los archivos y prepara al Button btnCrear Button btnMerge lstFiles btnDel btnO pen ListBox Button Button Enabled = False Enabled = False programa para generar los datos. Genera los datos de los Mezcla archivos. Muestra los archivos generados. Elimina Abre el el archivo archivo y lo seleccionado. seleccionado dos listas. rblstA, rblstB btnCLS Button RadioButton rblstA.Checked = True Determina la lista en donde se mostrar un archivo. Limpia las listas. dos los archivos dos aleatoriamente. establecer del el 1er

muestra en una de las

Public Class frmSortExt Private Structure Datos Dim Valor As Integer End Structure Private Archivo1, Archivo2, Ruta As String Private N1, N2, A As Integer Private Sub frmSortExt_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Ruta = My.Application.Info.DirectoryPath + "\Datos" If Not My.Computer.FileSystem.DirectoryExists(Ruta) Then My.Computer.FileSystem.CreateDirectory(Ruta) End If Ruta += "\" ShoFiles() End Sub Private Sub ShoFiles() lstFiles.Items.Clear() For Each sFile As String In My.Computer.FileSystem.GetFiles(Ruta, FileIO.SearchOption.SearchTopLevelOnly, "*.dat") lstFiles.Items.Add(My.Computer.FileSystem.GetName(sFile)) Next End Sub Private Sub btnCrear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCrear.Click Generar() ShoFiles() End Sub Private Sub Generar() Dim LI As Integer = 1 Dim LS As Integer = 100 Dim x, i As Integer

171

Estructuras de datos con microsoft VB.NET


'Se crea el primer archivo Dim D1 As Datos Dim D2 As Datos N1 = NumN1.Value N2 = NumN2.Value Dim NA As Integer = FreeFile() FileOpen(NA, Archivo1, OpenMode.Random, , , Len(D1)) For i = 1 To N1 x = CInt(LS - LI + 1) * Rnd() + LI D1.Valor = x FilePut(NA, D1.Valor) Next FileClose(NA) 'Segundo archivo FileOpen(NA, Archivo2, OpenMode.Random, , , Len(D2)) For i = 1 To N2 x = CInt(LS - LI + 1) * Rnd() + LI D2.Valor = x FilePut(NA, D2.Valor) Next FileClose(NA) Ordenar() End Sub Private Sub Ordenar() SortE(Archivo1) SortE(Archivo2) VerDatos(Archivo1, lstSerieA) VerDatos(Archivo2, lstSerieB) labN1.Text = lstSerieA.Items.Count labN2.Text = lstSerieB.Items.Count btnMergeSort.Enabled = True End Sub Private Sub SortE(ByVal sFile As String) 'Burbuja: Dim R As Integer Dim bSorted As Boolean = False Dim RTemp, D As New Datos Dim DA As New Datos Dim DB As New Datos Dim NA As Short = FreeFile() FileOpen(NA, sFile, OpenMode.Random, , , Len(D)) Dim N As Integer = LOF(NA) / Len(D) 'N de registros Dim U As Integer = N, iCta As Integer = 0 Do While Not bSorted For R = 1 To U - 1 FileGet(NA, DA, R) FileGet(NA, DB, R + 1) If DA.Valor > DB.Valor Then FilePut(NA, DB, R) FilePut(NA, DA, R + 1) iCta += 1 End If Next If iCta = 0 Then bSorted = True Else iCta = 0 U -= 1 End If Loop FileClose() End Sub Private Sub VerDatos(ByVal sFile As String, ByRef Lista As ListBox) Dim D As New Datos Dim NA As Short = FreeFile() FileOpen(NA, sFile, OpenMode.Random, , , Len(D)) Dim N As Integer = LOF(NA) / Len(D) 'N de registros Dim R As Integer Lista.Items.Clear() For R = 1 To N FileGet(NA, D, R)

172

Estructuras de datos con microsoft VB.NET


Lista.Items.Add(D.Valor) Next FileClose(NA) End Sub Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click Archivo1 = Ruta + txtFileA.Text.Trim Archivo2 = Ruta + txtFileB.Text.Trim If Archivo1.Length > 0 Then ValidarExt(Archivo1) If My.Computer.FileSystem.FileExists(Archivo1) Then If Not Borrar(Archivo1) Then Exit Sub End If End If Else MsgBox("Falta nombre de archivo 1") Exit Sub End If If Archivo2.Length > 0 Then ValidarExt(Archivo2) If My.Computer.FileSystem.FileExists(Archivo2) Then If Not Borrar(Archivo2) Then Exit Sub End If End If Else MsgBox("Falta nombre de archivo 2") Exit Sub End If btnCrear.Enabled = True End Sub Private Function Borrar(ByVal sFile As String) As Boolean A = MsgBox(My.Computer.FileSystem.GetName(sFile) + " ya existe" + vbCr _ + "Lo elimna", MsgBoxStyle.YesNo) If A = vbYes Then My.Computer.FileSystem.DeleteFile(sFile) lstFiles.Items.Remove(My.Computer.FileSystem.GetName(sFile)) Return True Else Return False End If End Function Private Sub ValidarExt(ByRef sFile As String) Dim x As Integer = InStrRev(sFile, ".") If x = 0 Then sFile += ".dat" ElseIf Mid(sFile, x + 1, 3) <> "dat" Then Mid(sFile, x + 1, 3) = "dat" End If End Sub Private Sub btnDel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDel.Click If Not lstFiles.SelectedItem Is Nothing Then A = MsgBox("Elimina archivo", MsgBoxStyle.YesNo) If A = vbYes Then Dim sFile As String = Ruta + lstFiles.SelectedItem My.Computer.FileSystem.DeleteFile(sFile) lstFiles.Items.Remove(lstFiles.SelectedItem) End If End If End Sub Private Sub btnOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpen.Click If Not lstFiles.SelectedItem Is Nothing Then If rbLstA.Checked Then Archivo1 = Ruta + lstFiles.SelectedItem VerDatos(Archivo1, lstSerieA)

173

Estructuras de datos con microsoft VB.NET


btnMergeSort.Enabled = True labFileA.Text = My.Computer.FileSystem.GetName(Archivo1) Else Archivo2 = Ruta + lstFiles.SelectedItem VerDatos(Archivo2, lstSerieB) btnMergeSort.Enabled = True labFileB.Text = My.Computer.FileSystem.GetName(Archivo2) End If labN1.Text = lstSerieA.Items.Count labN2.Text = lstSerieB.Items.Count End If End Sub Private Sub btnMergeSort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMergeSort.Click MergeSort() End Sub Private Sub MergeSort() Dim NR1, NR2, NA1, NA2, NAM, i, j, k As Integer Dim D1, D2, MS As Datos Dim sFileMerge As String sFileMerge = InputBox("Nombre de la mezcla", "Nuevo archivo", "Merge1") If sFileMerge <> "" Then sFileMerge = Ruta + sFileMerge ValidarExt(sFileMerge) If My.Computer.FileSystem.FileExists(sFileMerge) Then My.Computer.FileSystem.DeleteFile(sFileMerge) End If NA1 = FreeFile() FileOpen(NA1, Archivo1, OpenMode.Random, , , Len(D1)) NR1 = LOF(NA1) / Len(D1) NA2 = FreeFile() FileOpen(NA2, Archivo2, OpenMode.Random, , , Len(D2)) NR2 = LOF(NA2) / Len(D2) NAM = FreeFile() FileOpen(NAM, sFileMerge, OpenMode.Random, , , Len(MS)) i = 1 : j = 1 : k = 1 Do While i <= NR1 And j <= NR2 FileGet(NA1, D1, i) FileGet(NA2, D2, j) If D1.Valor < D2.Valor Then FilePut(NAM, D1, k) i += 1 Else FilePut(NAM, D2, k) j += 1 End If k += 1 Loop If i <= NR1 Then Do While i <= NR1 FileGet(NA1, D1, i) FilePut(NAM, D1, k) i += 1 k += 1 Loop ElseIf j <= NR2 Then Do While j <= NR2 FileGet(NA2, D2, j) FilePut(NAM, D2, k) j += 1 k += 1 Loop End If FileClose() ShoFiles() VerDatos(sFileMerge, lstMerge) labM.Text = lstMerge.Items.Count End If End Sub

174

Estructuras de datos con microsoft VB.NET


Private Sub btnCLS_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCLS.Click lstSerieA.Items.Clear() lstSerieB.Items.Clear() lstMerge.Items.Clear() btnMergeSort.Enabled = False End Sub End Class

La aplicacin funciona de la siguiente manera: 1. 2. Escribir los nombres del par de archivos a generar. Seleccionar

3. 4. 5.

Generar los datos aleatoriamente Mezclar archivos. previo). Cuando se abre un archivo, previamente debe seleccionarse la lista donde ser desplegado. (se pide el nombre del archivo resultante, si existe elimina el

175

Estructuras de datos con microsoft VB.NET

Ejercicio: Modifique el mtodo de ordenamiento usado en esta aplicacin y cmbielo por: QuickSort HeapSort

176

Estructuras de datos con microsoft VB.NET

6 Mtodos de Bsqueda.
Competencia especifica.- Aplicar el mtodo de bsqueda pertinente en la solucin de un problema real. Competencia especfica: Aplicar el mtodo de bsqueda pertinente en la solucin de un problema real.
Introduccin.- La bsqueda y recuperacin de datos es una tarea fundamental en programacin y es una de las que ms ha sido estudiada. Existen bsicamente dos formas de buscar datos en una lista (o arreglo); la bsqueda secuencial y la

bsqueda binaria. La primera se usa cuando los datos no estn ordenados, la segunda es usada
cuando los datos estn ordenados. Bsqueda Secuencial. Este mtodo es bastante fcil de implementar ya que consiste en recorrer el arreglo hasta encontrar el elemento que se busca: Para ejemplificar lo anterior, se utilizar la misma aplicacin de la Unidad V (Ordenamiento), agregando los siguientes controles en la parte inferior de la forma:

Objeto txtLoc btnBSec btnBBins labTB

Tipo TextBox Button Button Label

Propiedades

Enabled = False BordeStyle = Fixed3D, TextAlignment = MiddleCenter, Text=0

Private Sub btnBSec_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBSec.Click If IsNumeric(txtLoc.Text) Then Dim L As Integer = LSup.ToString.Length Dim y As Integer = txtLoc.Text Dim i As Integer, bFound As Boolean = False Dim k, x, z As Integer Dim Tiempo As New Stopwatch Tiempo.Start() For i = 0 To Arreglo.GetUpperBound(0) If Arreglo(i) = y Then bFound = True

177

Estructuras de datos con microsoft VB.NET


Exit For End If Next Tiempo.Stop() labTB.Text = Tiempo.Elapsed.Milliseconds If bFound Then MsgBox("Elemento encontrado en posicin " + i.ToString) 'Para marcarlo en el TextBox: Marcarlo(i, L, y) Else MsgBox(y.ToString + " no existe en el arreglo", MsgBoxStyle.Information) End If Else MsgBox("Debe ingresar un valor numrico", MsgBoxStyle.Information) txtLoc.Focus() End If End Sub

Private Sub Marcarlo(ByVal P As Integer, ByVal L As Integer, ByVal x As Integer) Dim z, k As Integer Dim d1, d2 As String d1 = x.ToString.PadLeft(L) z = InStr(txtArreglo.Text, d1) d2 = txtArreglo.Text.Substring(z - 1, L + 1) If d1.Trim <> d2.Trim Then Do 'z = InStr(z, txtArreglo.Text, " ") z = InStr(z + 1, txtArreglo.Text, d1) d2 = txtArreglo.Text.Substring(z - 1, L + 1) Loop Until d1.Trim = d2.Trim End If txtArreglo.Focus() txtArreglo.SelectionStart = z - 1 txtArreglo.SelectionLength = x.ToString.PadLeft(L).Length End Sub

Arreglo desordenado:

Buscar x = 3: Bsqueda Binaria. Se aplica nicamente sobre arreglos ordenados. La idea es seguir un procedimiento similar a buscar un telfono especfico en un directorio telefnico. As si se desea buscar el telfono de Prez Alcocer Alicia no se busca pgina por pgina sino que se van abriendo pginas de la A-Z, luego se parte a la mitad esa seccin, resultando por ejemplo M Z, descartando la primera mitad y se repite el proceso, por ejemplo M R hasta llegar a la P. Luego en esos apellidos no leemos

178

Estructuras de datos con microsoft VB.NET


secuencialmente, sino que se va dividiendo la lista hasta tener a la vista los apellidos P y lo calizar (si existe) el telfono deseado. As, se lleva este procedimiento a un arreglo A[N] (ordenado), deben establecerse los lmites de la bsqueda que al principio son 0 y N:
0 1 2 3 4 5 6 7 8 9

10

A estos lmites los representamos por las variables iMin e Max. iMin 0: iMax 9 (N) Luego se divide el arreglo en dos mitades, esta posicin se representa por iMit: Donde iMit TRUNC (iMin + iMax) / 2 Luego: iMit (0+9)/2 = 4 (valor truncado) Si x representa el valor a buscar, entonces se prueba la mitad en que debera estar si existiera: Si x < A[iMit] entonces (debera encontrarse en la primera mitad). Descartar la segunda mitad: iMin iMit + 1 De otro modo, Si x > A[iMit] entonces (debera encontrarse en la segunda mitad). Descartar la primera mitad: iMax iMit 1 De otro modo ( x = A[iMit]), el dato ha sido localizado. Fin Si Y este proceso deber repetirse mientras el dato no sea localizado e iMin <= iMax. As, para activar la bsqueda binaria, agregar la siguiente lnea a todos los mtodos de ordenacin:
Private Sub btnHeap_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnHeap.Click HeapSort() btnBBin.Enabled = True End Sub

Private Sub btnBBin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBBin.Click Dim x As Integer = txtLoc.Text BinarySearch(x) End Sub

179

Estructuras de datos con microsoft VB.NET


Private Sub BinarySearch(ByVal x As Integer) Dim L As Integer = LSup.ToString.Length Dim iMin, iMax, iMit As Integer Dim bFound As Boolean = False iMin = 0 : iMax = N Dim Tiempo As New Stopwatch Tiempo.Start() Do While Not bFound And iMin <= iMax iMit = (iMin + iMax) \ 2 If x < Arreglo(iMit) Then iMax = iMit - 1 ElseIf x > Arreglo(iMit) Then iMin = iMit + 1 Else bFound = True End If Loop Tiempo.Stop() labTB.Text = Tiempo.ElapsedMilliseconds If bFound Then Dim i As Integer = Array.IndexOf(Arreglo, x) MsgBox("Elemento en posicin " + i.ToString) Marcarlo(i, L, x) Else MsgBox("No se encontr " + x.ToString) End If End Sub

Arreglo ordenado:

Bsqueda por Funciones Hash. Introduccin36. El hash es una tcnica para almacenar y recuperar datos rpidamente. Esta utiliza una estructura de datos llamada tabla hash. An y cuando estas tablas proporcionan mtodos de insercin, remocin y
36

McMillan.

180

Estructuras de datos con microsoft VB.NET


recuperacin resulta pobre para operaciones que involucran la bsqueda de datos mnimo mximo (por ejemplo). Las libreras del marco .NET proporciona una clase muy poderosa para trabajar con tablas hash. Tabla Hash.- Es una estructura desarrolla alrededor de un arreglo que consiste de varios elementos (0 a N) y debe poder cambiar su tamao tanto como sea necesario. Cada dato almacenado en el arreglo se basa en una parte del dato denominado clave. Para almacenar algn elemento en la tabla hash, la clave es mapeada sobre alguna posicin en el rango 0 a N por medio de una funcin denominada funcin hash. Idealmente una funcin hash almacena cada clave en su propia celda en el arreglo. Sin embargo, dado que existe un nmero ilimitado de claves posibles y un nmero finito de celdas en el arreglo, una meta ms realista de esta funcin ese el intentar en lo posible distribuir uniformemente las claves en las celdas de un arreglo. Adems, con todo y se tenga una buena funcin hash es probable que dos claves tengan el mismo valor hash. A esto se le llama colisin y debe tenerse una estrategia para manejarla cuando ocurra. Por ltimo, debe determinarse que tan grande debe ser el tamao del arreglo usado como tabla hash. Es recomendable que este tamao sea un nmero primo. Eleccin de una Funcin Hash. La eleccin de una funcin hash se basa en el tipo de dato de la clave que ser usada. Si se trabaja con nmeros enteros la funcin ms simple debe retornar un valor como x mod N donde x es la clave a insertar. Existen circunstancias, sin embargo, donde este mtodo no es recomendable, por ejemplo cuando todas las claves terminan en 0 y el tamao del arreglo es 10. Esta es una de las razones por las que N debera ser un nmero primo. Por otro lado, si las claves son nmeros enteros aleatorios, la funcin hash debera distribuir ms eficientemente las claves. En muchas aplicaciones, las claves son de tipo cadena (string), en cuyo caso resulta ms difcil elegir una funcin hash que opere sobre estas claves y debe elegirse cuidadosamente. Una funcin simple que parece trabajar bien, consiste en sumar los valores ASCII de las letras en la clave y el valor retornado por la misma es el mdulo aritmtico de esa suma y el valor de N:

Private Function HashSimple(ByVal s As String, ByVal Arr() As String) As Integer Dim T, i As Integer For i = 0 To s.Length - 1 T += Asc(s.Chars(i)) Next Return T Mod Arr.GetUpperBound(0) End Function

181

Estructuras de datos con microsoft VB.NET


Y su uso sera:
Option Strict On Imports System.Console Module Module1 Sub Main() ForegroundColor = ConsoleColor.Black BackgroundColor = ConsoleColor.White Clear() Dim Nombres(9) As String, Nombre As String Dim VariosNombres() As String = {"Ricardo", "Ana", "Alicia", "Susana", "Sandra", "Carolina", "Karen", "Carla", "Yolanda", "Margarita"} Dim HashVal, i As Integer For i = 0 To 9 Nombre = VariosNombres(i) HashVal = HashSimple(Nombre, Nombres) Nombres(HashVal) = Nombre Next VerDist(Nombres) WriteLine() Write("Buscar: ") Nombre = ReadLine() If HashSearch(Nombre, Nombres) Then WriteLine("Dato encontrado") Else WriteLine("Dato no encontrado") End If ReadKey() End Sub Private Function HashSimple(ByVal s As String, ByVal Arr() As String) As Integer Dim T, i As Integer For i = 0 To s.Length - 1 T += Asc(s.Chars(i)) Next Return T Mod Arr.GetUpperBound(0) End Function Private Sub VerDist(ByVal Arr() As String) Dim i As Integer For i = 0 To Arr.GetUpperBound(0) If Arr(i) <> "" Then WriteLine(i & " " & Arr(i)) End If Next End Sub

Para localizar una clave, slo se invoca a la funcin hash y se compara el valor de esa celda con el dato a buscar:
Private Function HashSearch(ByVal s As String, ByVal Arr() As String) As Boolean Dim H As Integer H = HashSimple(s, Arr) If Arr(H) = s Then Return True Else Return False End If End Function

182

Estructuras de datos con microsoft VB.NET


El primer problema que se observa es que no se despliegan todos los datos. Lo interesante es que si se cambia N a un nmero primo < 99 todos los nombre son almacenados adecuadamente.

Dim Nombres(91) As String, Nombre As String

El tamao que finalmente sea elegido depende del nmero de registros que se van almacenar en la tabla hash, un nmero seguro parece ser 10, 007 que es primo y los requerimientos de memoria no son lo suficientemente grandes como para afectar el rendimiento del programa:
Dim Nombres(10007) As String, Nombre As String

Con la misma idea de usar el cmputo de los valores ASCII de la clave, el siguiente algoritmo proporciona un mejor hash:
Private Function Hash2(ByVal s As String, ByVal Arr() As String) As Integer Dim i As Integer, T As Long For i = 0 To s.Length - 1 T += 37 * T + Asc(s.Chars(i)) Next T = T Mod Arr.GetUpperBound(0) If T < 0 Then

183

Estructuras de datos con microsoft VB.NET


T += Arr.GetUpperBound(0) End If Return CInt(T) End Function

Esta funcin utiliza la regla de Horner37 para calcular la funcin polinomial de 37. Lneas que se modifica:
HashVal = Hash2(Nombre, Nombres) H = Hash2(s, Arr)

Y se observa una mejor distribucin de las claves.

Cuando se almacenan ms datos la probabilidad de que ocurran colisiones es alta, para resolver este problema se pueden usar cubos (buckets). Un cubo es una estructura de datos simple almacenada en un elemento de una tabla hash que puede almacenar tems mltiples. En la mayora de las implementaciones esta estructura es a su vez un arreglo pero es mejor usar un arreglo lista (ArrayList), as se evita el problema de requerir ms memoria en caso de ser necesario. Para insertar un tem, primero se usa la funcin para determinar en qu ubicacin del arreglo lista ha de almacenarse, luego se verifica si esa ubicacin ya est ocupada. Si lo est no se hace nada, si no se invoca al mtodo Add del arreglo lista. Para remover un tem, de nuevo se obtiene su valor hash y se revisa el arreglo lista para asegurarse que ese tem existe y liego se elimina.

37

http://www.physics.utah.edu/~detar/lessons/c++/array/node4.html

184

Estructuras de datos con microsoft VB.NET

Public Class CBucketHash Private Const Tam As Integer = 101 Private Dato() As ArrayList Public Sub New() Dim i As Integer ReDim Dato(Tam) For i = 0 To Tam - 1 Dato(i) = New ArrayList(4) Next End Sub Private Function Hash(ByVal s As String) As Integer Dim i As Integer, Tot As Long For i = 0 To s.Length - 1 Tot += 37 * Tot + Asc(s.Chars(i)) Next Tot = Tot Mod Dato.GetUpperBound(0) If Tot < 0 Then Tot += Dato.GetUpperBound(0) End If Return CInt(Tot) End Function Public Sub Insertar(ByVal Item As String) Dim H As Integer H = Hash(Item) If Not Dato(H).Contains(Item) Then Dato(H).Add(Item) End If End Sub Public Sub Remover(ByVal Item As String) Dim H As Integer H = Hash(Item) If Dato(H).Contains(Item) Then Dato(H).Remove(Item) End If End Sub Public Sub VerDist(ByVal Arr() As String) Dim i, H As Integer, s As String For i = 0 To Tam - 1 If Dato(i).Count > 0 Then For j As Integer = 1 To Dato(i).Count s = Dato(i).Item(j - 1) Console.WriteLine(i & " " & j & " " & s) Next End If Next End Sub End Class

Cuando en el

se

usan

cubos, lista

el

nmero de elementos usados arreglo debe mantenerse tan bajo como sea posible ya que esto minimiza el trabajo extra que se tiene que hacer cuando se agregan o eliminan hash. lista En tems de la tabla este cdigo, el se

minimiza el tamao del arreglo estableciendo valor inicial a 1 en el constructor. Luego, una vez que se tienen colisiones contina vez. El radio del nmero de la capacidad del cada arreglo lista se hace 2 y as duplicndose

elementos en la tabla hash se denomina Diferentes demostrado

factor
que

de
un

carga.
han mejor

estudios

rendimiento en una tabla hash se logra cuando el factor de carga es 1.0 cuando el tamao de la tabla es exactamente igual al nmero de elementos.

Option Strict On Imports System.Console Module Module1 Private MiHash As New CBucketHash Sub Main() ForegroundColor = ConsoleColor.Black BackgroundColor = ConsoleColor.White Clear() Dim Nombres(99) As String, Nombre As String Dim VariosNombres() As String = {"Ricardo", "Ana", "Teresa", "Susana", "Sandra", "Carolina", "Martha", "Julian", "Yolanda", "Margarita"} Dim i As Integer For i = 0 To VariosNombres.GetUpperBound(0) Nombre = VariosNombres(i) MiHash.Insertar(Nombre) Next MiHash.VerDist(VariosNombres) ReadKey() End Sub End Module

185

Estructuras de datos con microsoft VB.NET

Colisiones.

La Clase HashTable (.NET). La clase HashTable es un tipo especial del objeto Dictionary que almacena pares de valores de claves. Dado que esta clase es bastante eficiente, debera ser usada en aplicaciones que requieran tablas hash. Cmo instanciar y agregar datos a un objeto HashTable:
Private MiHash As New CBucketHash Private MiHash As New CBucketHash(71) Private MiHash As New CBucketHash(23, 3.0)

La primera lnea crea una tabla hash con su capacidad y factor de carga por defecto. La segunda lnea crea una tabla hash con capacidad para 71 elementos y un factor de carga por defecto. Y la tercera lnea crea una tabla hash con una capacidad inicial de 23 elementos y un factor de carga de 3.0. Uso:

Option Strict On Imports System.Collections Imports System.Console Module Module1

Se enumeran consecutivamente los datos

para que la salida corresponda a cada Sub Main() alumno. ForegroundColor = ConsoleColor.Black BackgroundColor = ConsoleColor.White Clear() Dim Claves() As String = {"Nombre1", "Edad1", "Carrera1"} Dim AA As New ArrayList Dim Alumnos As New Hashtable(17) Alumnos.Add("01Nombre", "Olga Zuiga") Alumnos.Add("02Edad", 19) Alumnos.Add("03Carrera", "ISC") Alumnos.Add("04Gnero", "F") Alumnos.Add("05Nombre", "Sandra Alvarez")

186

Estructuras de datos con microsoft VB.NET


Alumnos.Add("06Edad", 20) Alumnos.Add("07Carrera", "INF") Alumnos.Add("08Gnero", "F") Alumnos.Add("09Nombre", "Pedro Garza") Alumnos.Add("10Edad", 21) Alumnos.Add("11Carrera", "ISC") Alumnos.Add("12Gnero", "M") For Each de As DictionaryEntry In Alumnos AA.Add(de.Key) Console.WriteLine("Key = {0}, Value = {1}", _ de.Key, de.Value) Next de AA.Sort() WriteLine() For Each K As String In AA WriteLine(K & " " & Alumnos.Item(K).ToString) Next ReadKey() End Sub End Module

Aplicacin: Crear un glosario de palabras reservadas de VB.NET (utilizando la ayuda). Esta aplicacin comienza creando un archivo de texto (usando el bloc de notas y guardando las definiciones en formato UTF-8.

187

Estructuras de datos con microsoft VB.NET


No debe haber espacios en blanco al final del archivo y ste debe guardarse en una ubicacin fcil de encontrar. En la aplicacin de muestra se guardo en la misma ubicacin del ejecutable. Para esto debe crearse un proyecto nuevo:

Una vez que se cambie el nombre a la forma por defecto, debe guardarse el proyecto en una ubicacin conocida.

ListBox. Sorted = True. Font Consolas 9

txtDef (TextBox). MultiLine = True, ScrollBars = Verticarl, Font = Consolas, 9

Option Strict On Imports System.IO Imports System.Collections Public Class frmGlosario Inherits System.Windows.Forms.Form Private Glosario As New Hashtable

188

Estructuras de datos con microsoft VB.NET


Private Sub frmGlosario_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load CrearGlosario() VerPalabras() End Sub Private Sub CrearGlosario() Dim Archivo As StreamReader Dim sLine As String Dim Palabras() As String Archivo = File.OpenText(My.Application.Info.DirectoryPath & "\glosario.txt") Do While Archivo.Peek <> -1 sLine = Archivo.ReadLine Palabras = sLine.Split(","c) Glosario.Add(Palabras(0), Palabras(1)) Loop Archivo.Close() End Sub Private Sub VerPalabras() For Each K As Object In Glosario.Keys lstTerminos.Items.Add(K) Next If lstTerminos.Items.Count > 0 Then lstTerminos.SelectedIndex = 0 End If End Sub 'Procedimiento de evento Private Sub lstTerminos_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles lstTerminos.SelectedIndexChanged Dim Termino As Object = lstTerminos.SelectedItem txtDef.Text = CStr(Glosario.Item(Termino)) End Sub End Class

Ejecucin:

Ejercicios:

189

Estructuras de datos con microsoft VB.NET


1. 2. Re escribir este programa pero usando la clase CBucketHash desarrollada antes en esta unidad. Usando la clase HashTable escribir un programa que verifique la ortografa de algunas palabras, que las lea desde un archivo de texto y verifique errores ortogrficos. El lmite del diccionario debe ser slo de algunas palabras comunes. La ortografa es para palabras en espaol.

190

Estructuras de datos con microsoft VB.NET

7 Anlisis de los Algoritmos.


Competencia Especfica: Comprender la complejidad de los algoritmos e identificar la eficiencia de los mismos.
Introduccin. Se sabe que un algoritmo es una secuencia de instrucciones que tiene como objetivo resolver un problema y que puede haber diferentes algoritmos que lo pueden resolver. Saber cul de estos algoritmos es mejor requiere poder en cierto modo cuantificar su eficiencia de manera que se pueda calificar su eficiencia. Eso es la complejidad. Al tiempo que consume un algoritmo para resolver un problema se le denomina complejidad

temporal y a la cantidad de memoria que requiere el algoritmo se le denomina complejidad espacial.


Un concepto que se usa en este tipo de anlisis se conoce como el tamao del problema. Todo problema requiere datos de entrada pare resolverlo, as por ejemplo cuando ordenamos arreglos 38 los diferente algoritmos que se usan pueden requerir un tiempo ms o menos igual para arreglos pequeos, por ejemplo N = 100. Sin embargo cuando se ordenan arreglos grandes las diferencias de tiempo son evidentes. Por ejemplo, para un arreglo de tamao 5000, se tienen los tiempos siguientes para ordenarlo (tomados del programa desarrollado en la Unidad V): Modo Seleccin Burbuja QuickSort HeapSort Tiempo (ms) 246 318 100 6

El tamao del arreglo, incide directamente en el tiempo de ejecucin. Se puede concluir que HeapSort es el ms eficiente en cuanto a lo temporal. Algunos lenguajes (como .NET) contienen libreras sumamente eficientes para resolver una serie de problemas, cual simplifica enormemente la tarea de desarrollar grandes aplicaciones. As por ejemplo, agregando lo siguiente a esa aplicacin:

Private Sub btnSortNet_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSortNet.Click Dim Tiempo As New Stopwatch Tiempo.Start()

38

Unidad V.

191

Estructuras de datos con microsoft VB.NET


Array.Sort(Arreglo) Tiempo.Stop() VerArreglo() labTB.Text = Tiempo.ElapsedMilliseconds End Sub End Class

El cual tarda 0 ms en ejecutarse. Claramente una situacin real es el mejor. La complejidad, por otro lado, no es un nmero es una funcin y sus valores dependen de en qu equipo se ejecuta as los valores obtenidos difieren de acuerdo al equipo. Cada problema tiene uno varios valores que determinan su tamao y se calcula de un tamao genrico y no concreto, as por ejemplo la complejidad de los algoritmos de ordenacin se calcula en base a un arreglo de tamao N y no de 5, 10 5000. Un problema generalmente usado para ejemplificar la complejidad de un algoritmo consiste en encontrar el n-simo trmino de una sucesin de Fibonacci. 1
0

1/3
2

1/5
3

1/8
4

La complejidad en el tiempo depende de cmo se resuelva este problema (por ejemplo una funcin iterativa una recursiva).

Imports System.Console
Module Module1

Module Module1 Sub Main() ForegroundColor = ConsoleColor.Black BackgroundColor = ConsoleColor.White Clear() Dim T As New Stopwatch Dim N As Integer = 37 T.Start() WriteLine("Iterativa_") Dim FBNI As Long = FiboIter(N) WriteLine(T.ElapsedMilliseconds) T.Stop() WriteLine(FBNI) WriteLine() WriteLine("Recursiva") T.Start() Dim FBR As Long = FiboRec(N) T.Stop() WriteLine(FBR) WriteLine(T.ElapsedMilliseconds)

192

Estructuras de datos con microsoft VB.NET


ReadKey() End Sub Private Function FiboIter(ByVal N As Integer) As Long Dim i As Integer Dim Valores(N) As Integer If N = 1 Or N = 2 Then Return 1 Else Valores(1) = 1 Valores(2) = 2 For i = 3 To N - 1 Valores(i) = Valores(i - 1) + Valores(i - 2) Next Return Valores(N - 1) End If End Function Private Function FiboRec(ByVal N As Integer) As Long If N < 2 Then Return N Else Return FiboRec(N - 1) + FiboRec(N - 2) End If End Function End Module

El tiempo requerido para completar cada tarea depende del valor N (en este caso 37) que se va a calcular (adems de la potencia del equipo donde se ejecuta).

Otra medida de la complejidad son el nmero de instrucciones necesarias que un algoritmo necesita para completar su tarea:

Claramente, el sort por seleccin es menos complejo en el espacio, y adems debe considerarse que en el HeapSort se invoca al procedimiento CrearHeap.

193

Estructuras de datos con microsoft VB.NET


Esta complejidad se mide por el nmero de lneas que se ha requerido para resolver el problema. Adems se considera el nmero de ciclos e instrucciones If-Then-Else involucradas. PSP (Personal Software Process) es una herramienta que proporciona varias mtricas para medir la complejidad de un programa39. Otro caso que puede ejemplificar el concepto de complejidad es el programa de sort externo, que agregndole algunas pocas lneas nos puede mostrar que el tiempo requerido est en funcin del tamao de los archivos:

Se observa que entre ms grandes sean los tamaos de los archivos, el proceso de sort externo tarda ms. Una solucin a este problema sera implementar un sort ms rpido (como el heap sort). Aunque el nmero de lneas ser mayor.

Por otro lado, la recuperacin de los datos iniciales desde un archivo existente, es ms rpida que los procesos anteriores porque los datos ya estn ordenados.

39

Ingeniera de Software.

194

Estructuras de datos con microsoft VB.NET


Aunque se tarda ms en mostrar los datos desde el archivo, se ahorra el tiempo del sort (que ya no se realiza). Y cuando se abre la mezcla desde un archivo40 el tiempo es mucho menor que el obtenido por el proceso (porque ya no se efecta).

Ciertos autores sealan que la complejidad de algoritmos es muy til en el nivel terico pero que no es conveniente obsesionarse demasiado en un nivel prctico. Para cada algoritmo existe un par de medidas generales: El peor de los casos que se denota con la notacin (O micrn Big-O). El mejor de los casos denotado por (omega)

En general es imprescindible conocer el peor de los casos ya que proporciona una visin de lo que puede pasar cuando las cosas van realmente mal. Ejemplo: Para una cierta cantidad de datos n, la desviacin estndar de estos puede medirse por:

Pero tambin se puede encontrar por:

Con la primera ecuacin:


40

Debe modificarse el programa (unas pocas lneas) para medir este tiempo.

195

Estructuras de datos con microsoft VB.NET

Con la segunda:

A medida que se incrementa N (1)

(2)

Este es el cdigo:

196

Estructuras de datos con microsoft VB.NET


Public Class frmStat Dim N As Integer, Datos() As Integer Dim sMedia As Single, sDS As Single Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click N = NumN.Value - 1 GeneraDatos() End Sub Private Sub GeneraDatos() Dim Tiempo As New Stopwatch Tiempo.Start() ReDim Datos(N) Dim LI As Integer = 1 Dim LS As Integer = 1000 Dim x, i As Integer For i = 0 To N x = CInt(Int(LS - LI + 1) * Rnd() + LS) Datos(i) = x lstDatos.Items.Add(x) Next sMedia = Media() 'sDS = sDesv() sDS = sDev2() Tiempo.Stop() labMedia.Text = sMedia.ToString("n2") labdDev.Text = sDesv.ToString("n4") labT.Text = Tiempo.ElapsedMilliseconds End Sub Private Function Media() As Single Dim SX As Integer = 0 For i As Integer = 0 To N SX += Datos(i) Next Return SX / N End Function Private Function sDesv() As Single Dim SX2 As Integer = 0, i As Integer For i = 0 To N SX2 += (Datos(i) - sMedia) ^ 2 Next Return Math.Sqrt(SX2) / N - 1 End Function Private Function sDev2() As Single Dim SX2 As Long = 0, s2 As Single Dim i As Integer For i = 0 To N SX2 += Datos(i) ^ 2 Next s2 = (SX2 - N * sMedia ^ 2) / (N - 1) Return Math.Sqrt(s2) End Function End Class

Este proceso puede mejorarse si, por ejemplo se calcula x2 al momento de ingresar los datos:

197

Estructuras de datos con microsoft VB.NET


Estos son los cambios:
Private Sub GeneraDatos() Dim SX2 As Long = 0 Dim Tiempo As New Stopwatch Tiempo.Start() ReDim Datos(N) Dim LI As Integer = 1 Dim LS As Integer = 1000 Dim x, i As Integer For i = 0 To N x = CInt(Int(LS - LI + 1) * Rnd() + LS) Datos(i) = x SX2 += x ^ 2 lstDatos.Items.Add(x) Next sMedia = Media() 'sDS = sDesv() sDS = sDev2(SX2) Tiempo.Stop() labMedia.Text = sMedia.ToString("n2") labdDev.Text = sDesv.ToString("n4") labT.Text = Tiempo.ElapsedMilliseconds End Sub La funcin que calcula la Private Function sDev2(ByRef SX2 As Long) As Single Dim s2 As Single s2 = (SX2 - N * sMedia ^ 2) / (N - 1) Return Math.Sqrt(s2) End Function desviacin estndar se reduce, adems, considerablemente.

As, el primer intento con la ecuacin 1 repesentara el peor de los casos, y la ltima modificacin ser el mejor de los casos. Ejercicio: Para el problema de encontrar una ecuacin de ajuste con regresin lineal mltiple41, se tiene el siguiente mtodo42: Ecuacin general de ajuste:

Para J variables independientes (X1, X2, , Xj), la varia dependiente Y. Para la ecuacin anterior utilizando a como una estimacin de y bj como una estimacin de j , las ecuaciones normales son:

..

41 42

Unidad I. Richard L. Mils. Estadstica para economa y administracin. McGraw Hill

198

Estructuras de datos con microsoft VB.NET

Si se usa lgebra de matrices. Estas ecuaciones pueden describirse como:

n X1 A= X2 ... Xj

X1 X12 X1X2 ... X1Xj

X2 X1X2 X22 ... X1Xj

... ... ... ... ...

Xj X1Xj X2Xj ... Xj2

a b1 Z= b2 . . . bj Yd=

Y YX1 YX2 . . . YXj

Entonces pueden resolverse las ecuaciones por: . . . (1)

Para simplificar este caso, considrese el caso de tres variables: Y = Consumo anual de carne X1 = Un ndice del precio al por menor de carne X2 = ndice del precio al por menor de la carne de cerdo. Estos son los datos histricos de los ltimos 5 aos (x10)- hipotticos Consumo de carne Y 6 5 4 3 7 Precio de la carne X1 1 1 2 2 4 Precio del cerdo. X2 1 2 1 2 9

Clculos preliminares:

199

Estructuras de datos con microsoft VB.NET

Y 6 5 4 3 7 25

X1 1 1 2 2 4 10

X2 1 2 1 2 9 15

YX1 6 5 8 6 28 53

YX2 6 10 4 6 63 89

X1 1 1 4 4

X2 1 4 1 4

X1X2

36 25 16 9 49 135

16 26

81 91

1 2 2 4 36 45

Las matrices resultantes son:

A=

5 10 15

10 26 45

15 45 91

d=

25 53 89

El resultado es (de la ecuacin 1):

Escribir un programa que lea los valores de muestra (Y, X1, X2) y obtenga los valores de Z siguiendo esta metodologa y luego comprelo con el mostrado en la pgina 58. Cul algoritmo es ms eficiente?

200

Das könnte Ihnen auch gefallen