Está en la página 1de 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.

Comprender el problema.

2.

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.

Cmo se organizan los datos en relacin a otros.

2.

Cules datos son calculados necesariamente.

3.

Cules datos permanecen en memoria.

4.

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

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


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.

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.

Que datos son necesarios (entradas).

2.

Que datos se esperan en la solucin.

3.

Que valores son calculados en los procesos de solucin.

4.

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:

Datos de entrada:
P1 y P2 definidos por
pares

de

Distancia entre P1 y P2

Recta

(d).

valores

Pendiente de la recta (m).

numricos para (x, y) y


(x, y)

Ecuacin: y = mx + b

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

x = 1, y =

d=

Recta

m=1

x = 5, y
=5

y=x

Algoritmos

Definicin del objeto Recta:

Recta
Propiedades
Nombre

Mtodos

Tipo de dato

Nombre

Tipo de dato

Propsito

X1

Nmero real simple

Distancia

Real simple

Calcula distancia

X2

Nmero real simple

Pendiente

Real simple

Obtiene m

Y1

Nmero real simple

Ecuacin (Ec)

Cadena

Ecuacin resultante

Y2

Nmero real simple

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.

Calcular la distancia usando [1].

3.

Calcular la pendiente usando [3].

4.

A partir de las ecuaciones [4] [5] obtener la ecuacin de la recta como una cadena de
caracteres.

5.

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

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

Tipo
Form

txtX1, txtY1
txtX1, txtY2
btnResult
labD, labM

Textbox
TextBox
Buttton
Label

Propiedades
MaximizeBox = False
StartPosition = CenterScreen
TextAlign = Center
TextAlign = Center
AutoSize = False

13

Propsito

Capturar X1
Capturar Y2
Iniciar mtodos
Mostrar distancia y

Estructuras de datos con microsoft VB.NET

labEc

Label

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

Pendiente.

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

correspondiente.

texto
Dimetro

(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

GroupBox.

en

un

Estructuras de datos con microsoft VB.NET


Valores de la propiedad Tag sugeridos

Tag en RadioButton
Nombre

Tag

rbVol

rbV

rbAltura

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

seleccionar

esta

opcin,

los

objetos de texto para el volumen y


el

rea

son

desactivados

(propiedad ReadOnly = True) por el


mdulo SetTextos. De esta manera,
el usuario slo puede ingresar los
valores conocidos (propiedades del
TDA).

desarrollados en la clase y muestra los resultados faltantes.

18

El botn

desencadena los

mtodos

(operaciones)

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:

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

Dimetro

altura

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

Posiciones

Ei

En

Elementos

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.

La memoria asignada

de forma esttica no se libera sino hasta que la ejecucin del programa

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()

El ciclo For-Each itera


sobre cada elemento del

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

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:

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

10

15

10

15

20

Al comprimirlo resultara en:


15

10

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.

Hacer m 0 (contador de elementos eliminados)

2.

Recorrer el arreglo para i 0, 1, , N 2 (hasta el penltimo elemento).

3.

Recorrer el arreglo hacia adelante para j i + 1, i + 2, , i + (N 1) (hasta el ltimo


elemento)
a.

Si A[i] no es nada (Si A[j] Nada entonces A[j] Nada: m m + 1

4.

Crear el arreglo temporal de resultados: B[N m]

5.

Llenarlo con los valores del arreglo original diferentes de nada.

6.

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

-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.

Establecer el tamao del arreglo en base al grado del polinomio (m). N m + 1.

2.

Crear el arreglo y asignar los coeficientes. A[i] ai

3.

Inicializar el valor de la expresin: P 0

4.

Leer un valor para X

5.

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


Dim
Dim
m =
For

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

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

Divisor

Cociente

Residuo

Arreglo de residuos

1024

512

512

256

256

128

178

64

64

32

32

16

16

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

Char en donde se almacenarn los

Do

residuos (convirtindolos con el mtodo

'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.

ToString..
N representa el tamao del arreglo
anterior y no afecta a los objetos

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

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

Uso

Num

Entero

El nmero decimal que se va a usar. Se pasa como una copia del valor

largo

ingresado en la forma principal (ByVal), por lo tanto el valor original no es


afectado.

Base

Entero

Base a la que se convierte (2 u 8).

corto

Arr()

Objeto

El arreglo principal de esta aplicacin. Al pasarse por referencia ( ByRef) los


cambios que se hagan en afectan al arreglo inicial.

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()

Agrega un elemento a la lista

AddRange

Agrega los elementos de una coleccin al fina de un ArrayList

Capacity

Almacena el nmero de elementos que un ArrayList puede manejar

Clear()

Elimina todos los elementos del ArrayList

Contains()

Determina si un tem especfico existe en el arreglo

CopyTo()

Copia el ArrayList un segmento de ste a un arreglo

Count

Es el nmero de elementos actualmente en la lista

GetEnnumerator

Regresa un enumerador para iterar sobre un ArrayList

GetRange()

Devuelve un subconjunto del ArrayList como otro ArrayList

IndexOf()

Devuelve el ndice de la primera ocurrencia de un tem especfico

Insert

Inserta un elemento en un ndice especificado

37

Estructuras de datos con microsoft VB.NET


InsertRange()

Inserta los elementos de una coleccin dentro de un ArrayList comenzando en un


ndice especfico

Item()

Obtiene o establece un elemento en el ndice especificado

Remove()

Elimina la primera ocurrencia de un tem especfico

RemoveAt()

Elimina el elemento con el ndice especificado

Reverse()

Invierte el orden de los elementos en el ArrayList

Sort()

Ordena alfabticamente los elementos en ele arreglo

ToArray()

Copia los elementos de un ArrayList a un arreglo

TrimToSize()

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

Tipo

Nombre

Texto

Apellido

Texto

Calif

Entero corto (rango 0 a 100)

Mtodos
MiNombre

Apellido + Nombre (Texto)

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

(TextBox,

CharacterCasing

=Upper)
txtNom (igual a la anterior)
NumCalif

(NumericUpDown

Maximum

=100)
btnOK (Button).
txtLoc (igual las anteriores)
btnFind (Button

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

(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

(Button)

btnMenor

(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

valor

numrico

de

la

columna Calif se establece con


las

DefaultCellStyle.

Funcionamiento:

40

propiedades

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.

A=

a11

a12

ain

a21

a22

a2n

an1

an2

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

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

numricos

(NumericIpDown) de nombre NumN. Crear primero este control y despus copiarlo y pegarlo en la
forma modificando luego sus propiedades Name a NumM y NumK.
Propiedades del control numricos NumN.

Propiedad

Valor

Maximum

10

Minimum

TextAlign

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

Valor

En

AllowUserToAddRows

False

diferentes algoritmos que muestran el

AllowUserToResizeRows

False

manejo de

AutCellsColumnMode

AllCells

podrn guardar en archivos y recuperarse

MultiSelect

False

Tag11

esta

ventana

se

podrn

probar

este tipo de arreglos. Se

en otro momento.
A para DGVA, B para DGVB
Esta forma manejar tres matrices:
btnSuma

A[N, M), B([M, K) y R[ , ] cuyo orden


depender del resultado de la operacin

btnProd

que se realice.

btnInvA

GroupBox
Name = GpoOp
Enabled = False

btnGuardar
btnAbrir

11

Sin comillas.

49

Suma

Multiplicacin

Inversa

Otros problemas a resolver.

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

X1

X2

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

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.

btnArreglos.- Muestra los valores de los arreglos X y Y. (Enabled = False).

2.

btSave.- Guarda los datos iniciales (los arreglos X y Y). Enabled = False

3.

btnOpen.- Recupera el archivo de datos.

4.

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.

Valores de N y M.

2.

El arreglo X.

3.

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.

Crea la transpuesta de X.

2.

La multiplica por X y por Y para obtener XX y Xy.

3.

Obtiene la inversa de XX.

4.

Multiplica la inversa por el arreglo Xy para obtener el arreglo de resultados, B.

5.

Forma los DatagridVew necesarios para mostrar resultados intermedios y el resultado final
el arreglo B.

6.

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

Propiedades

Descripcin

TextBox

Name = txtNum, TextAlign = Center, Text =0

NumericUpDown

Name = NumB, Maximum =9,

Minimum

Captura el nmero a convertir


=2,

La base.

TextAlign =Center
Button

Name = btnConvert

Button

Name = btnNew

Label

Name

labResult,

Inicia el clculo.
Nuevo cmputo.
BorderStyle

Fixed3D,

BackColor = Honeydew, TextAlign = TopCenter.

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

1.0

0.001

1.5

0.001

2.5

0.001

225

14.2

.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:

71

entonces el nmero de

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

Carolina

Juan

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

de

Propiedades

Descripcin

TextBox

Name = txtDato

Captura de datos

Button

Name = btnInserta

Insertar el dato en la lista

ListBox

Name = LaLista

Desplegar la lista actual

Button

Name=btnRemove

Quita el elemento seleccionado

inters

de la lista.
Button

Name=New

Prepara una lista nueva

Button

Name=btnSave

Guarda la lista actual

Button

Name=btnOpen

Abre una lista

Button

Name=btnClose

Cierra la ventana

Label

Name=labTL

Para

OpenFileDialog

Name=SaveFD,

mostrar

el

total

de

elementos en la lista.
Filter=Archivo

de

datos

Ubicacin del archivo a crear.

(*.dat)|*.dat
DefaultExt=dat
SaveFileDialog

Name=SaveFD e iguales propiedades que el

Selecciona

anterior.

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.

Obtener un nodo nuevo y establecer sus campos.

2.

Si la lista est vaca entonces insertar el nodo y actualizar sus ligas derecha e izquierda.

3.

Si el nodo a insertar est al frente de la lista, entonces insertar el nodo y actualizar sus
apuntadores.

4.

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.

Crear un nodo nuevo y ubicar el ltimo elemento de la lista (U).

b.

Crear otro nodo nuevo con la informacin de Nuevo [NodoNuevo(Nuevo)].

c.

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.

Crear un nodo nuevo para ubicar al elemento despus del cual se insertar el nodo nuevo (U).

b.

Crear otro nodo nuevo con la informacin de Nuevo. (NodoNuevo).

c.

Buscar U.

d.

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:

Alicia

Header

Juan

Alicia

Header

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

almacenados-

txtDato
btnDel
btnModificar

btnSave

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

87

de

una

lista)

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,

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

97

Minimum

=0,

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

lo que desencadena un evento

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.

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.

Crear una lista circular de N elementos (N>10) con los nombres de los que sern
ejecutados.

2.

Establecer cada cuantos son eliminados (M).

3.

Repetir mientras el tamao de la lista sea >M.

4.

a.

Recorrer la lista cada m-simo elemento agregarlo a un ListBox

b.

Agregar ese nombre a otra lista (yo utilic un ArrayList)

c.

Al terminar el recorrido eliminar la seleccin de la lista circular (que est en el ArrayList)

d.

Vaciar el ArrayList.

e.

Mostrar la lista circular restante

FIN

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

2 Tope

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

Precedencia

Rango

+, -

-1

*, /

-1

a, b, c,

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.

Inicializar el contenido de la pila con #

2.

Extraer el smbolo ms a la izquierda de expresin infija (smbolo de entrada actual).

3.

Repetir hasta el paso 6 mientras el smbolo de entrada <>#

4.

Remover y sacar todos los smbolos en la pila cuya precedencia sea mayor o igual al valor de
precedencia del valor del smbolo actual.

5.

Colocar en la pila el smbolo actual.

6.

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.

Inicializar la PILA:
PILA.PUSH(#)

2.

Inicializar la cadena de salida y el contador de rangos:


POLISH
Rango 0

3.

Obtener el primer smbolo:


Actual SIGUIENTE(INFIJA)

4.

Traducir la expresin infija:


Repetir hasta el paso 6 mientras Actual #

5.

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

Precedencia de entrada

Funcin de precedencia en la pila

Funcinde Rango

+, -

-1

*,-

-1

-1

a,b,c,

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.

Inicializar PILA:
PILA.PUSH(()

2.

Inicializar la cadena de salida y contador de rangos.


POLACA

26

Tremblay

115

Estructuras de datos con microsoft VB.NET


Rango 0
3.

Obtener smbolo de entrada:


Actual SIGUIENTE

4.

Traducir la expresin infija:


Repetir hasta el paso 7 mientras Actual

5.

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.

Obtener siguiente smbolo de entrada:


Actual SIGUIENTE

8.

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"

117

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

'5]

'[6]

'[7]
'[8]

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.

Se inicializa una pila

2.

Se recorre la expresin polaca de izquierda a derecha

3.

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

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

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

Siguientes smbolos que se extraen:


e

R2

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

R2

Siguiente smbolo (h) se apila:


h

R1

R1

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

10

R1

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

pueden construirse con ayuda de pilas como lo muestra el

siguiente ejemplo:
En la unidad II se mostr el algoritmo recursivo para la funcin Factorial:

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

Unidad II.

28

J.P. Tremblay.

125

Estructuras de datos con microsoft VB.NET

1.

Guardar N y regresar direccin:


P.PUSH(TEMP_REC)

2.

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.

Calcular N!
FACTORIAL N * FACTORIAL

4.

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

Director de

Direccin de

Finanzas

Produccin

Ventas

F
Fig. 4. 1

29

Jefe de operaciones

Cair/Guardati. Estructuras de datos. McGraw Hill.

127

Soporte tcnico

Estructuras de datos con microsoft VB.NET

Otro tipo de rboles puede definirse en otros trminos:


Nodo Raz
M

T
C

F
E

Sub-rbol

Fig 4.2
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

17

80

75

40

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.

Nodo a eliminar

(No se puede eliminar


el sub-rbol).

5
0
4

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.

Asignar el hijo derecho al nodo sucesor izquierdo del padre.

2.

Asignar el hijo derecho del nodo a remover al nodo hijo derecho del nodo sucesor.

3.

Remover el nodo actual del hijo derecho de su padre y apuntarlo al nodo sucesor.

4.

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

Tipo

Descripcin

txtDato

TextBox. ReadOnly = True


CaracterCasing = Upper
Button
CheckBox

Permite el ingreso de datos.

btnOK

Acepta el dato.
Indica que los datos que se ingresan son
nmeros.
Muestra los datos del rbol.

lstDatos

ListBox

txtSalida

Muestra diferentes recorridos del rbol.

btnDel

TextBox
Multiline,
ScrollBars = Both,
WordWrap = False
Button

btnCLS

Button

Limpia el rbol.

btnSave

Button

Guarda la secuencia de datos de entrada.

btnOpen

Button

Abre un archivo de datos de entrada.

Button

Recorre el rbol en Postorden.

Button

Recorre el rbol en orden.

Button

Recorre el rbol en pre orden.

Button

Cierra la aplicacin.

Button

Encuentra el nodo mayor

Button

Encuentra el nodo menor

SaveFileDialog. DefaultExt =
dat, Filter = Archivos de
datos (*.dat)|*.dat

Dilogo para guardar archivos.

OpenFileDialog,
con
las
mismas especificaciones que
el anterior.

Dilogo para abrir archivos.

Elimina el nodo seleccionado (en la lista).

btnPostOrder

btnInOrder

btnPreOrder
btnClose
btnMax
btnMin

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

LOPEZ

ALVAREZ

DIAZ

BERNAL

CANALES

Fig. 4.8.

138

Estructuras de datos con microsoft VB.NET

Ejercicios:
1.

Agregar una funcin a la clase CArbolB que cuente el nmero de ramas en el rbol.

2.

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.

3.

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
0

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
4

Fig. 4.11. rbol balanceado.


Otro caso:
3
0
4
0

3
0
4
0
2
5

Fig. 4.12. rbol balanceado


3
0
2

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

V1

V2

V3

V4

V0

V1

V2

V3

V4

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) :

Fundamentos

de

Programacin

Matemticas

computadora

Programacin Orientada a Objetos.

En el caso de la retcula de ISC:

Fundamentos
Fundamentos
de

de Bases de
Programacin
OO

Datos
Estructuras

Programacin

de Datos

Matemticas

Lenguaje

para Comp.

Ensamblador

144

para

Estructuras de datos con microsoft VB.NET


Algoritmo bsico de clasificacin topolgica:
1.

Encontrar un vrtice sin sucesores.

2.

Agregar el vrtice a la lista de los mismos.

3.

Remover el vrtice del grafo.

4.

Repetir desde el paso #1 hasta que todos los vrtices sean removidos.

FP

OOP

ED

LE

FP

OOP

ED

2
3

LE

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:

30

OOP

ED

LE

LE

Mover rengln y mover columna del vrtice.

145

Estructuras de datos con microsoft VB.NET


OOP

ED

LE

LE

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

Tipo

Propiedades

Forma

MaximizeBox = False

NumericUpDown

1.- Maximum = 5000, Minimum = 100 (determina el

tamao del arreglo)

NumN (1), NumM (2)

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

columnas a desplegar en la caja de texto).


btnOK

Button

Crea el arreglo y lo llena aleatoriamente con nmeros en


el rango especificado (por defecto 1000 9999.

TextBox

Especifica el rango en que se generarn los nmeros en el


arreglo.

NumericUpDown

Maximum = 20 (Limita a20 el tamao del arreglo de

txtMin, txtMax
NumTest

prueba).
Minimum = 10 (El tamao mnimo del arreglo).
chkTest
btnCrear

CheckBox

Determina el tipo de arreglo a crear (pequeo o grande).

Button

Crea un arreglo pequeo y lo muestra en el DataGridView.

DataGridView.

AllowUserToAddRows = False, AutosizeColumnsMode =


AllCells

DGVA
PB

PregressBar

Visible = False

TextBox

BackColor = White, Multiline = True, ScrollBars = Both,

txtArreglo

WordWrap = False.
Button

Ejecuta los mtodos de ordenamiento burbuja y seleccin.

Button

Ejecuta los procedimientos sealados.

btnBSort, btnSSel

btnQSort, btnShell

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

Canales

Acevedo

Acevedo

Garca

Garca

Canales

Bernal

Puente

Lpez

Garca

Canales

Puente

Lpez

Garca

Puente

Lpez
Puente

Las credenciales estn ordenadas.


Ejemplo con nmeros:
N = 9 (10 elementos).
i

En el primer recorrido (i 0) se hacen intercambios

64

49

53

27

28

70

29

69

64

para las posiciones (j 1, 3, y 6.

49

64

53

27

28

70

29

59

64

27

64

23

49

28

70

29

59

64

64

23

49

28

70

27

29

59

64

59

64

Para el siguiente valor de i (i 1), ocurren un slo


intercambio en j 2.

Siguiente recorrido de i (i 1)
i

Para i 2, tambin ocurre un intercambio en j 3.

64

23

23

64

49

49

28

70

27

29

28
70
i 2

27

29

59

64

28

70

27

Para i 4 se hace un intercambio en j 5, y en i 5

23

64

49

23

49

64

29

59

64

28
70
i 3

27

29

69

64

23

49

64

28

70

27

29

69

64

23

49

28

64

70

27

29

69

64

23

49

27

64

70

28

29

69

64

70

28

29

59

64

64

29

59

64

64

29

59

64

i 4

slo se intercambia para j 6.


En i 6 se intercambia para j 7 y 8 y para i 7 en j
8.

En i 3, ocurren intercambios en j 4 y 6.

23

49

27

64

j
3

23

49

27

28
70
i 5

23

49

27

28

70

j
3

23

49

27

28

64

70

29

59

64

23

49

27

28
29
i 6

70

64

59

64

154

Estructuras de datos con microsoft VB.NET


i

23

49

27

28

29

70

64

59

64

23

49

27

28

29

64

70

59

64

23

49

27

28
29
i 7

59

70

64

64

23

49

27

28

59

70

64

64

29

23

49

27

28

29

59

64

70

64

23

49

27

28

29

59

64

64

70

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,

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

ByVal

As

System.EventArgs)

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.

Inicio.
F Verdadero

2.

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

Tremblay.

33

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.

Un heap debe estar completo, lo que significa que cada rengln debe estar lleno.

2.

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.

Repetir hasta el paso 7 mientras an exista un registro que deba ser colocado en el
acumulamiento (heap).

2.

Obtener el hijo a colocar en la rama.

3.

Obtener la posicin del padre de este hijo.

4.

Repetir hasta el paso 6 mientras el hijo tenga un padre y el valor clave del hijo se mayor que
su padre.

5.

Mover al padre debajo de la posicin del hijo.

6.

Obtener la posicin de un padre nuevo para el hijo.

7.

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

34

Tremblay.

163

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

Estructuras de datos con microsoft VB.NET


Arreglo(i) = K
Next
End Sub

'[7]

El algoritmo Heap Sort es el siguiente:


1.

Crear el acumulamiento inicial (CrearHeap).

2.

Repetir hasta el paso 8 un total de N 1 veces.

3.

Intercambiar el primer registro con el ltimo registro no ordenado.

4.

Obtener el ndice del hijo ms grande del nuevo registro.

5.

Repetir hasta el paso 8 para los elementos desordenados en al acumulamiento (heap) y


mientras el elemento actual sea mayor que el primer elemento.

6.

Intercambiar registro y obtener el hijo izquierdo siguiente.

7.

Obtener el ndice del siguiente hijo ms grande.

8.

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

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

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.

A[N]
0 1 2

1.

Iniciar ndices: (i 0, j 0, k 0

2.

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

2
j

C[k] B[j]

B[M]
0 1

Fin Si
K k +1

3.

Si el arreglo A no ha completado su recorrido, pasar los elementos


restantes a C[k].

C[N + M]
1 2 3 4

4.
5

los elementos restantes a C[k].

6
5.

Si, por el contrario, el arreglo B no ha completado su recorrido, pasar


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

Valor

10

Sort Externo

169

Estructuras de datos con microsoft VB.NET


Archivo Ordenado
N de Registro

Valor

10

Proyecto:

Objeto

Tipo

Propiedades

Uso

NumN1

NumericUpDown

Maximun = 5000, Minimum=10,

Establecer el tamao

Increment =10

del primer archivo.

Maximun = 5000, Minimum=10,

Establecer el tamao

Increment =10

del segundo archivo.

NumN2
lstSerieA

NumericUpDown
ListBox

Mostrar

datos

del

datos

del

archivo 1
lstSerieB

ListBox

Mostrar
archivo 2

labN1

Label

Text=0

Muestra el n de datos

labN2

Label

Text=0

Datos en el archivo 2

lamM

Label

Text=0

Muestra el n de datos

del archivo 1

de

170

la

mezcla

Estructuras de datos con microsoft VB.NET


resultante.
lstMerge

ListBox

txtFileA

TextBox

Muestra la mezcla de
archivos.
Para

establecer

nombre

del

el
1er

archivo.
txtFileB

TextBox

Para

establecer

el

nombre del 2 archivo.


btnO

Button

Valida los nombre de

los archivos y prepara


al

programa

para

generar los datos.


Button

Enabled = False

Genera los datos de

btnCrear

los

dos

archivos

aleatoriamente.
Button

Enabled = False

Mezcla

btnMerge

los

dos

archivos.

lstFiles

ListBox

Muestra los archivos


generados.

btnDel

Button

Elimina

el

archivo

seleccionado.
btnO

Button

Abre

pen

el

archivo

seleccionado

lo

muestra en una de las


dos listas.
rblstA,

RadioButton

rblstA.Checked = True

rblstB

Determina la lista en
donde se mostrar un
archivo.

btnCLS

Button

Limpia las listas.

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.

Escribir los nombres del par de archivos a generar.

2.

Seleccionar

3.

Generar los datos aleatoriamente

4.

Mezclar archivos.

(se pide el nombre del archivo resultante, si existe elimina el

previo).
5.

Cuando se abre un archivo, previamente debe seleccionarse la lista donde ser desplegado.

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

Tipo

txtLoc

TextBox

btnBSec
btnBBins
labTB

Propiedades

Button
Button

Enabled = False

Label

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 localizar
(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

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

se

usan

cubos,

el

nmero de elementos usados


en

el

arreglo

lista

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.

tems de la tabla

En

este

cdigo,

se

minimiza el tamao del arreglo


lista

estableciendo

el

valor

inicial a 1 en el constructor.
Luego, una vez que se tienen
colisiones

la

capacidad

del

arreglo lista se hace 2 y as


contina

duplicndose

cada

vez.
El

radio

del

nmero

de

elementos en la tabla hash se

factor

denomina

de

Diferentes

estudios

demostrado

que

un

carga.
han
mejor

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.

Re escribir este programa pero usando la clase CBucketHash desarrollada antes en esta unidad.

2.

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

Tiempo (ms)

Seleccin

246

Burbuja

318

QuickSort

100

HeapSort

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

1/3

1/5

1/8

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

Unidad I.

42

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:

A=

X1

X2

...

Xj

X1

X12

X1X2

...

X1Xj

X2

X1X2

X22

...

X2Xj

...

...

...

...

...

Xj

X1Xj

X1Xj

...

Xj2

b1
Z=

YX1

b2

Yd=

YX2

bj

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

Precio de

Precio del

de carne

la carne

cerdo.

X1

X2

Clculos preliminares:

199

Estructuras de datos con microsoft VB.NET

YX2

X1

X2

X1X2

36

10

25

16

28

63

49

16

81

25

10

15

53

89

135

26

91

1
2
2
4
36
45

X1

X2

YX1

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

También podría gustarte