Java Script
Java Script
1. INTRODUCCIÓN
recibir datos
acción 1
[condición 3]
[else] [condición1]
[condición 7]
[condición2]
proceso 1 acción 3
[condición4]
[condición 5]
acción 4
[condición 12]
[condición6]
[condición13] [condición8]
[condición9]
[condición10]
proceso 2
[condición11]
1.6.1. Variables
1.6.2. Operadores
% : Residuo de la división
++ : Incremento
-- : Decremento
Los cuatro primeros permiten realizar las operaciones básicas, el quin-
to “%” devuelve el residuo de la división (entera o real), el operador
“++” incrementa en uno el valor de una variable numérica, mientras que “—
-“ disminuye en uno el valor de una variable numérica.
Los dos últimos operadores (“++” y “--“) tienen un comportamiento que
varía en función a si son escritos como prefijo (antes) o sufijo (después)
de la variable: si se encuentran como prefijo primero incrementan (o dis-
minuyen) el valor de la variable y luego realiza las operaciones con el
nuevo valor de la variable, mientras que como sufijo primero realiza las
operaciones con el valor original de la variable y luego incrementa o
disminuye su valor.
A más del operador de asignación (“=”), en JavaScript se cuentan con
los operadores de asignación compuestos:
+= : Suma y asignación (x+=5; equivale a x=x+5;)
-= : Resta y asignación (x-=5; equivale a x=x-5;)
*= : Multiplicación y asignación (x*=5; equivale a x=x*5;)
/= : División y asignación (x/=5; equivale a x=x/5;)
%= : Residuo y asignación (x%=5; equivale a x=x%5;)
}
Esta estructura realiza una iteración por cada elemento que existe en
el “objeto”, recuperando en la variable “atributo”, una a una, las pro-
piedades del objeto. Si el objeto es un vector o texto, los atributos son
los índices del vector, es decir números enteros consecutivos, comenzando
en 0.
Para salir del interior de un ciclo, sin que se cumpla la condición del
mismo, se escribe el comando “break”. Cuando Javascript encuentra este
comando, termina inmediatamente la ejecución del ciclo y pasa a ejecutar
la siguiente instrucción del programa (la que está después del ciclo).
Para continuar con el siguiente ciclo, sin terminar el ciclo actual, se
escribe el comando “continue”. Cuando Javascript encuentra el comando
“continue” pasa inmediatamente al siguiente ciclo, dejando sin ejecutar
las instrucciones restantes.
1.6.12.Ciclos infinitos
for (;;) {
instrucciones;
if (condición) break;
instrucciones;
}
Observe que en el caso de la estructura “for”, para crear un ciclo in-
finito, simplemente se dejan en blanco los sectores de inicialización,
condición e incremento.
1.6.13.Funciones
function nombre_de_la_funcion(lista_de_parámetros) {
instrucciones;
}
Donde “nombre_de_la_función” es el nombre que se da a la función y cuya
denominación sigue las mismas reglas que las variables.
La “lista_de_parámetros” son los nombres de las variables donde se
guardan los datos que se mandan a la función. Dichos nombres deben estar
separados por comas.
Para que devuelver un resultado desde una función se emplea el comando
“return”, de acuerdo a la sintaxis:
return valor_o_expresión;
Cuando Javascript encuentra este comando termina la ejecución de la
función y devuelve el “valor_o_expresión”. El “valor_o_expresión” puede
ser un valor literal (por ejemplo un número o texto), una variable (cuyo
valor es devuelto) o una expresión (que es evaluada y cuyo resultado es
devuelto).
Si en una función no se escribe el comando “return”, la función termina
al ejecutarse su última línea de código sin devolver ningún resultado.
Como se dijo, en la calculadora Javascript no se pueden crear funciones
en la forma estándar, por lo que deben ser creadas en la forma literal,
de acuerdo a la siguiente sintaxis:
var variable=function nombre_de_la_funcion(lista_de_parámetros) {
instrucciones;
}
Como se puede ver, la única diferencia con relación a la forma estándar,
es que la función es asignada a una variable (se le da un alias), enton-
ces la función puede ser llamada indistintamente con el “nom-
bre_de_la_función” o el “nombre_de_la_variable” (el alias). Por eso, en
esta forma, casi siempre se omite el “nombre_de_la_función” (es decir que
se crea una función anónima).
var variable=function (lista_de_parámetros) {
instrucciones;
}
Finalmente una función puede ser creada también de la siguiente forma:
var variable = new Function(“par1”,“par2”,…,“parn”, “instrucciones”);
Donde “par1”, “par2”,…,”parn” son los parámetros de la función e “ins-
trucciones” son las instrucciones Javascript, es decir el código de la
función. Esta forma permite crear funciones en tiempo de ejecución: fun-
ciones dinámicas, las cuales, a diferencia de las formas estándar y lite-
ral, son siempre globales. Esta forma de crear funciones Javascript no se
utiliza muy frecuentemente.
En Javascript (a diferencia de C) las funciones pueden ser anidadas, es
decir se puede crear una función dentro de otra (excepto, por supuesto
con la última forma, que siempre crea funciones globales).
Una vez repasados los fundamentos del lenguaje, se pueden elaborar al-
gunos programas básicos en Javascript.
Como ya se dijo, Javascript es un lenguaje que corre en los navegadores
INTRODUCCIÓN - 11 -
Internet, por lo tanto, un programa Javascript, debe ser escrito y/o im-
portado en una página HTML. Ello implica aprender también algo de HTML
(el lenguaje de las páginas WEB).
Las instrucciones en HTML se escriben dentro de etiquetas. Las etique-
tas son palabras reservadas que se encierran entre los símbolos “< >”. La
mayoría de las etiquetas tienen una etiqueta de apertura y otra de cierre.
La etiqueta de cierre se diferencia de la de apertura porque está prece-
dida por el símbolo “/”, por ejemplo todas las etiquetas de un página
HTML se encierran dentro de la etiqueta “html”:
<html>
. . .
</html>
La etiqueta dentro la cual se escribe (o importa) código Javascript es
“script”. En la mayoría de los navegadores es suficiente escribir esta
etiqueta para que sea reconocido como código (instrucciones) Javascript.
Así por ejemplo si se crea el archivo “hola.html”, en Notepad, Notepad++,
DroidEdit o cualquier otro editor de textos y se escribe dentro del mismo
lo siguiente:
<script>
alert("Hola Mundo!");
</script>
Al abrir el archivo, en un navegador, aparece una ventana de alerta con
el mensaje “Hola Mundo!” (la instrucción “alert” de Javascript, sirve
justamente para ese fin). La apariencia de esta ventana varía de un nave-
gador a otro, pero no su funcionalidad, así en Google Chrome es:
En Firefox:
Y en Opera:
- 12 - Hernan Peñaranda V.
En Firefox:
Y en Opera:
UC Browser tiene algún defecto (un bug) con las ventanas emergentes
pues no las muestra ni genera ningún mensaje de error.
Ahora se verá con más detalle cómo crear un archivo HTML. Una vez
abierto el editor, simplemente se elige la opción archivo->nuevo y se
guarda el archivo con la extensión “.html”. Así en Notepad (en el block
de notas), se elige la opción “Guardar como…”:
INTRODUCCIÓN - 13 -
Entonces en la ventana que aparece se hace tap en “Local” (es decir que
se elige guardar el archivo en el dispositivo móvil):
Y en DroidEdit:
Por supuesto este programa hace lo mismo que el anterior (con excepción
del título de la página). No debe olvidar “guardar” el archivo una vez
escrito el código.
Una vez creado el archivo HTML debe ser abierto en un navegador. Y para
ello existen varias alternativas, la más sencilla (en Windows) consiste
en arrastrar el icono del archivo:
También se puede hacer clic sobre el archivo, con el botón derecho del
mouse y en el menú emergente se elige “abrir con..”, seleccionando luego
el navegador con el cual se quiere abrir la página:
1.8. EJERCICIOS
Sin embargo se debe tomar en cuenta que este alias es local, es decir
que sólo existe y por lo tanto puede ser empleado, en la página donde ha
sido creado.
Si se piensa emplear frecuentemente un conjunto de alias (como por
ejemplo alias para todas las funciones matemáticas), lo más eficiente es
crear dichos alias en una librería Javascript. Una librería Javascript
simplemente es un archivo de texto, guardado con la extensión “.js”, don-
de se escriben (sin la etiqueta “script”) todas las instrucciones Ja-
vascript que se quiere estén disponibles para las páginas que así lo re-
quieran.
Generalmente en una librería Javascript se crean objetos, funciones,
constantes, alias, etc., sin embargo, es posible escribir cualquier ins-
trucción Javascript válida, como “alert(„Hola Mundo!‟)” por ejemplo.
Existe un gran número de librerías Javascript disponibles (a través de
Internet) para diferentes propósitos. En la materia se emplearán algunas
de dichas librerías, además, se ha creado la librería “sis101.js” (que se
distribuye con el material del tema) donde en primera instancia, se han
escrito alias para todas las funciones matemáticas y se han añadido ade-
más las siguientes funciones matemáticas no disponibles en el objeto
“Math”.
csc(x) Cosecante de x.
sec(x) Secante de x.
cot(x) Cotangente de x.
sinh(x) Seno hiperbólico de x.
cosh(x) Coseno hiperbólico de x.
tanh(x) Tangente hiperbólica de x.
csch(x) Cosecante hiperbólica de x.
sech(x) Secante hiperbólica de x.
coth(x) Cotangente hiperbólica de x.
asinh(x) Arco seno hiperbólico (seno hiperbólico inverso) de x.
acosh(x) Arco coseno hiperbólico (coseno hiperbólico inverso) de x.
atanh(x) Arco tangente hiperbólico de x.
sqr(x) Cuadrado de x.
sign(x) Signo de x: 1 positivo, -1 negativo, 0 cero.
cbrt(x) Raíz cúbica de x.
odd(x) Impar. Verdadero si x es impar, falso en caso contrario.
even(x) Par. Verdadero si x es par, falso en caso contrario.
xroot(x,n) Raíz enésima (n) de x.
quot(x,y) Cociente de la división entre “x” y “y”.
frac(x) Parte fraccionaria de x.
isInteger(x) Es entero. Veradero si x es un entero.
toDeg(x) Convierte x de radianes a grados.
toRad(x) Convierte x de grados a radianes.
log10(x) Logaritmo en base 10 de x.
log2(x) Logaritmo en base 2 de x.
logb(b,x) Logaritmo en base “b” de x.
fact(n) Factorial de n.
Esta librería cuenta además con otras funciones y a medida que se avan-
ce en la materia, se le irán añadiendo otras más, por lo que la misma se-
rá distribuida conjuntamente el material de los diferentes temas (pues se
modificará frecuentemente).
INTRODUCCIÓN - 21 -
Como ya se explicó, para emplear una librería en una página HTML, sim-
plemente se la importa en la cabecera de la página HTML, dentro de la
etiqueta “script”:
<script type="text/javascript" src="mat205.js"></script>
Por ejemplo, si el problema es calcular el valor de la siguiente expre-
sión matemática para para valores de “y” iguales a 3.1, 4.2 y 7.3:
3 𝑦 + 4! + 𝑦 3.2
√ 𝑦
e + cos(𝑦)
Lo primero que se debe hacer es un análisis del problema. En este caso
se debe evaluar la expresión 3 veces, por lo tanto (aplicando el primer
principio de la programación estructurada), se deduce que es necesario un
módulo (una función) que reciba como dato el valor de “y” y devuelva como
resultado el valor de la expresión.
Por otra parte, dado que no existe ninguna condición, no se requiere
ninguna estructura estándar (segundo principio) y como los datos son
constantes, tampoco es necesario validarlos (tercer principio).
Tomando en cuenta las anteriores consideraciones se resuelve el proble-
ma creando la siguiente página HTML (ejemplo1.html):
- 22 - Hernan Peñaranda V.
log(𝑥 + √𝑦 + 𝑧)
5,
√𝑥 + 𝑦 𝑧
Para los siguientes valores de “x”, “y” y “z”: x=1.1, y=1.4, z=1.9;
INTRODUCCIÓN - 23 -
1.10. EJERCICIOS
Para presentar los ejemplos y ejercicios del tema, debe crear una car-
peta con el nombre “tema1” y guardar en la misma todos los archivos HTML
creados.
3. Calcule el valor de la siguiente expresión, para valores de “x”
iguales a 2.3, 4,5 y 7.2.
√x + 2x 0.3 + 1.2
sin−1 ( )
2x + 0.5
4. Calcule el valor de la siguiente expresión, para los siguientes va-
lores de “x” y “y”: x=9.2, y=5.6; x=2.3, y=8.4; x=7.1, y=6.3.
sec(𝑦) 0.34
(sin(𝑥) − )
sinh(𝑥)
5. Determine si los siguientes números son positivos, negativos o cero:
23, 0, 12.2, -5.42, 12, -20.3.
6. Muestre el equivalente en días de la semana (siendo el primer día
“domingo”) de los siguientes números: 2, 5, 3, 4, 7, 1, 6.
7. Encuentre la sumatoria de los primeros 20, 40 y 55 números pares.
8. Para cada uno de los siguientes números muestre el primer cociente
que no es divisible entre 2: 66, 128, 1832, 3830, 1234, 227, 2680.
VALIDACIÓN - 27 -
2. VALIDACIÓN
Un flujo, que es el símbolo empleado para unir los elementos del dia-
grama y señalar la dirección en que se deben seguir las acciones, se re-
presenta por una flecha continua abierta:
Cuando se emplea como unión llegan dos o más flujos y sale uno.
Cuando se emplea como bifurcación ingresan uno o más flujos y salen dos
o más flujos acompañados de alguna condición.
2.4. EJERCICIOS
2.6. EJERCICIO
2.8. EVENTOS
2.9. EJEMPLOS
En esta solución hay algunas cosas nuevas que se deben aclarar. En pri-
mer lugar, antes de la etiqueta <html>, se ha empleado una nueva etiqueta
<!DOCTYPE html>. Esta etiqueta le informa al navegador que el contenido
debe ser formateado de acuerdo a lo establecido en la especificación
HTML5, que es la especificación actual para el lenguaje HTML (aunque to-
davía no es un estándar).
Se ha empleado también una nueva etiqueta <meta>, con el atributo “name”
igual a “viewport”. Esta etiqueta y atributo, le instruyen al navegador
que en caso de tratarse de un dispositivo móvil, emplee el conjunto de
pares “atributo=valor” que se le dan en “content”. En este ejemplo se le
instruye que el ancho del navegador sea el ancho del dispositivo
(width=device-width) y que la escala inicial sea 1 (initial-scale=1) es
decir que inicialmente la página esté en el tamaño normal (sin amplia-
ción).
En cuanto al código Javascript, se ha dividido el problema en dos módu-
los (primer principio de la programación estructurada), pues en realidad
se tienen dos problemas: a) convertir un número comprendido entre 1 y 12
en el nombre del mes equivalente (nombreMes) y b) Leer el número selec-
cionado del elemento <select> y mostrar el nombre del mes equivalente en
el elemento <input> (mostrarMes).
En cuanto al segundo principio, en “nombreMes” se han empleado las es-
tructuras “if” y “switch”, mientras que en “mostrarMes” sólo se requiere
una instrucción.
En lo referente al tercer principio, la validación ha comenzado con el
uso del elemento <select>, con el cual se impide que el usuario introduz-
ca datos erróneos.
Como por definición un módulo debe ser independiente, es decir que debe
funcionar igual sin importar de donde o quien le envíe los datos, se ha
hecho la validación respectiva en el módulo “nombreMes”, comprobando pri-
mero que el dato sea realmente un número, empleando para ello la función
“isNaN” que devuelve verdadero (true) si el dato que se le pasa no es un
número y falso en caso contrario. Si el dato es un número se verifica que
no sea un número entero, es decir que no tenga parte fraccionaria (em-
pleando para ello la función “frac”), finalmente, se verifica que el nú-
mero entero esté comprendido entre 1 y 12.
En caso de no cumplirse alguna de las condiciones de validación, la
función genera un error (con “throw new Error(…)”) y no devuelve ningún
VALIDACIÓN - 41 -
2.10. EJERCICIOS
Para presentar los ejemplos y ejercicios del tema, debe crear una car-
peta con el nombre “tema2” y guardar en la misma todos los archivos HTML
creados.
5. Cree una página HTML que dado un día de la semana (por ejemplo
“miércoles”) devuelva el número equivalente respectivo (siendo 1 el
equivalente al día “domingo”).
6. Cree una página HTML que dado un número entero comprendido entre 1 y
15, muestre su equivalente en números romanos.
7. Cree una página HTML que dado un número, calcule, en función a la o
las opciones elegidas, la raíz cuadrada, cúbica, quinta y/o séptima
del mismo.
8. Cree una página HTML que dado un ángulo en grados, calcule, en fun-
ción a la o las opciones elegidas, el seno, coseno, secante y cose-
cante del mismo.
RECURSIVIDAD - 45 -
3. RECURSIVIDAD
Propiedad Descripción
type Nombre del evento (sin la palabra “on” por delante, por ejem-
plo “click”).
target Elemento en el cual se ha producido el evento (el elemento
que ha disparado el evento).
which Código (número) de la tecla pulsada (eventos onkeydown y on-
keypress).
keyCode Código (número) de la tecla pulsada (evento onkeydown).
charCode Código (número) de la tecla pulsada (evento onkeypress).
altKey Verdadero si la tecla “Alt” está presionada.
ctrlKey Verdadero si la tecla “Ctrl” está presionada.
shiftKey Verdadero si la tecla “Shift” está presionada.
isChar Verdadero si la tecla pulsada es un carácter.
button El botón (número) del mouse que ha sido pulsado.
detail Número de veces que se han pulsado los botones del mouse.
clientX Coordenada horizontal del mouse respecto a la ventana actual.
clientY Coordenada vertical del mouse respecto a la ventana actual.
pageX Coordenada horizontal del mouse respecto a la página.
pageY Coordenada vertical del mouse respecto a la página.
screenX Coordenada horizontal del mouse respecto a la pantalla.
screenY Coordenada vertical del mouse respecto a la pantalla.
Algunos de los métodos (funciones) del objeto “event” son:
Método Descripción
stopPropagation() Detiene la propagación del evento. El evento no pasa a
los elementos dentro del cual se encuentra el elemento
donde se produjo el evento.
preventDefault() Cancela la acción que por defecto genera el evento.
Cuando se enlaza, mediante código Javscript, el manejador de eventos al
elemento (como se verá posteriormente), el objeto “event” es pasado auto-
máticamente, pero cuando se realiza una asignación manual, como se ha
procedido hasta ahora, el objeto “event” debe ser pasado explícitamente,
por ejemplo, la siguiente instrucción crea un <input> de tipo “text” que
responde al evento “onkeydown” mediante el manejador “validar” al que se
le manda el objeto “event”.
una especie de array, donde cada uno de sus elementos corresponde a cada
uno de los argumentos (datos) que se pasan a la función, puesto que en un
manejador de eventos el primer (y único) argumento es el objeto “event”,
se accede al mismo con “arguments[0]”:
Una vez recibido el evento se pueden acceder a sus propiedades y/o mé-
todos empleando la notación de objetos, así el código de la tecla pulsada
se obtiene con: “event.keyCode”.
3.3. EJEMPLOS
1. Cree una página HTML que permita introducir un número entero positivo
y que, mediante una función recursiva, muestre el factorial del mismo.
Este es el ejemplo clásico de recursividad. Desde el punto de vista
iterativo se define como una productoria:
𝑛
𝑛! = ∏ 𝑖
𝑖=1
Que se resuelve con ciclo “for” que va desde 2 hasta “n” (no 1 porque
el acumulador comienza en 1):
5! = 4! ⋅ 5 = 24 ⋅ 5 = 120
Qué efectivamente es el resultado correcto, por lo tanto el plantea-
miento recursivo (en este caso la fórmula recursiva) es correcto.
Como ya se dijo en el planteamiento recursivo sólo interesa que el
planteamiento recursivo devuelva el resultado buscado, en este caso por
ejemplo, no es parte del problema averiguar cómo se calcula el factorial
de 4, sólo interesa verificar que al multiplicar el factorial de 4 por 5
se obtiene el factorial de 5.
Como también se dijo, en toda solución recursiva se debe contar además
con una condición de finalización, pues de lo contrario el proceso sería
infinito. En este caso se sabe (por definición) que el factorial de 0 es
1, por lo tanto esa es la condición de finalización natural del problema,
es decir que el proceso debe concluir cuando “n” sea 0 devolviendo el re-
sultado 1.
El algoritmo, en forma de diagrama de actividades, es:
sos que lleva a cabo el lenguaje que se está empleando (no el programador)
para resolver el problema de forma recursiva.
La primera vez que se llama a fact el parámetro “n” toma el valor 5 y
como no es igual a 0, se ejecuta la instrucción:
fact(5-1)*5 = fact(4)*5
Ahora, para calcular el factorial de 4 (fact(4)) la función se llama a
sí misma y en esta llamada (n=4), se ejecuta la instrucción:
fact(4-1)*4 = fact(3)*4
Una vez más, para calcular el factorial de 3, la función se llama a sí
misma y sigue así hasta que “n” es igual a 0:
fact(3-1)*3 = fact(2)*3
fact(2-1)*2 = fact(1)*2
fact(1-1)*1 = fact(0)*1
Ahora la función se llama a sí misma con “n” igual a 0 y como se cumple
la condición de finalización (n es igual a 0) devuelve el resultado 1.
Este resultado es devuelto a la función que hizo la llamada (la copia de
la función para “n” igual a 1), donde “fact(0)” es reemplazado por el re-
sultado devuelto (1), valor con el cual se lleva a cabo la multiplicación:
fact(0)*1 = 1*1 = 1
Este resultado (1) es devuelto a la función que hizo la llamada (la co-
pia de la función para “n” igual a 2), e igual que el caso anterior, con
este resultado se puede calcular ahora el factorial de 2:
fact(1)*2 = 1*2 = 2
Y continúa así hasta llegar a la primera llamada recursiva:
fact(2)*3 = 2*3 = 6
fact(3)*4 = 6*4 = 24
fact(4)*5 = 24*5 = 120
Siendo este el resultado devuelto por la función recursiva. Como se
puede ver el proceso recursivo en si es moroso y hasta confuso, pero co-
mo se dijo, dicho proceso no es parte del problema, del mismo se encarga
automáticamente el lenguaje de programación.
Observe también que en el algoritmo se ha resuelto exclusivamente el
problema sin validar el dato recibido. Esto es algo que siempre se debe
hacer al resolver un problema de manera recursiva: la función recursiva
sólo debe resolver el problema en sí, la validación debe ser hecha en una
función no recursiva desde la cual se llame a la recursiva.
El hacer la anterior división es muy importante cuando se resuelven
problemas de forma recursiva, porque si los casos especiales se tratan en
la función recursiva, dicho tratamiento ocurre en cada llamada recursiva,
lo que constituye un error porque sólo deben ser tratados una vez: la
primera vez que se llama a la función.
En cuanto a la interfaz de usuario, en este caso el dato será leído en
un <input> de tipo texto. Esto porque existe un número infinito de núme-
ros naturales (enteros positivos) y no es posible crear un <select> con
un número infinito de opciones. Se podría emplear uno de los nuevos atri-
butos HTML5 (como “number”), pero como ya se dijo, no son aún soportadas
por todos los navegadores. La validación se logrará mediante un manejador
de eventos y el objeto “event”.
- 50 - Hernan Peñaranda V.
3.4. EJERCICIOS
Para presentar los ejemplos y ejercicios del tema, debe crear una car-
peta con el nombre “tema3” y guardar en la misma todos los archivos HTML
creados (ejemplos y ejercicios).
1. Cree una página HTML que, mediante una función recursiva, calcule el
valor de xn, siendo “x” un número real y “n” un número entero positi-
vo.
2. Cree una página HTML que, mediante una función recursiva, calcule la
sumatoria de los primeros “n” números enteros positivos.
- 58 - Hernan Peñaranda V.
3. Cree una página HTML que reciba un número entero positivo y mediante
una función recursiva, devuelva dicho número sin su primer dígito.
MATRICES - 59 -
4. MATRICES
Con “new Array”, la declaración de los vectores “a”, “b” y “c”, es:
Se escribe:
- 62 - Hernan Peñaranda V.
Una vez más la primera forma es la más sencilla (y con mucho), sin em-
bargo, en la elaboración de programas por lo general se emplea la última,
porque es la forma en que se puede acceder a los elementos individualmen-
te.
Se debe tener presente que al ser una matriz un vector de vectores, ca-
da fila puede tener diferente número de elementos. Esa puede ser una
fuente de errores cuando se quiere trabaja con matrices rectangulares,
pero puede ser de utilidad para trabajar con matrices irregulares o espe-
ciales como la siguiente matriz triangular inferior:
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
Los vectores en Javascript son objetos y como tales tienen una serie de
propiedades (atributos) y métodos. En este acápite se verán algunas de
dichas propiedades y métodos.
La propiedad “length”, devuelve el número de elementos del vector, así,
para el siguiente vector:
En las matrices irregulares esta operación debe ser repetida para cada
fila (porque cada fila puede tener diferente número de columnas).
El método “concat(a1,a2,…)” une los elementos de una, dos o más matri-
ces a los elementos de la matriz desde la cual se llama al método. Por
ejemplo, si se crean las siguientes matrices:
Con lo que se crea un nuevo vector, que en este ejemplo ha sido guarda-
do en la variable “d”. El vector original “a”, desde el cual se llama al
método “concat”, no es modificado:
- 64 - Hernan Peñaranda V.
El método “join(s)”, devuelve una cadena (String) con los elementos del
vector desde el cual se llama al método. Para separar los elementos “join”
emplea la cadena de caracteres “s”. Por ejemplo, con la siguiente ins-
trucción se crea una cadena de caracteres con los elementos del vector
“d”, quedando los elementos separados con una coma y un espacio “, “:
Como de costumbre, estos métodos pueden ser empleados también con las
matrices (pues simplemente son vectores de vectores), así la siguiente
instrucción añade dos filas al principio de la matriz “y”:
Se escribe:
Una de las estructuras que más se emplea cuando se trabaja con matrices
es la estructura “for”, esto porque por lo general en dichas operaciones
se conocen los límites y/o el número de veces que se debe repetir el pro-
ceso y, como se sabe, la estructura iterativa más adecuada para esos ca-
sos es la estructura “for”.
Por ejemplo, dada la siguiente matriz:
Donde, una vez más (para no reescribir código), la segunda función lla-
ma a la primera y la tercera a la segunda.
Con estas funciones, para que por ejemplo un input text, sólo permita
escribir números enteros, se puede escribir:
Para que una función responda de una u otra forma, en función a los ar-
gumentos (datos) que recibe, se emplean los argumentos por defecto. Ja-
- 72 - Hernan Peñaranda V.
vascript no tiene argumentos por defecto como tales, sin embargo, cuenta
con herramientas que permiten emularlos. Así si una función no recibe el
número de argumentos que espera, los argumentos restantes quedan indefi-
nidos y se puede averiguar ese hecho comparándolos con “null” (o “undifi-
ned”).
Por ejemplo la siguiente función suma 3 números, pero si no se le manda
el último toma por defecto el valor 3, si no se le mandan los dos últimos
toman por defecto los valores 2 y 3, y si no se le manda ninguno de los
números toman por defecto los valores 1, 2 y 3:
Con dos argumentos genera una matriz con ese número de filas y columnas
de elementos aleatorios comprendidos entre 0 y 1:
La función “linspace”:
linspace(li,ls,n)
Genera un vector con “n” elementos, igualmente espaciados, comprendidos
entre “li” “ls”:
MATRICES - 75 -
Para crear una matriz (o vector) con todos sus elementos iguales a cero,
se cuenta con la fución “zeros”:
zeros(n,m)
Así, la siguiente instrucción crea una matriz de ceros, con 3 filas y
cuatro columnas:
Si no se manda ningún dato, crea una matriz de ceros con tres filas y
tres columnas:
Para crear una matriz (o vector) con todos sus elementos iguales a una
constante dada, se cuenta con la función “mconst”:
mconst(n,m,c)
Así la siguiente instrucción crea una matriz de 3 filas y 4 columnas,
con todos sus elementos iguales a 5:
4.8. EJEMPLOS
1. Cree una página HTML que dado un vector de números reales o enteros,
calcule la media aritmética de los mismos. La aplicación debe dar la
opción de introducir el vector manualmente o de generarlo automática-
mente y de ser así generar números enteros comprendidos entre 1 y 100.
La media aritmética se calcula con la expresión:
∑𝑖=𝑛
𝑖=1 𝑥𝑖
𝑥̅ =
𝑛
Donde “n” es el número de elementos a promediar. La codificación de es-
ta expresión es muy sencilla: en un ciclo “for” que va desde 1 hasta “n”
se añade (en cada repetición del ciclo) el valor del elemento “xi” a un
contador, luego se divide el acumulador entre el número de elementos.
En cuanto a la interfaz, lo ideal sería introducir y mostrar los datos
en tablas, por el momento, sin embargo, los datos se introducirán y mos-
trarán en cuadros de texto “textarea”, que son similares a los “input
text” excepto que permite escribir y mostrar varias líneas en lugar de
una sola. La presentación e introducción de datos en tablas (que requiere
algo más de programación) se verá posteriormente.
MATRICES - 77 -
}
}
//si no, se comprueba que sea una tecla válida
return isNaturalKey(key);
}
</body>
</html>
Abriendo la página en un navegador se obtiene algo parecido a:
MATRICES - 79 -
Como se puede ver en este ejemplo, se han fijado las dimensiones del
“textarea” en 7 filas de alto y 30 columnas de ancho (valores que, por
supuesto, pueden ser cambiados).
Por otra parte y como está explicado en el código, se ha empleado la
función “eval” para convertir el texto introducido en el “textarea” en un
vector. La función “eval” trata el texto que se le manda como instruccio-
nes Javascript, es la función que se emplea en la calculadora Javascript
para evaluar las instrucciones que se escriben en la misma, por lo tanto,
en este ejemplo “eval”, al recibir el texto, en forma de vector, lo trata
como tal, con lo que se consigue la conversión (siempre y cuando el vec-
tor haya sido correctamente escrito).
Otro aspecto que se debe tomar en cuenta es que los código (números)
empleados para las teclas “[“, “]” y “,” no son los mismos en todos los
teclados, pues depende de la configuración del mismo, en este caso espe-
cífico corresponden a un teclado en español. Este problema puede ser re-
suelto con el evento “onkeypress”, aunque en ese caso se deben tomar en
cuenta otros aspectos, como se verá posteriormente.
2. Elabore una página HTML que dadas dos matrices de números reales o
enteros, calcule el producto de los mismos. La aplicación debe dar la
opción de escribir las matrices manualmente o de generarlas con núme-
ros enteros comprendidos entre 1 y 10.
Como se sabe en la multiplicación de matrices se multiplican las filas
de la primera matriz (a) con las columnas de la segunda (b), realizando
la sumatoria respectiva. La ecuación para calcular los elementos de la
matriz resultante “c” es la siguiente:
𝑘=𝑛𝑐𝑎
𝑖 = 1 → 𝑛𝑓𝑎
𝑐𝑖,𝑗 = ∑ 𝑎𝑖,𝑘 𝑏𝑘,𝑗 {
𝑗 = 1 → 𝑛𝑐𝑏
𝑘=1
En esencia, para resolver el problema se debe programar esta ecuación y
puesto que se trata de una sumatoria (con límites definidos) la estructu-
ra más adecuada para este fin es “for”. Se requieren tres estructuras for,
una donde “i” va desde 1 hasta el número de filas de la matriz “a” (nfa),
otro (dentro del anterior) que va desde “j” igual a 1 hasta el número de
columnas de “b” (ncb) y un tercero (dentro del último ciclo “for”) que va
desde “k” igual a 1 hasta el número de columnas de “a” (nca).
En el último ciclo, puesto que se trata de una sumatoria, se deben ini-
cializar los elementos cij en cero (o emplear una variable auxiliar) para
- 80 - Hernan Peñaranda V.
//Multiplicación de matrices
function mulmat(a,b){
var nfa=a.length, nca=a[0].length;
var nfb=b.length, ncb=b[0].length;
//Si las matrices no son compatibles se genera un error
if (nca!=nfb)
throw new Error("mulmat: matrices no compatibles.");
var c=new Array(nfa);
for (var i=0;i<nfa;i++){
c[i]=new Array(ncb);
for (var j=0;j<ncb;j++){
c[i][j]=0;
for (var k=0;k<nca;k++) c[i][j]+=a[i][k]*b[k][j];
}
}
return c;
}
document.getElementById("nfa").value=ma.length;
document.getElementById("nca").value=ma[0].length;
}
}
function iniciar(){
document.getElementById("nfa").focus();
document.getElementById("nfa").select();
}
</script>
</head>
<body onload="iniciar()">
<h3>Multiplicación de Matrices</h3>
</body>
</html>
Abriendo la página en un navegador se obtiene algo parecido a lo si-
guiente:
Como se puede ver en este ejemplo, los dos primeros “textarea” respon-
den a dos eventos, el evento “onkeydown”, para permitir escribir sólo los
caracteres válidos y el evento “onblur” para actualizar los números de
fila y columna cuando las matrices se escriben (como ocurre en el ejemplo)
en lugar de generarlas.
3. Elabore una página HTML que dada una matriz, permita intercambiar los
elementos de dos columnas. La aplicación debe dar la opción de escri-
bir la matriz manualmente o generarla con números reales comprendidos
entre -10 y 10 y redondeados al primer dígito.
- 84 - Hernan Peñaranda V.
return isRealKey(key);
}
</script>
</head>
<body onload="iniciar()">
<h3>Intercambio de Columnas</h3>
</body>
</html>
Abriendo la página en un navegador se obtiene algo parecido a:
Como se puede ver, para mostrar las filas de la matriz en líneas sepa-
radas se ha empleado la función “mshow”.
Los elementos “select” (para elegir los números de columnas a intercam-
biar) están inicialmente vacíos (no tiene opciones: <option></option>).
Dichas opciones son añadidas en tiempo de ejecución mediante la función
“llenarSelects”. En esta función se lee el número de columnas de la ma-
triz y mediante un ciclo “for” que va desde 0 hasta el número de columnas
menos uno, se añade al texto “t”, en cada repetición del ciclo, una op-
ción, con el número de columna respectivo. Luego este texto (con las op-
ciones añadidas) se asigna a la propiedad “innerHTML” del “textarea”. La
MATRICES - 87 -
4.9. EJERCICIOS
Para presentar los ejemplos y ejercicios del tema, debe crear una car-
peta con el nombre “tema4” y guardar en la misma todos los archivos HTML
creados (ejemplos y ejercicios).
1. Cree una página HTML que dado un vector de números reales o enteros,
calcule la desviación estándar de los mismos, empleando la ecuación
que se muestra al pie de la pregunta. La aplicación debe dar la op-
ción de introducir el vector manualmente o de generarlo automática-
mente y de ser así generar números enteros comprendidos entre -25 y
25.
∑𝑖=𝑛(𝑥̅ − 𝑥𝑖 )2
𝑑𝑠𝑡𝑑 = √ 𝑖=1
𝑛
∑𝑖=𝑛
𝑖=1 𝑥𝑖
𝑥̅ =
𝑛
2. Elabore una página HTML que dada una matriz de números reales o en-
teros, calcule la transpuesta de la misma. La aplicación debe dar la
opción de escribir la matriz manualmente o de generarlas con números
enteros comprendidos entre 10 y 50.
3. Elabore una página HTML que dada una matriz de números reales o en-
teros, permita intercambiar los elementos de dos filas. La aplica-
ción debe dar la opción de escribir la matriz manualmente o generar-
la con números reales comprendidos entre 1 y 9 y redondeados al se-
gundo dígito.
CADENAS (STRINGS) - 89 -
5. CADENAS (STRINGS)
En Javascript las cadenas, al igual que los vectores, son objetos, por lo
que formalmente, una variable de tipo cadena (de tipo texto) se crea de con
la instrucción “new”:
Este método crea una nueva cadena con el resultado, pero no modifica la
cadena original, por lo que el valor de “s1” sigue siendo:
Este método puede devolver una cadena conformada con los caracteres equi-
valentes a la lista de códigos que se le manda, por ejemplo, la siguiente
instrucción devuelve “HOLA”:
Para copiar una parte de una cadena (una subcadena) se puede emplear el
método “substr(inicio,longitud)”, que copia “longitud” caracteres de la ca-
dena, comenzando en el índice “inicio”, por ejemplo, si la cadena es:
Para obtener un vector conformado solo por las tres primeras palabras, se
escribe:
CADENAS (STRINGS) - 93 -
Las expresiones regulares son secuencias de caracteres que pueden ser em-
pleadas para encontrar patrones en una cadena.
En Javascript las expresiones regulares son objetos y como tales se crean
formalmente con “new RegExp(patrón,modificadores)”. Por ejemplo la siguien-
te instrucción crea una expresión regular que ubica cualquier letra minús-
cula (no acentuada) en una cadena:
>>r=new RegExp("[a-z]","g")
/[a-z]/g
Tal como ocurre con los vectores y las cadenas, las expresiones regulares
tienen una forma más sencilla de ser creadas y es la forma que se ve en el
resultado de la instrucción, es decir que una expresión regular puede ser
creada escribiendo el patrón entre quebrados (“/”) y los modificadores des-
pués del último quebrado. Por lo tanto, la anterior expresión regular puede
ser creada también con:
>>r=/[a-z]/g
/[a-z]/g
Ambas formas son equivalentes, pero por su sencillez casi siempre se em-
plea la segunda.
Si se tiene la siguiente cadena:
>>s="programación en JAVASCRIPT"
programación en JAVASCRIPT
- 94 - Hernán Peñaranda V.
Modificador Descripción
i Si se emplea este modificador, la búsqueda no distingue entre
mayúsculas y minúsculas.
g Si se emplea este modificador, la búsqueda es global, es decir
que encuentra todas las coincidencias y no sólo la primera.
m Si se emplea este modificador la búsqueda se realiza en todas
las líneas y no sólo la primera.
Por otra parte, el patrón de una expresión regular, puede estar conforma-
do por texto simple, en cuyo caso encuentra el texto especificado. Por
ejemplo con la siguiente instrucción se encuentran todas las letras “a” en
la cadena “s” (sin importar que estén escritas en mayúsculas o minúsculas):
>>s.match(/a/gi)
[a, a, A, A]
El patrón puede estar encerrado también entre corchetes, en cuyo caso en-
cuentra el rango de caracteres especificado o el conjunto de caracteres
dado:
Forma Descripción
[caracteres] Encuentra cualquiera de los caracteres escritos entre los
corchetes. Por ejemplo /[aefg]/ encuentra los caracteres
“a”, “e”, “f” o “g”.
[^caracteres] Encuentra cualquier carácter, excepto los escritos a con-
tinuación del circunflejo (“^”). Por ejemplo /[^begxz]/
encuentra todos los caracteres que no sean “b”, “e”, “g”,
“x” o “z”.
[inicial-final] Encuentra todos los caracteres comprendidos entre el ca-
rácter “inicial” y el carácter “final”. Por ejemplo /[A-
Z]/ encuentra todas las letras mayúsculas.
[opc1|opc2|opc3] Encuentra los caracteres especificados en “opc1” o en
“opc2” o en “opc3”. Por ejemplo /[código|javascript|len-
guaje]/ encuentra “código” o “javascript” o “lenguaje”.
Metacarácter Descripción
. Encuentra un carácter (cualquier carácter, excepto saltos de
línea: \n).
\w Encuentra cualquier carácter alfanumérico, incluido el carác-
ter de subrayado “_”.
\W Complemento de “\w”. Encuentra cualquier carácter que no sea
alfanumérico o “_”.
\d Encuentra un dígito.
CADENAS (STRINGS) - 95 -
Metacarácter Descripción
n+ Encuentra cualquier cadena que contenga uno o más caracteres
o patrones “n”. Por ejemplo /Ja+vascript/ encuentra palabras
como “Javascript”, “JaaavaScript”, pero no “Jvascript”.
n* Encuentra cualquier cadena que contenga 0 o más caracteres o
patrones “n”. Por ejemplo /co*dificar/ encuentra palabras
como “cooodificar”, “cdificar”, “coodificar”, pero no “oodi-
ficar”.
n? Encuentra cualquier cadena que contenga 0 o 1 caracteres o
patrones “n”. Por ejemplo /pro*grama/ encuentra palabras como
“prgrama” y “programa”, pero no “proograma”.
n{x} Encuentra cualquier cadena que contenga una secuencia de “x”
caracteres o patrones “n”. Por ejemplo /\d{4}/ encuentra ca-
denas como “1234” “6032” pero no “12” o “344”.
n{x,y} Encuentra cualquier cadena que contenga una secuencia de en-
tre “x” y “y” caracteres o patrones “n”. Por ejemplo
/Ja{2,4}vascript/ encuentra cadenas como “Jaavascript”, “Jaa-
avascript”, “Jaaaavascript”, pero no “Javascript” o “Jaaaaa-
vascript”.
n{x,} Encuentra cualquier cadena que contenga una secuencia de “x”
o más caracteres o patrones “n”. Por ejemplo /ca(de){2,}na/
encuentra cadenas como “cadedena”, “cadedededena” pero no
“cadena” o “cana”.
Metacarácter Descripción
^n Encuentra una cadena que comience con el carácter o patrón
- 96 - Hernán Peñaranda V.
Finalmente, dado que las expresiones regulares son objetos, tienen pro-
piedades y métodos propios.
Las propiedades de una expresión regular informan sobre su contenido, así
“global”, “ignoreCase”, “multiline” devuelven verdadero si se han estable-
cido los modificadores “g”, “i” o “m” y falso en caso contrario. La propie-
dad “source” devuelve el patrón de la expresión regular.
Dos de los métodos más empleados en una expresión regular son “exec(cade-
na)” y “test(cadena)”. El primero “exec” devuelve la primera coincidencia
del patrón en la cadena o nulo (null) si no hay coincidencias. El segundo
devuelve verdadero (true) si hay por lo menos una coincidencia y falso
(false) en caso contrario. Si la expresión regular tiene el modificador “g”
se puede emplear la propiedad “lastIndex” que devuelve el índice posterior
a la última coincidencia encontrada.
Como se dijo la verdadera potencia de métodos como “replace”, “match” y
“search” (e inclusive “splite”) se consigue cuando se emplea en conjunción
con expresiones regulares. Por ejemplo si se tiene la siguiente cadena:
>>s="El correo electrónico del usuario 1 es: usuario_1@gmail.com, del
usuario 2 es: usuario_2@gmail.com, del usuario 3: usuario_3@gmail.com"
El correo electrónico del usuario 1 es: usuario_1@gmail.com, del usuario
2 es: usuario_2@gmail.com, del usuario 3: usuario_3@gmail.com
Y se quiere extraer (en un vector) los correos electrónicos que se en-
cuentran en el texto, se puede emplear el método “match(expresión regular)”
con la siguiente expresión:
>>s.match(/\w+@\w+\.\w{3}/g)
[usuario_1@gmail.com, usuario_2@gmail.com, usuario_3@gmail.com]
Es importante notar que para ubicar las cadenas que tienen un punto se-
guido de tres caracteres (como “.com”, “.net”, “.org”, etc.), no se ha es-
crito directamente el punto, sino que se ha precedido el mismo con el que-
brado invertido “\”, esto porque el punto en una expresión regular (como ya
se ha visto) es un metacarácter que representa a cualquier carácter (excep-
to el salto de línea “\n”).
El anteceder un carácter con el quebrado invertido “\” hace que dicho ca-
rácter sea tratado como tal y no con el significado especial que pudiera
tener. Al par quebrado invertido carácter (o quebrado invertido código) se
conoce también como secuencia de escape y se puede emplea en cualquier tex-
to para introducir caracteres especiales como saltos de línea (\n), tabula-
ciones (\t), comillas (\”), apóstrofos (\'), etc.
Si en la anterior expresión regular no se emplea una secuencia de escape
para el punto y el texto en el que se está buscando el correo es:
>>t=s.replace(/\./g,"*")
El correo electrónico del usuario 1 es: usuario_1@gmail*com, del usuario
2 es: usuario_2@gmail*com, del usuario 3: usuario_3@gmail*com
CADENAS (STRINGS) - 97 -
Devolvería lo siguiente:
>>t.match(/\w+@\w+.\w{3}/g)
[usuario_1@gmail*com, usuario_2@gmail*com, usuario_3@gmail*com]
Lo que sería incorrecto porque no son correos electrónicos propiamente,
en cambio con la secuencia de escape devuelve:
>>t.match(/\w+@\w+\.\w{3}/g)
null
Que es correcto, pues en la cadena “t” no existe realmente un correo
electrónico.
Como otro ejemplo, si se tiene la siguiente cadena:
>>s2="Dirección: Calle Ravelo 3456, celular: 74589123, ci: 1028178"
Dirección: Calle Ravelo 3456, celular: 74589123, ci: 1028178
Y se quiere ubicar la posición del número de celular en el mismo, se pue-
de emplear el método “search(expresión regular)” con la siguiente expresión:
>>i=s2.search(/\d{8}/)
39
Luego, una vez conocida la posición del texto, se puede extraer el mismo
con “substr” o “substring”:
>>s2.substr(i,8)
74589123
>>s2.substring(i,i+8)
74589123
Por supuesto, se puede extraer también directamente el texto, en forma de
vector, con “match”:
>>s2.match(/\d{8}/)
[74589123]
O también con el método “exec” de la expresión regular:
>>/\d{8}/.exec(s2)
[74589123]
De forma similar, se pueden extraer las fechas de la siguiente cadena:
>>s3="reunión en oficina: 7/4/2013; cita con el médico: 15/8/2013; reunión
colegio: 23/11/13"
reunión en oficina: 7/4/2013; cita con el médico: 15/8/2013; reunión
colegio: 23/11/13
>>s3.match(/\d\d?\/\d\d?\/\d{2,4}/g)
[7/4/2013, 15/8/2013, 23/11/13]
Tres funciones que se emplean frecuentemente con cadenas, pero que no
forman parte de los método estándar del objeto “String” y que por lo tanto
no están disponibles en todos los navegadores, son “trim()”, que elimina
los espacios en blanco al principio y al final de la cadena; “trimLeft()”
que elimina los espacios en blanco al principio de la cadena y
“trimRight()” que elimina los espacios en blanco al final de la cadena. La
mayoría de los navegadores actuales, como Google Chrome y Mozilla Firefox,
cuentan con estas funciones, algunos otros, como Opera, sólo implementan
alguna de ellas (“trim”) y otros como Internet Explorer no implementan nin-
guna.
Dado que son de utilidad, es conveniente que estén disponibles en todos
los navegadores. Afortunadamente, en Javascript, es posible añadir métodos
y propiedades a un objeto a través de la propiedad “prototype” y para ello
- 98 - Hernán Peñaranda V.
Si además de números se debe permitir los caracteres “e”, “E”, “+”, “-” y
“.” (números reales), la expresión regular cambia a:
Observe que el signo menos (“-”) ha sido escrito como una secuencia de
escape, esto porque el signo menos dentro de los corchetes especifica un
rango de caracteres (tal como ocurre con “0-9”).
De esta forma se pueden emplear las expresiones regulares para validar,
de manera más sencilla, tanto las teclas pulsadas como la información in-
troducida.
Sin embargo, si la validación se la hace en función a los caracteres en
lugar de códigos, resulta más práctico trabajar con el evento “onkeypress”
en lugar del evento “onkeydown”, pues el evento “onkeypress” devuelve el
código del carácter pulsado en lugar del código de la tecla pulsada.
5.3. TABLAS
Para que las líneas de división sean visibles se debe establecer la pro-
piedad “border” en algún ancho, por ejemplo la anterior tabla con un borde
igual a “1” produce el siguiente resultado:
Observe que el ancho del borde (1), ha sido encerrado entre apóstrofos,
esto porque toda la instrucción está encerrada entre comillas, por lo que
no se pueden emplear otras comillas dentro la misma (a no ser que esté como
una secuencia de escape '\”').
Lamentablemente las tablas sólo permiten mostrar datos, no introducirlo,
por lo que para lograr dicha funcionalidad es necesario escribir código Ja-
vascript.
Como ocurre con todos los atributos HTML, el valor del atributo debe es-
tar encerrado entre comillas o entre apóstrofos, en este ejemplo se han em-
pleado apóstrofos porque la instrucción en su conjunto está encerrada entre
comillas.
Como se puede ver en el ejemplo, cada propiedad CSS está conformada por
el par “nombre_de_la_propiedad:valor” y las propiedades se separan unas de
- 102 - Hernán Peñaranda V.
otras con puntos y comas. Las propiedades empleadas en este ejemplo son “co-
lor”, que permite cambiar el color del texto y “background-color” que per-
mite cambiar el color de fondo del elemento.
En CSS el color se establece en una de 4 formas: a) Con el nombre del co-
lor en inglés, pero se debe tomar en cuenta que solo tienen nombre un limi-
tado conjunto de colores; b) Con la función rgb(r,g,b), donde “r” es el có-
digo del color rojo (un número comprendido entre 0 y 255, siendo 0 la au-
sencia de color y 255 el color puro), “g” es el código del color verde y
“b” es el código del color azul; c) Con #rrggbb, donde “rr” es el código
del color rojo (en hexadecimal, donde el valor mínimo es “00” y máximo
“FF”), “gg” es el código del color verde y “bb” es el código del color azul
y d) Con rgb(r%,g%,b%), donde “r%” es el porcentaje de color rojo (compren-
dido entre 0% y 100%), “g%” es el porcentaje de color verde y “b%” es el
porcentaje de color azul.
Cuando una propiedad debe ser fijada como alguna medida, por ejemplo para
el ancho de un elemento, dicha medida puede tener las siguientes unidades:
% = porcentaje del elemento contenedor; in = pulgadas; cm = centímetros; mm
= milímetros; em = tamaño en puntos de la fuente actual (normalmente 12
pt); ex = alto, en puntos, de la fuente actual; pt = puntos (1 pt = 1/72
pulgadas); pc = pica (1 pc = 12 pts) y px = pixeles (un punto en la panta-
lla de la computadora).
En cuanto a las imágenes, se asignan mediante al función “url(‘URL’)”,
donde “URL” es la dirección Internet donde se encuentra la imagen o el nom-
bre del archivo en el disco duro (incluyendo el camino si la imagen no se
encuentra en el mismo directorio que el archivo HTML). Por ejemplo
url(‘scroll.gif’), asigna como imagen el archivo “scroll.gif’ que debe es-
tar en el mismo directorio que la página, de no ser así, se debe escribir
el camino completo para llegar al archivo, por ejemplo:
url(‘C:/Downloads/images/scroll.gif’), observe que la separación entre di-
rectorios se la hace con el quebrado normal (“/”), no el quebrado invertido
(“\”) como ocurre normalmente en Windows.
Algunas de las propiedades CSS son:
Propiedad Descripción
background-color Establece el color de fondo del elemento.
background-image Establece la imagen de fondo del elemento: url(‘url
o dirección de la imágen’)
background-position Establece la posición de la imágen: left top, left
center, left bottom, right top, right center, right
bottom, center top, center, center bottom o
posiciónx posicióny
border-color Establece el color del borde del elemento.
border-style Establece el estilo del borde: hidden, dotted,
dashed, solid, doublé, Groove, ridge, inset,
outset.
border-width Establece el ancho del borde.
height Establece el alto del elemento.
width Establece el ancho del elemento.
font-family Especifica la familia de caracteres a emplear. Si
el nombre de la familia tiene espacios, debe estar
encerrada entre comillas, p.e. “Times New Roman”.
Cuando se especifica más de una familia deben estar
separadas con comas.
font-size Especifica el tamaño del texto: xx-small, x-small,
small, médium, large, x-large, xx-large, smaller,
CADENAS (STRINGS) - 103 -
Estos nuevos elementos, así como los estilos CSS, se comenzarán a aplicar
a partir del presente tema.
5.6. EJEMPLOS
1. Elabore una aplicación que permita introducir texto, en una o varias lí-
neas, conteniendo únicamente letras en minúsculas (incluido acentos, es-
pacios puntos, comas y la tecla enter). La aplicación debe mostrar el
número total de caracteres escritos, el número de palabras escritas, el
número de palabras con 3 o más letras, convertir las letras iniciales de
cada palabra a mayúsculas y mostrar el texto resultante en un elemento
<div> con las letras convertidas resaltadas en color rojo siendo el fon-
do del elemento amarillo claro.
Para la introducción del texto se empleará un elemento <textarea>, porque
permite introducir texto en una o más líneas y dado que sólo debe ser posi-
ble escribir letras en minúsculas, se validará el teclado con el evento
“onkeypress”. En este caso resulta más práctico emplear este evento porque
devuelve directamente el código del carácter pulsado (no de la tecla), por
lo tanto diferencia entre mayúsculas y minúsculas. Se puede emplear también
el evento “onkeydown”, pero en ese caso se debe controlar además si la te-
cla “shift” (o “caps lock”) ha sido pulsada.
Sin embargo, cuando se emplea el evento “onkeypress” se debe tomar en-
cuenta que el mismo sólo responde a las teclas “normales”, es decir que
prácticamente sólo responde a las teclas alfanuméricas (y la tecla
“enter”), por lo tanto con este evento no se pueden validar teclas como las
teclas de función (F1 a F12), los cursores, teclado numérico, etc.
Para mostrar el número de caracteres, el número palabras y el número de
palabras con 3 o más letras, se empleará un elemento <table> y para mostrar
el texto resultante se empleará un elemento <div> (tal como dicta el enun-
ciado).
El código de la página HTML donde se resuelve el problema es:
- 106 - Hernán Peñaranda V.
CADENAS (STRINGS) - 107 -
En esta expresión “$1” representa a las cadenas que concuerdan con la ex-
presión regular “\b\w” (es decir las primeras letras de cada palabra), pero
para que “$1” represente a esas coincidencias, la parte de la expresión re-
gular a la que representa debe estar entre paréntesis (como se muestra en
el ejemplo). De esta forma es posible agrupar y trabajar con las coinciden-
cias de hasta 99 grupos (de $1 a $99) dentro de una expresión regular.
2. Elabore una aplicación que permita introducir texto alfanumérico, en una
o varias líneas, conteniendo letras tanto mayúsculas como minúsculas
(incluido acentos, espacios puntos, comas y la tecla enter), así como
siglas de materias en el formato CCCDDD (3 caracteres y 3 dígitos) y nú-
meros de carnet universitario en el formato “##-#####”. La aplicación
CADENAS (STRINGS) - 109 -
5.7. EJERCICIOS
Para presentar los ejemplos y ejercicios del tema, debe crear una carpeta
con el nombre “tema5” y guardar en la misma todos los archivos HTML creados
(ejemplos y ejercicios).
1. Elabore una aplicación que permita introducir texto, en una o varias lí-
neas, conteniendo únicamente letras en mayúsculas (incluido acentos, es-
pacios puntos, comas y la tecla enter). La aplicación debe mostrar el
número total de vocales escritas, el número total de saltos de línea, el
número de palabras con 3 letras o menos y convertir la letra final de
cada palabra a mayúsculas, mostrando el texto resultante en un elemento
<div> con las letras convertidas en color azul, siendo el fondo del ele-
mento verde claro.
- 112 - Hernán Peñaranda V.
6. ESTRUCTURAS DE DATOS
O lo que es lo mismo:
>>empleado1["nombre"]
Juan Pérez
Igualmente, se puede cambiar el valor de una propiedad con esta notación,
así para cambiar la fecha de ingreso a 1/7/2003, se escribe:
>>empleado1["fecha_ingreso"]="1/7/2003"
1/7/2003
Por supuesto es posible también añadir una nueva propiedad con esta nota-
ción, así por ejemplo para añadir la propiedad fecha de nacimiento se es-
cribe:
>>empleado1['fecha_nacimiento']='17/10/1900'
17/10/1900
Con lo que la estructura tiene ahora los siguientes campos (propiedades):
>>empleado1
{nombre:Juan Pérez, direccion:Calle Junín 345, celular:73242361,
fecha_ingreso:1/7/2003, ci:1092883, fecha_nacimiento:17/10/1900}
En general es más sencillo y claro emplear la notación de punto, sin em-
bargo, cuando el nombre de la propiedad tiene espacios o es una palabra re-
servada, la única forma de acceder a la misma es mediante la notación de
Arrays.
Para eliminar una propiedad (campo) se procede como con cualquier varia-
ble, es decir empleando el comando “delete”. Por ejemplo para eliminar la
propiedad “fecha_nacimiento” se escribe:
>>delete empleado1.fecha_nacimiento
true
Con lo que la estructura “empleado1” tiene ahora los campos:
>>empleado1
{nombre:Juan Pérez, direccion:Calle Junín 345, celular:73242361,
fecha_ingreso:1/7/2003, ci:1092883}
Sin la notación JSON, es posible también crear estructuras (array asocia-
tivos), pero el proceso es más moroso. Por ejemplo, para crear otro objeto
empleado sin JSON, se escribe:
>>empleado2=new Object()
{}
>>empleado2.nombre="Carlos Cardozo"
Carlos Cardozo
>>empleado2.direccion="Calle Loa 532"
Calle Loa 532
>>empleado2.celular=58347832
58347832
>>empleado2.fecha_ingreso="1/3/2006"
1/3/2006
>>empleado2.ci=10238932
10238932
Con lo que la estructura (el objeto) empleado2 tiene los campos:
>>empleado2
{nombre:Carlos Cardozo, direccion:Calle Loa 532, celular:58347832,
fecha_ingreso:1/3/2006, ci:10238932}
Por supuesto, el mismo resultado se puede conseguir empleando la notación
de Arrays:
- 116 - Hernán Peñaranda V.
>>empleado3=new Object()
{}
>>empleado3["nombre"]="Juan Mendez"
Juan Mendez
>>empleado3["direccion"]="Calle Junín 654"
Calle Junín 654
>>empleado3["celular"]=72847832
72847832
>>empleado3["fecha_ingreso"]="1/5/2001"
1/5/2001
>>empleado3["ci"]=10238932
10238932
>>empleado3
{nombre:Juan Mendez, direccion:Calle Junín 654, celular:72847832,
ci:10238932, fecha_ingreso:1/5/2001}
Es necesario aclarar que la posibilidad de añadir y quitar campos en una
estructura, después de haber sido creada, es una característica especial de
Javascript. La mayoría de los lenguajes (como C, C++, Java, Hecl, RPL, Pas-
cal, etc.) no permiten añadir ni quitar campos de una estructura, una vez que
ha sido creada.
Los campos de una estructura pueden ser de cualquier tipo válido, inclui-
do otro registro. Cuando esto ocurre, es decir cuando uno o más campos son
a su vez registros, se dice que son jerárquicos (los registros que no cuen-
tan con este tipo de campos se denominan registros planos).
Un mismo conjunto de datos puede ser visto tanto como un registro plano
como uno jerárquico, por ejemplo el nombre de una persona puede ser visto
como un dato simple (de tipo texto) o como un registro con tres campos:
apellido paterno, apellido materno y nombres, igualmente la fecha de naci-
miento puede ser vista como un registro compuesto por tres campos: el día,
el mes y el año, algo similar ocurre con la dirección, que puede ser vista
como un registro compuesto por dos campos: el nombre de la calle y el núme-
ro de la casa.
Así para guardar los datos de una persona en un registro jerárquico se
crean primero los constructores para los registros internos:
>>Nombre = function(a_paterno,a_materno,nombres){ this.a_paterno =
a_paterno, this.a_materno = a_materno, this.nombres = nombres }
function (a_paterno,a_materno,nombres){
this.a_paterno = a_paterno,
ESTRUCTURAS DE DATOS - 119 -
this.a_materno = a_materno,
this.nombres = nombres
}
>>Direccion = function(calle,numero){ this.calle = calle, this.numero =
numero }
function (calle,numero){
this.calle = calle,
this.numero = numero
}
>>Fecha = function(dia,mes,año){ this.dia = dia, this.mes = mes,
this.año = año }
function (dia,mes,año){
this.dia = dia,
this.mes = mes,
this.año = año
}
Con estos constructores es posible ahora crear el registro jerárquico:
>>Persona = function(ci,nombre,direccion,f_nacimiento){ this.ci = ci,
this.nombre = nombre, this.direccion = direccion, this.f_nacimiento =
f_nacimiento }
function (ci,nombre,direccion,f_nacimiento){
this.ci = ci,
this.nombre = nombre,
this.direccion = direccion,
this.f_nacimiento = f_nacimiento
}
Con este constructor se pueden crear registros jerárquico, como por ejem-
plo:
>>nombre = new Nombre("Juan","Perez","Romero")
{a_paterno:Juan, a_materno:Perez, nombres:Romero}
>>direccion = new Direccion("Avenida Jaime Mendoza",678)
{calle:Avenida Jaime Mendoza, numero:678}
>>f_nacimiento = new Fecha(4,10,1997)
{dia:4, mes:10, año:1997}
>>p1 = new Persona(10827374,nombre,direccion,f_nacimiento)
{ci:10827374, nombre:{a_paterno:Juan, a_materno:Perez, nombres:Romero}, di-
reccion:{calle:Avenida Jaime Mendoza, numero:678}, f_nacimiento:{dia:4,
mes:10, año:1997}}
Como se puede ver los campos nombre, dirección y f_nacimiento, muestran
la información que contienen entre llaves, lo que confirma que se tratan de
registros (objetos). Para acceder a uno de los campos de este registro se
procede de la forma habitual, así por ejemplo, para obtener la dirección de
“p1” se escribe:
>>p1.direccion
{calle:Avenida Jaime Mendoza, numero:678}
Y para acceder a uno de los subcampos, simplemente se extiende esta no-
menclatura, por ejemplo, para obtener el año de nacimiento de “p1”, se es-
cribe:
>>p1.f_nacimiento.año
1997
Que se interpreta como de costumbre, de derecha a izquierda, es decir es
el “año” del campo “f_nacimiento” de la persona “p1”.
Es posible crear directamente el constructor para una persona, sin crear
previamente los constructores para los campos internos:
- 120 - Hernán Peñaranda V.
>>Persona_ =
function(ci,a_paterno,a_materno,nombres,calle,numero,dia,mes,año){ this.ci
= ci, this.nombre ={a_paterno:a_paterno, a_materno:a_materno, nombres:nom-
bres}, this.direccion = {calle:calle, numero:numero} this.f_nacimiento =
{dia:dia, mes:mes, año:año} }
function (ci,a_paterno,a_materno,nombres,calle,numero,dia,mes,año){
this.ci = ci,
this.nombre ={a_paterno:a_paterno, a_materno:a_materno, nombres:nombres},
this.direccion = {calle:calle, numero:numero}
this.f_nacimiento = {dia:dia, mes:mes, año:año}
}
Como se puede ver, en este caso los registros internos no tienen la pala-
bra “this” para diferenciarlos de los nombres de los parámetros y no es ne-
cesario, porque Javascript sabe que el valor antes de los dos puntos es el
nombre del campo y que el valor después de los dos puntos es su valor.
Con este constructor se crean los mismos campos que con “Persona”, pero
mandando los datos de todos los campos (incluidos subcampos) por separado,
como por ejemplo:
>>new
Persona_(1082834,"Gómez","Salazar","Mariela","Estudiantes",67,23,5,1991)
{ci:1082834, nombre:{a_paterno:Gómez, a_materno:Salazar, nombres:Mariela},
direccion:{calle:Estudiantes, numero:67}, f_nacimiento:{dia:23, mes:5,
año:1991}}
Si bien en primera instancia los registros jerárquicos pueden ser vistos
como una forma más eficiente y ordenada de organizar la información, en la
práctica dificultan el acceso a la misma y constituyen estructuras rígidas
que complican innecesariamente su expansión y/o modificación. Es por esta
razón que en la práctica la mayoría de las bases de datos (más del 80%) es-
tán constituidas por registros planos. Los registros jerárquicos funcionan
bien en pequeñas aplicaciones y/o aplicaciones donde es poco probable que
la estructura de información sea ampliada o modificada.
6.5. OBJETOS
this.p2 = {x:x2,y:y2},
this.alto = function(){return this.p2.y-this.p1.y;},
this.ancho = function(){return this.p2.x-this.p1.x;},
this.perimetro = function(){return 2*(this.ancho()+this.alto());},
this.area = function(){return this.ancho()*this.alto();}
}
Ahora, si se crea un objeto con este constructor:
>>r1 = new Rectangulo(10,10,30,20)
{p1:{x:10, y:10}, p2:{x:30, y:20}, alto:function (){return this.p2.y-
this.p1.y;}, ancho:function (){return this.p2.x-this.p1.x;},
perimetro:function (){return 2*(this.ancho()+this.alto());}, area:function
(){return this.ancho()*this.alto();}}
Se puede averiguar el alto, ancho, perímetro y área del mismo llamando a
los métodos del objeto:
>>r1.alto()
10
>>r1.ancho()
20
>>r1.perimetro()
60
>>r1.area()
200
Sin embargo, esta solución es ineficiente pues cada vez que se crea un
nuevo objeto, se crean también nuevas funciones para el mismo, es decir que
si se crea un nuevo objeto, como el siguiente:
>>r2 = new Rectangulo(10,20,100,200)
{p1:{x:10, y:20}, p2:{x:100, y:200}, alto:function (){return this.p2.y-
this.p1.y;}, ancho:function (){return this.p2.x-this.p1.x;},
perimetro:function (){return 2*(this.ancho()+this.alto());}, area:function
(){return this.ancho()*this.alto();}}
No sólo se crean nuevos campos (con los nuevos valores), sino también
nuevos métodos (“ancho”, “alto”, “perimetro” y “area”) a pesar de ser exac-
tamente los mismos que para el objeto “r1”. Para evitar este comportamiento
ilógico los métodos deben ser añadidos a la propiedad “prototype” del cons-
tructor (tal como sucede con los campos constantes). De esa manera se crea
una sola copia de la función la cual es compartida (heredada) por todos los
objectos creados con ese constructor.
Procediendo de esa forma, la versión optimizada del constructor se crea
con:
>>Rectangulo = function(x1,y1,x2,y2){ this.p1 = {x:x1,y:y1}, this.p2 =
{x:x2,y:y2} }
function (x1,y1,x2,y2){
this.p1 = {x:x1,y:y1},
this.p2 = {x:x2,y:y2}
}
Al cual se añaden las funciones (métodos) en la propiedad prototype:
>>Rectangulo.prototype.alto = function(){return this.p2.y-this.p1.y;}
function (){return this.p2.y-this.p1.y;}
>>Rectangulo.prototype.ancho = function(){return this.p2.x-this.p1.x;}
function (){return this.p2.x-this.p1.x;}
>>Rectangulo.prototype.perimetro = function(){return 2*(this.ancho()
+this.alto());}
function (){return 2*(this.ancho()+this.alto());}
- 122 - Hernán Peñaranda V.
>>perimetro(r0)
60
>>area(r0)
200
>>diagonal(r0)
22.360679774997898
Obteniéndose, como era de esperar, los mismos resultados que en la solu-
ción con objetos.
Como se ha comprobado en el anterior ejemplo, el mismo problema puede se
resuelto tanto desde el punto de vista estructurado como orientado a obje-
tos y obteniendo en ambos casos los mismos resultados.
Entonces ¿qué enfoque se debe emplear para resolver un problema?, la res-
puesta a esta pregunta depende de varios factores: a) La naturaleza del
problema: existen problemas que por su naturaleza se resuelven de forma más
eficiente con el enfoque estructurado, mientras que otros con el enfoque
orientado a objetos; b) Las herramientas disponibles: algunas herramientas
sólo soportan uno de los enfoques en cuyo caso, si se está empleando una de
esas herramientas no queda otra alternativa que resolver el problema con el
enfoque soportado por la misma; c) El tamaño del proyecto: aunque en teoría
la programación orientada a objetos facilita la elaboración de grandes pro-
yectos, en la práctica el esfuerzo requerido en su mantenimiento incrementa
exponencialmente a medida que el proyecto crece, por lo que para proyectos
grandes (como los sistemas operativos) suele ser una mejor opción la pro-
gramación estructurada; d) La preferencia del desarrollador: este es en úl-
tima instancia el factor determinante, porque es el desarrollador quien
elegirá una u otro enfoque en función a su preferencia y experiencia con
uno u otro enfoque.
Son varias las ventajas y desventajas que los defensores de uno y otro
enfoque mencionan, pero como ya se dijo la elección final es sobre todo una
cuestión de preferencia, pues con ambas metodologías se pueden resolver los
mismos problemas.
Una de las desventajas que se señala con relación a la programación es-
tructurada es que las funciones pasan a forma parte del espacio de nombres
de las variables globales, con lo que incrementa la probabilidad de que los
nombres de dos o más variables colisionen. Este problema, sin embargo, pue-
de ser minimizado declarando las funciones en un espacio de nombres.
Un espacio de nombres es simplemente una estructura, inicialmente vacía,
a la cual se le añaden las funciones, estructuras, variables, etc., que se
quiere pertenezcan a este espacio de nombres. De esa manera el único nombre
que pasa al espacio de las variables globales es el nombre de la estructura.
Por ejemplo, el constructor “Rectangle” y sus funciones pueden ser colo-
cados en un espacio de nombres, por ejemplo un espacio de nombres denomina-
do “geometria”, que se crea con:
>>gemoetria = {}
{}
O también con:
>>geometria = new Object()
{}
Una vez creado el espacio de nombres se añaden al mismo el constructor y
las funciones:
>>geometria.Rectangle = function(x1,y1,x2,y2){ this.p1 = {x:x1, y:y1},
ESTRUCTURAS DE DATOS - 125 -
Aunque, como se dijo, la selección del enfoque es sobre todo una cuestión
de preferencia, cuando el problema es por su naturaleza estructurado u
orientado a objetos, lo recomendable es resolver el problema con ese enfo-
que.
Un ejemplo lo constituyen las expresiones matemáticas, que por su natura-
leza son estructuradas: en matemáticas se tienen por un lado los datos (nú-
meros naturales, enteros, reales, complejos, etc.) y por otro las funciones
que operan sobre los mismos (suma, resta, multiplicación, etc.) es por ello
que prácticamente el 100% de las soluciones profesionales en este campo son
estructuradas. Mientras que las soluciones orientadas a objetos, en este
campo, no han tenido éxito y no porque no sea posible resolver el problema
con ese enfoque, sino porque la solución (al no ser natural) es difícil de
aplicar en los problemas prácticos: por ejemplo en la suma, sin importar
qué se sume, se escribe el primer dato, el operador de suma (“+”) y el se-
gundo dato, no (como requiere la programación orientada a objetos) el dato,
un punto, el nombre del operador y el segundo dato entre paréntesis y la
situación se complica más aún si los datos no son del mismo tipo, pues en-
tonces se debe recurrir además al moldeo de tipos.
Para probar las aplicaciones que trabajan con registros, con frecuencia
se requieren conjuntos de datos no numéricos como apellidos, nombres de
personas, nombres de artículos, nombres de calles, etc. El introducir estos
datos manualmente no es una alternativa viable, pues por una parte consume
demasiado tiempo y por otra, cuando se produce un error y eso es algo que
ocurre en prácticamente el 100% de las aplicaciones en desarrollo, sería
necesario volver a introducirlos. Por esta razón, la alternativa más via-
bles consiste en generarlos aleatoriamente.
Para generar un conjunto de datos no numéricos de forma aleatoria se debe
crear primero un domino del cual se extraigan al azar los datos.
La forma más sencilla y práctica de crear un dominio es empleando Arrays,
por ejemplo con el siguiente Array, se crea un dominio con 45 apellidos:
>>d_apellidos_=["Abad","Ajata","Alsina","Cadenas","Aragón","Arteaga","Amor"
,"Barberá","Belda","Bonilla","Cadenas","Cantuta","Casado","Cervantes","Choq
uemamani","Comas","Cuervo","Elorza","Ferrán","Galiano","Gisbert","Guijarro"
,"Huguet","Janco","Ledesma","Lucas","Marí","Menéndez","Morales","Nieto","Pa
csipati","Paucarmayta","Pilco","Portero","Quevedo","Rico","Rosell","Salvà",
"Sevilla","Sureda","Tomé","Uyardo","Verdugo","Yáñez","Zurita"]
[Abad, Ajata, Alsina, Cadenas, Aragón, Arteaga, Amor, Barberá, Belda,
Bonilla, Cadenas, Cantuta, Casado, Cervantes, Choquemamani, Comas, Cuervo,
Elorza, Ferrán, Galiano, Gisbert, Guijarro, Huguet, Janco, Ledesma, Lucas,
Marí, Menéndez, Morales, Nieto, Pacsipati, Paucarmayta, Pilco, Portero,
Quevedo, Rico, Rosell, Salvà, Sevilla, Sureda, Tomé, Uyardo, Verdugo,
Yáñez, Zurita]
Con este dominio se pueden crear una función que genere al azar uno de
estos apellidos. Para ello simplemente se genera un número entero aleatorio
comprendido entre 0 y el número de elementos del dominio menos 1 devol-
viendo el elemento (el apellido) correspondiente a este número generado:
>>generarApellido=function(){ return
d_apellidos_[round(random(0,d_apellidos_.length-1))]; }
function (){
return d_apellidos_[round(random(0,d_apellidos_.length-1))];
}
ESTRUCTURAS DE DATOS - 127 -
6.8. FORMULARIOS
height:145px;
border-style:ridge;
border-width:5px;
border-color:lightblue;
background-color:lightblue;
padding: 10px;
}
label {
position:absolute;
width:70px;
color:blue;
font-weight:bold;
text-align:right;
}
input {
position:absolute;
text-color:green;
font-weight:bold;
left:100px;
}
</style>
</head>
<body>
<form id="forma1">
<!--Campo para introducir el nombre-->
<label for="nombre" style="top:35px;">Nombre:</label>
<input type="text" id="nombre" style="top:31px;"><br>
<!--Campo para introducir la dirección-->
<label for="direccion" style="top:60px;">Direccion:</label>
<input type="text" id="direccion" style="top:56px;"></input><br>
<!--Campo para introducir el número de teléfono-->
<label for="telefono" style="top:85px;">Telefono:</label>
<input type="text" id="telefono" style="top:81px;width:70px;"><br>
<!-- Campo para seleccionar el sexo-->
<label style="width:45px;top:110px;">Sexo:</label>
<input type="radio" name="sexo" id="sexo1" checked
style="top:110px;left:70px;cursor:pointer;">
<label for="sexo1" style="top:110px;left:95px;cursor:pointer">
Masculino</label>
<input type="radio" name="radio" id="sexo2"
style="top:110px;left:165px;cursor:pointer">
<label for="sexo2" style="top:110px;left:180px;cursor:pointer;">
Femenino</label><br>
<!--Botón para mandar los datos al servidor-->
<input type="submit" id="guardar" value="Guardar"
style="top:140px;left:115px;cursor:pointer;">
</form>
</body>
</html>
En este caso los estilos CSS se han aplicado en dos formas: a) Algunas
propiedades han sido fijadas dentro de la etiqueta <style> del encabezado
de la página y b) las propiedades específicas de cada elemento han sido
asignadas en la etiqueta del elemento (con el atributo “style”).
Observe que las propiedades comunes a los elementos “label” e “input”,
así como todas las propiedades del elemento “form” (que es el único elemen-
to “form” en esta página) han sido asignadas dentro de la etiqueta <style>.
ESTRUCTURAS DE DATOS - 129 -
Observe también que el puntero cambia a una mano con un dedo apuntando
cuando se encuentra sobre el botón o las opciones “Masculino” o “Femenino”.
Esto se debe a que se ha asignado el valor “pointer” a la propiedad “cur-
sor” de dichos elementos. Existen varios tipos de cursores que se pueden
emplear en esta propiedad (crosshair, e-resize, w-resize, n-resize, s-resi-
ze, help, move, progress, text, wait, etc.) mismos que constituyen una ayu-
da visual para los usuarios, por lo que es conveniente emplearlos en las
aplicaciones.
Por otra parte, el botón que aparece en el formulario es de tipo
“submit”, este botón envía los valores de los campos al servidor Internet
(algo que se estudiará en temas posteriores).
6.9. EJEMPLO
1. Elabore una aplicación que genere 300 registros aleatorios con los si-
guientes campos: nombre completo, dirección, teléfono, carnet de identi-
dad y fecha de nacimiento. La aplicación debe mostrar los registros en
un formulario y permitir recorrerlos hacia adelante o hacia atrás uno
por uno, así como ir al primer registro o al último y a un número de re-
- 130 - Hernán Peñaranda V.
gistro específico.
El código elaborado para resolver el problema es el siguiente:
<!DOCTYPE html>
<html>
<head>
<title>Ejemplo 1</title>
<script src="sis101.js"></script>
<script>
function Registro(nombre,direccion,telefono,ci,f_nacimiento){
this.nombre=nombre;
this.direccion=direccion;
this.telefono=telefono;
this.ci=ci;
this.f_nacimiento=f_nacimiento;
}
function generarRegistro(){
var apellido1=generarApellido();
var apellido2=generarApellido();
var nombre1= round(random(1)) ? generarNombreF():generarNombreM();
var nombre=apellido1+" "+apellido2+" "+nombre1;
var direccion=generarCalle()+" "+round(random(1,1000));
var telefono=round(random(30000,90000))+72800000;
var ci=round(random(10000,99999))+1000000;
var f_nacimiento=round(random(1,28))+"/"+round(random(1,12))+
"/"+round(random(1970,2000));
return new Registro(nombre,direccion,telefono,ci,f_nacimiento);
}
function mostrarRegistro(r){
document.getElementById("numreg").value=ra;
document.getElementById("nombre").value=r.nombre;
document.getElementById("direccion").value=r.direccion;
document.getElementById("telefono").value=r.telefono;
document.getElementById("ci").value=r.ci;
document.getElementById("f_nacimiento").value=r.f_nacimiento;
}
function inicializar(){
nr=300;//Número de registros
var txt="";
for (var i=0;i<nr;i++){
txt+="<option value="+i+">"+i+"</option>"
}
document.getElementById("numreg").innerHTML=txt;
registro = new Array(300);//Registros generados
for (var i=0;i<nr;i++)
registro[i]=generarRegistro();
ra=0;//Número de registro actual
mostrarRegistro(registro[ra]);
}
ESTRUCTURAS DE DATOS - 131 -
function primerRegistro(){
ra=0;
mostrarRegistro(registro[ra]);
}
function siguienteRegistro(){
ra = (ra<nr-1) ? ra+1 : 1;
mostrarRegistro(registro[ra]);
}
function anteriorRegistro(){
ra = (ra>0) ? ra-1 : nr-1;
mostrarRegistro(registro[ra]);
}
function ultimoRegistro(){
ra=nr-1;
mostrarRegistro(registro[ra]);
}
function enesimoRegistro(n){
ra=n;
mostrarRegistro(registro[ra]);
}
</script>
<style type="text/css">
form {
width:340px;
height:220px;
background-color:lightyellow;
border-width:5px;
border-style:groove;
border-color:lightyellow;
padding:10px;
}
label {
position:absolute;
color:red;
font-weight:bold;
width:110px;
text-align:right;
}
input {
position:absolute;
color:blue;
font-weight:bold;
left:140px;
}
input[type=button]{
top:220px;
width:50px;
cursor:pointer;
}
</style>
- 132 - Hernán Peñaranda V.
</head>
<body onload="inicializar()">
<form id="form1">
</form>
</body>
</html>
Que al ser abierta en un navegador, tiene la siguiente apariencia:
ESTRUCTURAS DE DATOS - 133 -
Como se puede ver, para navegar a través de los registros se han empleado
cuatro botones.
Para mostrar el número de registro actual, como para ir a un registro es-
pecífico se ha empleado un “select” en cuyo evento “onchange” se ha progra-
mado el salto al registro respectivo. Las opciones de este elemento (las
300 opciones) se generan en la función “inicializa” que es llamada cuando
la página termina de ser cargada (evento onload de “body”).
Igualmente, los 300 registros son generados en la función “inicializar”
llamando a la función “generarRegistro”, la cual a su vez hace uso del
constructor “Registro” y de las funciones “generarApellido”, “generarNom-
breF”, “generarNombreM” y “generarCalle” de la librerías “sis101.js”. Los
números de teléfono, carnet de identidad y la fecha de nacimiento, al ser
números, se generan con la función “random”.
Finalmente, para mostrar los resultados en el formulario se llama a la
función “mostrarRegistro” que recibe como dato el registro a mostrar.
Observe que las variables “nr” (número de registros), “ra” (registro ac-
tual) y “registro” (el vector con los registros generados) son variables
globales (no han sido declaradas con “var”), se ha procedido así para que
dichas variables puedan ser empleadas desde otras funciones (como “prime-
rRegistro”, “siguienteRegistro”, etc.)
En cuanto a los estilos, con la intención de demostrar uno de los meca-
nismos de selección de CSS, se ha empleado “input[type=button]” con esta
instrucción se crea un estilo para los elementos “input” que tengan el
atributo “type” igual a “button” (que en este ejemplo son los botones de
navegación). Este mecanismo de selección se puede emplear con cualquier
atributo y puede tener un valor asignado (como en el ejemplo) o simplemente
el nombre del atributo, por ejemplo si se escribe “label[for]” el estilo se
aplica a todos los elementos “label” que tienen el atributo “for” (sin im-
portar el valor que tengan asignado), es posible también seleccionar ele-
mentos que tengan un atributo con un valor diferente al designado, por
ejemplo “input[size~=20]” aplica el estilo a todos los elementos “input”
cuyo atributo “size” sea diferente de 20.
En este ejemplo no se ha validado la introducción de datos porque los
campos son generados (no introducidos manualmente). En una aplicación real
se tienen que validar los datos introducidos.
- 134 - Hernán Peñaranda V.
6.10. EJERCICIOS
Para presentar los ejemplos y ejercicios del tema, debe crear una carpeta
con el nombre “tema5” y guardar en la misma todos los archivos HTML creados
(ejemplos y ejercicios).
7. ORDENACIÓN
x1 x2 x3 x4 x5
5 4 2 1 3
x1 x2 x3 x4 x5
5 4 2 1 3
4 5
Ahora se compara el segundo con el tercer elemento (5 con 2) y como el
primero es mayor al segundo se realiza otro intercambio de variables:
x1 x2 x3 x4 x5
4 5 2 1 3
2 5
Se continúa entonces con el tercer y cuarto elemento (5 y 1) y como una
vez más el primero es mayor que el segundo se realiza un intercambio:
x1 x2 x3 x4 x5
4 2 5 1 3
1 5
Finalmente se compara el cuarto y quinto elemento (5 con 3) y se realiza
otro intercambio:
x1 x2 x3 x4 x5
4 2 1 5 3
3 5
Con ello termina el proceso y, como se puede observar, el mayor valor
queda en la última posición:
x1 x2 x3 x4 x5
4 2 1 3 5
x1 x2 x3 x4 x5
4 2 1 3 5
2 41 43 4
x1 x2 x3 x4 x5
2 1 3 4 5
Se repite una vez más el proceso (sin tomar en cuenta los dos últimos
elementos que ya están ordenados):
x1 x2 x3 x4 x5
2 1 3 4 5
1 2
x1 x2 x3 x4 x5
1 2 3 4 5
Finalmente se comparan los dos elementos restantes (el primer con el se-
gundo):
ORDENACIÓN - 137 -
x1 x2 x3 x4 x5
1 2 3 4 5
x1 x2 x3 x4 x5
1 2 3 4 5
x1 x2 x3 x4 x5 x6 x7
1 2 7 3 4 5 6
x1 x2 x3 x4 x5 x6 x7
1 2 7 3 4 5 6
3 74 75 76 7
x1 x2 x3 x4 x5 x6 x7
1 2 3 4 5 6 7
x1 x2 x3 x4 x5 x6 x7
1 2 3 4 5 6 7
7.1.1. Algoritmo
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Burbuja</title>
- 138 - Hernán Peñaranda V.
n = Nº de elementos en x
[n=0]
[else]
desde i=n-1 hasta 1
s = verdad
[else]
j = j+1
[x j>x j+1]
aux=xj; x j=xj+1; x j+1=aux
s = falso
[else]
i = i+1
[s]
<script src="sis101.js"></script>
<script>
function burbuja(x){
var i,j,aux,n=x.length;
if (n==0) return;
for (i=n-1;i>0;i--){
s=true;
for (j=0;j<i;j++)
if (x[j]>x[j+1]){
aux=x[j]; x[j]=x[j+1]; x[j+1]=aux;
s=false;
}
if (s) break;
}
}
function generar(){
x = round(rand(1000,1,2000));
document.getElementById("vect1").innerHTML = x;
}
function ordenar(){
var t1=new Date();
burbuja(x);
var t2=new Date();
var dt = t2.getTime()-t1.getTime();
document.getElementById("vect2").innerHTML=x;
document.getElementById("tiempo").value=dt+" milisegundos";
}
ORDENACIÓN - 139 -
</script>
<style>
input[type="button"] {
background-color:lightblue;
margin-left:100px;
cursor:pointer;
}
input[type="text"] {
color:red;
background-color:lightcyan;
}
label {
color:blue;
}
textarea {
color: green;
width:320px;
height:200px;
background-color:lightyellow;
}
</style>
</head>
<body onload="generar()">
<input type="button" value="Generar Vector" onclick="generar()"><br>
<label for="vect1">Vector Generado:</label><br>
<textarea id="vect1"></textarea><br>
<input type="button" value="Ordenar Vector" onclick="ordenar()"><br>
<label for="vect2">Vector Ordenado:</label><br>
<textarea id="vect2"></textarea><br>
<label for="tiempo">Tiempo empleado:</label>
<input type="text" id="tiempo">
</body>
</html>
Al abrir esta página en un navegador, se puede ver una interfaz con una
apariencia similar a la que se muestra en la siguiente página. Observe que
el vector se genera y guarda en la variable global “x” (es global porque no
ha sido declarada con la palabra “var” por delante), al ser global, puede
ser empleada desde cualquiera de las funciones, siendo esa la razón por la
cual puede ser empleada directamente en la función “ordenar”.
Para determinar el tiempo que demora el método en ordenar los elementos,
se han empleado objetos “Date”. Estos objetos permiten trabajar con valores
de tiempo y/o fecha en Javascript. Si se crea un objeto “Date” sin ningún
argumento (como se ha hecho en el ejemplo), contiene la fecha y hora actua-
les, por esa razón en el ejemplo se crea el objeto “t1” antes de llamar al
método de ordenación y se crea el objeto “t2” cuando el método devuelve la
lista ordenada, entonces, para obtener el tiempo transcurrido entre la lla-
mada y la devolución del resultado, se emplea el método “getTime()” que de-
vuelve los milisegundos transcurridos entre el primero de enero de 1970 y
la fecha del objeto. Por lo tanto, al restar los milisegundos de “t1” a los
milisegundos de “t2”, se obtiene el tiempo empleado por el método en orde-
nar la lista.
- 140 - Hernán Peñaranda V.
Como se puede ver, en listas pequeñas como esta (con solo 1000 elementos)
el tiempo requerido es también pequeño, sin embargo a medida que incrementa
el número de elementos el tiempo incrementa pero no en forma lineal, sino
en forma geométrica, así para ordenar 10000 elementos se requiere alrededor
de 370 milisegundos, es decir ¡74 veces lo que requiere ordenar 1000 ele-
mentos!. Si la relación fuera lineal, ordenar 10000 elementos debería tomar
unos 50 milisegundos, no 370 (por supuesto el tiempo real empleado varía de
computadora a computadora).
Por otra parte, cuando se generan números aleatorios, por lo general se
quiere que los mismos sean realmente aleatorios, es decir impredecibles
(como ha ocurrido hasta ahora), sin embargo, para comparar la eficiencia de
dos o más métodos, es necesario contar con la misma serie de valores, pues
de lo contrario la comparación no sería correcta y se podría llegar a con-
clusiones erróneas.
Con ese fin se deben generar números pseudoaleatorios, es decir secuen-
cias de números que pueden ser reproducidas. Javascript no cuenta con un
generador pseudoaleatorio, por lo que se ha añadido uno a la librería
“sis101.js”. Para activar este generador, se debe iniciar la variable glo-
bal “randseed” asignándole un valor diferente de nulo (null), dicho número,
conocido como semilla (seed), se emplea como base para generar la secuen-
ORDENACIÓN - 141 -
x1 x2 x3 x4 x5
5 4 2 1 3
x1 x2 x3 x4 x5
5 4 2 1 3
3 5
x1 x2 x3 x4 x5
3 4 2 1 5
1 4
Ahora los dos últimos elementos ya están ordenados, por lo que se repite
el proceso con los 3 elementos restantes:
x1 x2 x3 x4 x5
3 1 2 4 5
2 3
x1 x2 x3 x4 x5
2 1 3 4 5
1 2
x1 x2 x3 x4 x5
1 2 3 4 5
7.2.1. Algoritmo
function generar(){
randseed=10;
x = round(rand(10000,1,10000));
document.getElementById("vect1").innerHTML = x;
ORDENACIÓN - 143 -
n = Nº de elementos en x
[n=0]
k=0
[else]
j = j+1
[xj >x k]
k=j
[k<>i]
document.getElementById("vect2").innerHTML = "";
document.getElementById("tiempo").value = "";
}
function ordenar(){
var t1=new Date();
seleccion(x);
var t2=new Date();
var dt = t2.getTime()-t1.getTime();
document.getElementById("vect2").innerHTML = x;
document.getElementById("tiempo").value=dt+" milisegundos";
}
Abriendo la página y ordenando la lista, el tiempo requerido es de apro-
ximadamente 210 milisengudos, es decir casi 2 veces menos (1.7 veces menos)
que el método de Burbuja (aunque, como se ha explicado, esta diferencia no
siempre es a favor del método de selcción).
Este método, el de Burbuja y todos los métodos de ordenación que se estu-
diarán en este tema pueden ser implementados de forma recursiva. El razona-
miento recursivo para ordenar una lista por el método de selección es el
siguiente: Una lista puede ser ordenada buscando su mayor valor e intercam-
biándolo con el último elemento, mandando luego la lista restante (sin su
último elemento) a ser ordenada por el método de Selección. En el caso del
método de Burbuja el razonamiento recursivo es el siguiente: Una lista pue-
de ser ordenada llevando su mayor valor a la última posición comparando
elementos sucesivos e intercambiándolos si el primero es mayor que el se-
gundo, mandando luego la lista restante (sin su último elemento) a ser or-
denando por el método de Burbuja. Note que en ambos métodos el razonamiento
implica una llamada al mismo método.
- 144 - Hernán Peñaranda V.
n = número de elementos en x
[n<2]
selecr(n)
[else]
[n>1]
k=0
[else]
i = i+1
[x i>x k]
k=i
[k<>n-1]
selecr (n-1)
“x” porque al ser una función anidada tiene acceso a todas las variables de
la función contenedora. De esa manera, la función recursiva sólo recibe el
único dato que realmente varía en el proceso recursivo: el número de ele-
mentos “n”.
Para probar el algoritmo recursivo y como una forma de demostrar que este
algoritmo (como cualquier otro) no está limitado a números, sino que puede
ser aplicado a cualquier tipo de dato, se creará una página HTML en la que
se genera una lista con 1000 registros conteniendo los campos nombre, di-
rección y teléfono, ordenando luego dichos registros por el campo nombre:
<!DOCTYPE html>
<html>
<head>
<script>
function seleccion(x){
var i,k,aux;
function selecr(n){
if (n>1){
var k=0;
for (i=1;i<n;i++)
if (x[i].nombre>x[k].nombre) k=i;
if (k!=n-1){
aux=x[n-1]; x[n-1]=x[k]; x[k]=aux;
}
selecr(n-1);
}
}
var n=x.length;
if (n>1) selecr(n);
}
function Registro(nombre,direccion,telefono){
this.nombre = nombre;
this.direccion = direccion;
this.telefono = telefono;
}
function generarNombre(){
var s=generarApellido();
if (random(1)) s+=" "+generarApellido();
if (random(1)) s+=" "+generarNombreF()
else s+=" "+generarNombreM();
return s;
}
function generarDireccion(){
var s=generarCalle();
s+=" Nº "+round(random(1,1000));
return s;
}
- 146 - Hernán Peñaranda V.
function generarTelefono(){
return 6400000+round(random(1,99999));
}
function generarRegistros(){
randseed = 10;
r = new Array(1000)
for (var i=0;i<1000;i++){
r[i] = new Registro(generarNombre(),generarDireccion(),
generarTelefono());
}
}
function llenarTabla(){
generarRegistros();
var texto="<tr><th>Nombre</th><th>Dirección</th>"+
"<th>Teléfono</th></tr>";
for (var i=0;i<r.length;i++){
texto+= odd(i) ? "<tr fila='impar'>" : "<tr fila='par'>";
texto+="<td>"+r[i].nombre+"</td>"+
"<td>"+r[i].direccion+"</td>"+
"<td>"+r[i].telefono+"</td></tr>";
}
document.getElementById("tabla1").innerHTML=texto;
}
function ordenarTabla(){
seleccion(r);
var texto="<tr><th>Nombre</th><th>Dirección</th>"+
"<th>Teléfono</th></tr>";
for (var i=0;i<r.length;i++){
texto+= odd(i) ? "<tr fila='impar'>" : "<tr fila='par'>";
texto+="<td>"+r[i].nombre+"</td>"+
"<td>"+r[i].direccion+"</td>"+
"<td>"+r[i].telefono+"</td></tr>";
}
document.getElementById("tabla1").innerHTML=texto;
}
</script>
<style type="text/css">
button {
color:mediumblue;
font-weight:bold;
background-color:PowderBlue;
}
table {
color:ForestGreen;
border-style:double;
border-width:3px;
border-collapse:collapse;
}
td {
border-style:solid;
border-width:1px;
ORDENACIÓN - 147 -
}
th {
color:chocolate;
font-weight:bold;
background-color:#99CC00;
border-style:solid;
border-width:1px;
border-color:black;
}
tr[fila="impar"] {
background-color:#FFFFCC;
}
tr[fila="par"] {
background-color:#CCFF99;
}
</style>
</head>
<body onload="llenarTabla()">
<button onclick="llenarTabla()">Generar</button>
<button onclick="ordenarTabla()">Ordenar</button><br><br>
<table id="tabla1" >
</table>
</body>
</html>
Como se puede ver, el algoritmo en sí no cambia, lo único que es necesa-
rio tomar en cuenta cuando se ordenan registros, en lugar de datos simples,
es que al comparar los valores sólo se compara él o los campos, por los que
se ordenan (en este caso el campo “nombre”).
Al abrir la página se llena la tabla con los 1000 registros generados (el
cual puede volver a ser generado haciendo clic en el botón “generar”), para
ordenar estos registros se hace clic en el botón “ordenar” con lo que los
mismos quedan ordenados por el campo “nombre”:
x1 x2 x3 x4 x5
5 14 -2 10 3
Se comienza con el segundo elemento (que tiene el valor 14) y como es ma-
yor al primero se encuentra ya en su posición correcta con relación al ele-
mento anterior, por lo que es insertado directamente en la segunda posición:
x1 x2 x3 x4 x5
5 14 -2 10 3
Ahora se pasa al tercer elemento (que tiene el valor -2) y como es menor
a los dos anteriores, es insertado en la primera posición, desplazando los
elementos anteriores una posición hacia la derecha:
x1 x2 x3 x4 x5
5 14 -2 10 3
x1 x2 x3 x4 x5
-2 5 14 10 3
Ahora se pasa al cuarto elemento (que tiene el valor 10) y como este ele-
mento es menor al tercero, pero mayor al segundo, debe ser insertado en la
tercera posición:
x1 x2 x3 x4 x5
-2 5 14 10 3
x1 x2 x3 x4 x5
-2 5 10 14 3
x1 x2 x3 x4 x5
-2 5 10 14 3
x1 x2 x3 x4 x5
-2 3 5 10 14
7.3.1. Algoritmo
n = Nº de elementos en x
[n=0]
j=i; aux=xi
[j>0 y aux<xj-1]
xj=xj-1; j=j-1
[else]
i = i+1
[j<>i]
xj = aux
La página creada para probar este método, con excepción del método en sí,
es esencialmente la misma que la del anterior, las partes que varían con
relación a dicho código son:
function insercion(x){
var i,j,aux,n=x.length;
if (n==0) return;
for (i=1;i<n;i++){
j=i; aux=x[i];
while (j>0 && aux<x[j-1]){
x[j]=x[j-1]; j--;
}
if (j!=i) x[j]=aux;
}
}
function ordenar(){
var t1=new Date();
insercion(x);
var t2=new Date();
var dt = t2.getTime()-t1.getTime();
document.getElementById("vect2").innerHTML=x;
document.getElementById("tiempo").value=dt+" milisegundos";
}
- 150 - Hernán Peñaranda V.
x1 x2 x3 x4 x5 x6 x7 x8 x9
4 2 8 7 12 6 11 15 10
x1 x2 x3 x4 x5 x6 x7 x8 x9
4 2 8 7 12 6 11 15 10
10
x1 x2 x3 x4 x5 x6 x7 x8 x9
4 2 8 7 10 6 11 15 12
x1 x2 x3 x4 x5 x6 x7 x8 x9
4 2 8 7 10 6 11 15 12
6 7
x1 x2 x3 x4 x5 x6 x7 x8 x9
4 2 8 6 10 7 11 15 12
x1 x2 x3 x4 x5 x6 x7 x8 x9
42 24 86 68 10 7 7 10 11 15 12 1215
x1 x2 x3 x4 x5 x6 x7 x8 x9
2 4 6 8 7 7 8 10 11 12 15
Una vez más hay intercambios, por lo que se vuelve a repetir el proceso:
x1 x2 x3 x4 x5 x6 x7 x8 x9
2 4 6 7 8 10 11 12 15
7.4.1. Algoritmo
n = Nº de elementos en x; k = n
[else]
[k>1]
k=cociente(k/2)
s = verdad
[else]
i = i+1
[x i>x i+k ]
aux=xi ; xi=xi+k; xi+k=aux
s = falso
[else]
[s]
function shell(x){
var i,j,aux,n=x.length,k=n;
while (k>1) {
k = quot(k,2);
while (true) {
s = true;
for (i=0;i<n-k-1;i++)
if (x[i]>x[i+k]){
aux=x[i]; x[i]=x[i+k]; x[i+k]=aux;
s = false;
}
if (s) break;
}
}
}
function ordenar(){
var t1=new Date();
shell(x);
var t2=new Date();
var dt = t2.getTime()-t1.getTime();
document.getElementById("vect2").innerHTML=x;
document.getElementById("tiempo").value=dt+" milisegundos";
}
El método Shell requiere aproximadamente 9 milisegundos para ordenar los
10000 números, es decir que en esta lista es 41 veces más rápido que el mé-
todo de Burbuja, 23 veces más rápido que el método de Selección y 11 veces
más rápido que el método de inserción. Como todos los métodos puede ser im-
plementado también en forma recursiva.
ORDENACIÓN - 153 -
x1 x2 x3 x4 x5 x6 x7 x8 x9
15 21 30 7 20 18 10 14 28
Para este ejemplo, se elige como pivote el primer elemento, por lo tanto
el pivote será 15 (tome en cuenta que el pivote es el valor del primer ele-
mento, no el elemento en sí, porque en el proceso su valor puede ir cam-
biando).
Ahora se debe dividir la lista en 2, una con elementos mayores a 15 y
otra con elementos menores a 15. Para ello se emplean dos contadores: uno
que comienza en el índice más bajo del vector (1) y otro en el índice más
alto (9):
x1 x2 x3 x4 x5 x6 x7 x8 x9
15 21 30 7 20 18 10 14 28 pivote =15
i=1
j=9
x1 x2 x3 x4 x5 x6 x7 x8 x9
15 21 30 7 20 18 10 14 28
i=1 pivote =15
j=8 j=9
x1 x2 x3 x4 x5 x6 x7 x8 x9
15 14 21 30 7 20 18 10 1415 28
i=1 i=2 pivote =15
j=7 j=8
- 154 - Hernán Peñaranda V.
x1 x2 x3 x4 x5 x6 x7 x8 x9
14 21 30 7 20 18 10 15 28
i=2 pivote =15
j=7
Ahora que los contadores han quedado fijos, se intercambia xi con xj, lue-
go se incrementa i en uno y se disminuye j en uno:
x1 x2 x3 x4 x5 x6 x7 x8 x9
14 2110 30 7 20 18 10 21 15 28
i=2 i=3 pivote =15
j=6 J=7
x1 x2 x3 x4 x5 x6 x7 x8 x9
14 10 30 7 7 20 18 21 15 28
pivote =15
i=3 i=4
j=3 j=4 j=5 J=6
Como se puede ver en este caso el contador i queda con un valor mayor que
el contador j.
Cuando esto sucede el proceso concluye y la lista queda dividida en dos:
la lista izquierda que va desde el primer elemento hasta j (es decir desde
1 hasta 3) y la derecha que va desde i hasta el último elemento (es decir
desde 4 hasta 9):
x1 x2 x3 x4 x5 x6 x7 x8 x9
14 10 7 30 20 18 21 15 28
x1 x2 x3
14 10 7 pivote = x1 = 14
i=1
j=3
x1 x2 x3
14 7 10 7 14 pivote =14
i=1 i=2
j=2 j=3
x1 x2 x3
7 10 14 pivote =14
i=2 i=3
j=2
Ahora que los contadores han quedado fijos se debería intercambiar los
valores de xi y xj, pero como el contador i es mayor al contador j, no se
realiza el intercambio y la lista queda dividida en dos: la izquierda (has-
ta j=2) con los elementos menores al pivote y la derecha (desde i=3) con un
sólo elemento igual al pivote:
x1 x2 x3
7 10 14
Cuando, como en este caso, una de las listas queda con un solo elemento,
dicho elemento ya está ordenado, es decir tiene el valor correcto.
El vector izquierdo sin embargo tiene dos elementos por lo que se debe
aplicar el procedimiento al mismo:
x1 x2
7 10 pivote = 7
i=1 i=2
j=0 j=1 j=2
x0 x1 x2
7 10
Como todos los vectores del lado izquierdo de la primera división han
quedado con un solo elemento (o ninguno), estos elementos están ordenados.
Ahora se aplica el procedimiento al vector derecho resultante de la pri-
mera división:
- 156 - Hernán Peñaranda V.
x4 x5 x6 x7 x8 x9
30 28 20 18 21 15 28 30 pivote = x4 = 30
i=4 i=5
j=8 J=9
x4 x5 x6 x7 x8 x9
28 20 18 21 15 30 pivote = 30
i=5 i=6 i=7 i=8 i=9
j=8
x4 x5 x6 x7 x8 x9
28 20 18 21 15 30
Como la lista derecha tiene un solo elemento, está ya con el valor co-
rrecto.
La lista izquierda, sin embargo, tiene más de un elemento por lo que se
aplica el procedimiento a la misma:
x4 x5 x6 x7 x8
28 15 20 18 21 15 28 pivote = x4 = 28
i=4 i=5
j=7 j=8
x4 x5 x6 x7 x8
15 20 18 21 28 pivote= 28
i=5 i=6 i=7 i=8
j=7
x4 x5 x6 x7 x8
15 20 18 21 28
x4 x5 x6 x7
15 20 18 21 pivote = x4 = 15
i=4 i=5
j=3 j=4 j=5 j=6 j=7
ORDENACIÓN - 157 -
x3 x4 x5 x6 x7
15 20 18 21
x5 x6 x7
20 18 18 20 21 pivote = x5 = 20
i=5 i=6
j=5 j=6 j=7
x5 x6 x7
18 20 21
x6 x7
20 21 pivote = x6 = 20
i=6 i=7
j=5 j=6 j=7
x5 x6 x7
20 21
x1 x2 x3 x4 x5 x6 x7 x8 x9
7 10 14 15 18 20 21 28 30
plo, con Quick Sort se requieren 7 intercambios, comparado con los 19 que
serían necesarios con el método de Burbuja.
A medida que incrementa el número de elementos la diferencia se incremen-
ta y cuando la lista es muy grande (con millones o cientos de millones de
elementos) lo que a Burbuja le toma días a Quick Sort le toma minutos.
7.5.1. Algoritmos
[else]
[x i<piv]
i = i+1
[else]
[x j>piv]
j = j-1
[i<=j]
[i<>j]
[else]
[else] aux=x i; xi =xj ; xj =aux
i=i+1; j=j-1
[i<=j]
[else]
[j>p]
[i<u]
x = Nº de elementos en x
[n<2]
quickr(0,n-1)
function ordenar(){
var t1=new Date();
quick(x);
var t2=new Date();
var dt = t2.getTime()-t1.getTime();
document.getElementById("vect2").innerHTML=x;
document.getElementById("tiempo").value=dt+" milisegundos";
}
Para ordenar los 10000 números el método Quick-Sort requiere 2 milisegun-
dos, es decir 185 veces menos que Burbuja, 105 veces menos que Selección,
50 veces menos que inserción y 4.5 veces menos que Shell, con lo que se
comprueba es el método más rápido de los estudiados en este tema.
Simplemente para demostrar que este algoritmo (como todos los otros) pue-
de ser empleado para ordenar otros tipos de datos, tales como registros, se
ordenará el vector de 1000 elementos del método de selección, pero ahora
por el campo dirección. Las partes del código que cambian con relación a
dicho ejemplo son las siguientes:
function quick(x){
var aux,n=x.length,k=n;
function quickr(i,j){
var p=i,u=j,piv=x[i].direccion;
- 160 - Hernán Peñaranda V.
do {
while (x[i].direccion<piv) i++;
while (x[j].direccion>piv) j--;
if (i<=j){
if (i!=j){
aux=x[i]; x[i]=x[j]; x[j]=aux;
}
i++; j--;
}
} while(i<=j);
if (j>p) quickr(p,j);
if (i<u) quickr(i,u);
}
n = x.length;
if (n>1) quickr(0,n-1);
}
function ordenarTabla(){
quick(r);
var texto="<tr><th>Nombre</th><th>Dirección</th>"+
"<th>Teléfono</th></tr>";
for (var i=0;i<r.length;i++){
texto+= odd(i) ? "<tr fila='impar'>" : "<tr fila='par'>";
texto+="<td>"+r[i].nombre+"</td>"+
"<td>"+r[i].direccion+"</td>"+
"<td>"+r[i].telefono+"</td></tr>";
}
document.getElementById("tabla1").innerHTML=texto;
}
Como se puede ver y al igual que sucedió con el método de Selección, la
única modificación que se debe hacer al algoritmo es la de comparar los re-
gistros por el campo en que son ordenados. Como en Quick-Sort el pivote
forma parte de esa comparación, su valor debe ser tomado también de dicho
campo. Ordenando la tabla por el campo dirección se obtiene:
7.6. EJERCICIOS
Para presentar los ejemplos y ejercicios del tema, debe crear una carpeta
con el nombre “tema7” y guardar en la misma todos los archivos HTML creados
(ejemplos y ejercicios).
ORDENACIÓN - 161 -
1. Cree una página HTML que genere una lista con 15000 números enteros ale-
atorios comprendidos entre 0 y 30000 y los ordene de forma descendente
por el método de Burbuja. El programa debe mostrar el tiempo que requie-
re el método para encontrar los resultados.
2. Cree una página HTML que genere una lista con 2000 registros con los
campos: nombre, correo electrónico, fecha de nacimiento y carnet de
identidad. La página debe ordenar ascendentemente los registros por el
campo nombre, empleando el método de Burbuja implementado de forma re-
cursiva.
3. Cree una página HTML que genere una lista con 15000 números enteros ale-
atorios comprendidos entre 0 y 30000 y los ordene de forma descendente
por el método de Selección. El programa debe mostrar el tiempo que re-
quiere el método para encontrar los resultados.
4. Cree una página HTML que genere una lista con 2000 registros con los
campos: nombre, correo electrónico, fecha de nacimiento y carnet de
identidad. La página debe ordenar ascendentemente los registros por el
campo correo electrónico, empleando el método de Selección.
5. Cree una página HTML que genere una lista con 15000 números enteros ale-
atorios comprendidos entre 0 y 30000 y los ordene de forma ascendente
por el método de Inserción implementado en forma recuriva. El programa
debe mostrar el tiempo que requiere el método para encontrar los resul-
tados.
6. Cree una página HTML que genere una lista con 15000 números enteros ale-
atorios comprendidos entre 0 y 30000 y los ordene de forma ascendente
por el método Shell implementado en forma recursiva. El programa debe
mostrar el tiempo que requiere el método para encontrar los resultados.
7. Cree una página HTML que genere una lista con 15000 números enteros ale-
atorios comprendidos entre 0 y 30000 y los ordene de forma descendente
por el método Quick-Sort. El programa debe mostrar el tiempo que requie-
re el método para encontrar los resultados.
8. Cree una página HTML que genere una lista con 2000 registros con los
campos: nombre, correo electrónico, fecha de nacimiento y carnet de
identidad. La página debe ordenar de forma descendente los registros por
el campo fecha de nacimiento, empleando el método Quick-Sort.
INTERCALACIÓN Y BÚSQUEDA - 163 -
8. INTERCALACIÓN Y BÚSQUEDA
8.1. INTERCALACIÓN
recibir x, y
[else]
[i<nx y j<ny]
[else]
[xi < yj ]
[else]
[i < nx ]
zk=xi; i=i+1; k=k+1
[else]
[j < ny ]
zk=yj; j=j+1; k=k+1
devolver z
>>y=round(rand(20,1,50)).sort(function(a,b){return b-a;})
[48, 48, 44, 43, 42, 41, 39, 39, 38, 31, 29, 27, 21, 20, 18, 14, 9, 7, 6,
6]
>>z=intercalar(x,y,function(a,b){return b-a;})
[48, 48, 48, 44, 43, 42, 42, 41, 41, 39, 39, 38, 37, 36, 34, 32, 31, 30,
29, 28, 27, 27, 21, 20, 19, 18, 16, 14, 11, 11, 9, 7, 6, 6, 4]
Las funciones de comparación son útiles no sólo en la intercalación, sino
principalmente en los métodos de ordenación, pues con las mismas se pueden
crear módulos de carácter más general. Empleando estas funciones se han
añadido, a la librería “hpvlib.js”, funciones para los métodos de burbuja
(“burbuja”), selección (“seleccion”), inserción (“insercion”), shell (“she-
ll”) y quick-sort (“quick”). Todas ellas pueden recibir el vector a ordenar
y la función de comparación.
Al igual que con “intercalar”, si no se manda la función de comparación,
los métodos de ordenación generan una función por defecto, la misma que en
la función “intercalar”. En otras palabras, si no se manda la función de
comparación, los elementos se ordenan de forma ascendente.
Por ejemplo si se genera una lista con 1000 elementos enteros aleatorios
comprendidos entre 1 y 5000:
>>randseed=1; x=round(rand(1000,1,5000));
Puede ser ordenada de forma descendente, con el método Shell, escribiendo
la siguiente instrucción:
>>shell(x,function(a,b){return b-a;});
Con lo que los elementos del vector “x” quedan ordenados descendentemente:
>>x
[5000, 4998, 4993, 4989, 4987, 4966, 4964, 4957, 4953, 4949, 4942, 4928,
4916, 4916, 4911, 4909, 4907, 4905, 4901, 4900, 4899, 4896, 4895, 4891,
4887, 4877, 4875, 4873, 4869, 4859, 4858, 4858, 4853, 4853, 4841, 4838,
4837, 4834, 4831, 4829, 4812, 4807, 4796, 4793, 4793, 4787, 4780, 4774,
4772, 4770, 4769, 4762, 4753, 4751, 4741, 4738, 4730, 4729, 4719, 4717,
4709, 4709, 4706, 4698, 4698, 4694, 4684, 4679, 4676, 4674, 4671, 4670,
4669, 4669, 4666, 4666, 4666, 4656, 4654, 4645, 4644, 4638, 4638, 4637,
4633, 4633, 4632, 4630, 4626, 4623, 4622, 4622, 4620, 4618, 4614, 4613,
4611, 4608, 4587, 4583, 4582, 4579, 4574, 4564, 4561, 4549, 4548, 4525,
4522, 4521, 4514, 4513, 4507, 4502, 4501, 4496, 4495, 4490, 4488, 4482,
4480, 4478, 4477, 4471, 4441, 4437, 4434, 4427, 4425, 4423, 4422, 4415,
4410, 4405, 4399, 4395, 4394, 4385, 4374, 4368, 4367, 4362, 4358, 4357,
4348, 4338, 4334, 4328, 4328, 4326, 4322, 4318, 4317, 4312, 4310, 4306,
4303, 4303, 4289, 4270, 4262, 4253, 4234, 4230, 4219, 4216, 4214, 4205,
4204, 4203, 4202, 4197, 4195, 4190, 4182, 4180, 4180, 4176, 4176, 4175,
4167, 4163, 4162, 4151, 4143, 4142, 4142, 4139, 4139, 4138, 4133, 4131,
4123, 4122, 4106, 4102, 4096, 4095, 4093, 4085, 4083, 4070, 4069, 4066,
4064, 4062, 4057, 4054, 4054, 4045, 4045, 4045, 4045, 4044, 4042, 4036,
4035, 4023, 4022, 4019, 4017, 3996, 3996, 3991, 3990, 3985, 3979, 3975,
3973, 3969, 3966, 3961, 3947, 3944, 3943, 3937, 3936, 3935, 3929, 3925,
3924, 3915, 3911, 3897, 3896, 3894, 3889, 3872, 3857, 3850, 3839, 3836,
3829, 3824, 3821, 3816, 3815, 3812, 3799, 3797, 3769, 3763, 3757, 3757,
3754, 3751, 3751, 3739, 3739, 3737, 3731, 3729, 3701, 3700, 3694, 3685,
3677, 3677, 3674, 3670, 3665, 3657, 3657, 3649, 3644, 3644, 3639, 3637,
3636, 3631, 3630, 3619, 3617, 3613, 3610, 3610, 3600, 3597, 3595, 3592,
3581, 3580, 3579, 3576, 3571, 3568, 3568, 3567, 3567, 3566, 3562, 3561,
3550, 3547, 3541, 3536, 3536, 3533, 3532, 3530, 3528, 3520, 3494, 3493,
3486, 3484, 3470, 3463, 3461, 3460, 3453, 3447, 3443, 3440, 3439, 3435,
3424, 3424, 3418, 3418, 3401, 3363, 3355, 3349, 3348, 3338, 3337, 3336,
INTERCALACIÓN Y BÚSQUEDA - 167 -
3330, 3324, 3324, 3309, 3298, 3294, 3294, 3291, 3290, 3269, 3267, 3260,
3260, 3253, 3251, 3245, 3242, 3240, 3233, 3217, 3214, 3207, 3200, 3195,
3189, 3188, 3185, 3180, 3173, 3170, 3168, 3162, 3156, 3153, 3149, 3145,
3136, 3134, 3132, 3125, 3124, 3117, 3116, 3115, 3110, 3100, 3097, 3087,
3086, 3076, 3076, 3067, 3059, 3053, 3045, 3043, 3040, 3036, 3036, 3027,
3021, 3018, 3013, 2994, 2988, 2988, 2981, 2970, 2966, 2962, 2956, 2953,
2941, 2939, 2934, 2933, 2927, 2923, 2919, 2914, 2893, 2893, 2891, 2887,
2883, 2883, 2882, 2880, 2875, 2869, 2869, 2868, 2864, 2864, 2859, 2858,
2852, 2849, 2848, 2848, 2842, 2835, 2831, 2826, 2826, 2815, 2810, 2803,
2800, 2799, 2794, 2794, 2783, 2777, 2776, 2771, 2767, 2761, 2759, 2751,
2750, 2750, 2749, 2747, 2745, 2740, 2738, 2732, 2727, 2721, 2720, 2719,
2701, 2680, 2680, 2677, 2676, 2672, 2667, 2663, 2655, 2649, 2639, 2633,
2621, 2613, 2611, 2604, 2604, 2603, 2595, 2593, 2579, 2577, 2571, 2565,
2564, 2562, 2562, 2555, 2548, 2542, 2539, 2538, 2534, 2525, 2525, 2522,
2513, 2508, 2501, 2490, 2488, 2484, 2483, 2482, 2481, 2459, 2458, 2456,
2455, 2452, 2440, 2436, 2436, 2432, 2426, 2423, 2422, 2418, 2417, 2417,
2411, 2410, 2404, 2391, 2383, 2379, 2372, 2370, 2370, 2370, 2367, 2345,
2340, 2339, 2332, 2326, 2321, 2309, 2307, 2305, 2304, 2302, 2294, 2288,
2281, 2280, 2274, 2267, 2259, 2258, 2257, 2253, 2247, 2241, 2236, 2235,
2228, 2226, 2221, 2219, 2215, 2215, 2215, 2211, 2204, 2199, 2196, 2193,
2182, 2167, 2164, 2162, 2161, 2161, 2161, 2157, 2155, 2150, 2147, 2147,
2133, 2133, 2128, 2118, 2113, 2112, 2100, 2084, 2070, 2070, 2069, 2066,
2065, 2062, 2060, 2052, 2048, 2042, 2040, 2040, 2031, 2030, 2029, 2019,
1991, 1985, 1984, 1977, 1957, 1956, 1952, 1949, 1948, 1947, 1942, 1921,
1919, 1918, 1918, 1912, 1906, 1905, 1899, 1891, 1888, 1885, 1883, 1871,
1870, 1867, 1864, 1859, 1856, 1853, 1852, 1851, 1850, 1847, 1838, 1832,
1829, 1823, 1821, 1812, 1803, 1802, 1801, 1796, 1790, 1789, 1779, 1776,
1766, 1765, 1765, 1762, 1761, 1755, 1754, 1750, 1746, 1737, 1737, 1719,
1712, 1709, 1692, 1690, 1673, 1672, 1659, 1646, 1634, 1625, 1622, 1619,
1609, 1608, 1603, 1595, 1594, 1573, 1571, 1570, 1569, 1565, 1561, 1560,
1548, 1525, 1522, 1513, 1512, 1502, 1498, 1498, 1492, 1492, 1490, 1471,
1470, 1467, 1444, 1430, 1428, 1411, 1411, 1409, 1403, 1401, 1397, 1393,
1389, 1383, 1371, 1370, 1369, 1368, 1365, 1362, 1354, 1354, 1348, 1338,
1330, 1324, 1324, 1321, 1320, 1318, 1313, 1311, 1305, 1282, 1280, 1272,
1271, 1264, 1257, 1251, 1249, 1247, 1242, 1239, 1236, 1230, 1221, 1219,
1212, 1211, 1210, 1203, 1202, 1200, 1199, 1187, 1173, 1171, 1170, 1168,
1154, 1153, 1150, 1149, 1138, 1138, 1137, 1134, 1133, 1133, 1131, 1128,
1125, 1122, 1117, 1117, 1112, 1106, 1104, 1101, 1100, 1099, 1098, 1090,
1080, 1073, 1073, 1069, 1060, 1060, 1058, 1047, 1046, 1042, 1039, 1037,
1030, 1027, 1011, 1006, 1005, 1002, 986, 981, 975, 964, 962, 956, 954, 953,
947, 945, 940, 936, 936, 931, 928, 922, 908, 906, 898, 888, 885, 883, 878,
872, 858, 851, 847, 847, 832, 825, 822, 810, 807, 802, 788, 777, 777, 777,
770, 753, 746, 737, 728, 728, 726, 724, 722, 719, 713, 712, 708, 705, 705,
705, 705, 697, 690, 682, 679, 657, 655, 654, 652, 635, 627, 626, 619, 617,
613, 610, 593, 592, 590, 586, 572, 570, 570, 566, 564, 561, 557, 549, 540,
538, 531, 528, 516, 514, 514, 505, 497, 495, 494, 489, 481, 473, 473, 468,
464, 459, 458, 452, 441, 439, 432, 420, 416, 414, 396, 392, 391, 371, 369,
369, 365, 359, 358, 355, 350, 346, 345, 342, 332, 297, 282, 273, 268, 265,
260, 255, 253, 245, 242, 236, 227, 227, 225, 223, 222, 220, 216, 212, 200,
192, 190, 187, 185, 184, 173, 171, 169, 167, 165, 163, 153, 143, 132, 128,
124, 119, 117, 105, 103, 102, 96, 92, 80, 75, 66, 58, 58, 56, 54, 54, 32,
27, 16, 7]
Como ya se dijo, la intercalación puede ser empleada conjuntamente los
métodos de ordenación (principalmente los métodos directos) para optimizar
el proceso de ordenación. En ese caso, sin embargo, las listas a intercalar
así como la lista resultante deben estar en el mismo vector por lo que es
necesario modificar los algoritmos tanto del método de ordenación como de
intercalación para tomar en cuenta ese hecho.
- 168 - Hernán Peñaranda V.
<script src="hpvlib.js"></script>
<script>
var v;
function genvec(){
randseed=10;
v=round(rand(10000,1,20000));
}
function generar(){
genvec();
document.getElementById("ta1").innerHTML=v;
}
function ordenar(){
var t1,t2,dt;
t1=new Date();
burbujai(v,function(a,b){return a-b;});
t2=new Date();
dt=t2.getTime()-t1.getTime();
document.getElementById("ta2").innerHTML=v;
document.getElementById("it1").value=dt+" ms.";
genvec();
t1 = new Date();
burbuja(v,function(a,b){return a-b;});
t2 = new Date();
dt=t2.getTime()-t1.getTime();
document.getElementById("it2").value=dt+" ms.";
}
</script>
<style type="text/css">
textarea {
background-color:lightyellow;
}
</style>
</head>
<body>
</body>
</html>
Abriendo la página en un navegador, generando el vector y ordenando el
mismo y haciendo correr el programa se obtiene algo parecido a:
- 170 - Hernán Peñaranda V.
recibir x, j, v
n = Nº de elementos en x
i= j
[xi = v]
[else]
[i<n] devolver i
i = i+1
[else]
devolver -1
>>bsecuencial(x,0,77)
96
Por lo tanto, el primer número 77 se encuentra en la posición 97 (recuer-
de que los vectores en Javascript el primer elemento es el elemento 0). Se
puede buscar otro elemento que tenga el número 77 comenzando la búsqueda en
la posición 97 (96+1):
>>bsecuencial(x,97,77)
152
Y continuar de esa manera la búsqueda de otros elementos que tengan el
número 77:
>>bsecuencial(x,153,77)
184
>>bsecuencial(x,185,77)
-1
Como se puede ver existe otro elemento (en la posición 185) que tiene el
número 77, luego “bsecuencial” devuelve “-1”, informando que ya no existen
más elementos con ese número.
Se puede realizar la búsqueda de todos los elementos que tienen el número
77 y devolver un vector con las posiciones de dichos elementos, empleando
un ciclo “while”:
>r=[]; p=0; while((p=bsecuencial(x,p,77))>0){r.push(p); p++;}; r
[96, 152, 184]
En estos casos, funciona bien la función de comparación por defecto, sin
embargo, si por ejemplo se tiene la siguiente lista con apellidos:
>>randseed=0; v=new Array(100); for(i=0;i<100;i++) v[i]=generarApellido();
v
[Canquichoque, Peinado, Losada, Pocoata, Rosado, Anglada, Fabregat, Salom,
Viana, Lledó, Calzada, Paco, Navas, Coello, Mesa, Aucapoma, Manzano, Boada,
Dávila, Garriga, Quisicala, Queso, Chachajaque, Seguí, Rodríguez, Leal, Sa-
las, Sirpa, Montes, Baeza, Ferrán, Varela, Aznar, Porras, Velasco, Casares,
Figueras, Almansa, Trillo, Pereira, Moreno, Mascaró, Boada, Barón, Morell,
Barrios, Valle, Huanca, Alfonso, Ledesma, Llanquechoque, Colque, Chacón,
Casado, Duarte, Mateo, Zabala, Mateu, Tello, Caparrós, Goicoechea, Naranjo,
Crespo, Coello, Camino, Ponce, Montaña, Adadia, Solano, Rebollo, Inca, Be-
nito, Carreño, Almazán, Villalba, Esteve, Aruquipa, Quero, Montoya, Apari-
cio, Valle, Fiol, Espejo, Uriarte, Ayala, García, Bayón, Caballero, Mori-
llo, Villarroel, Albero, Gascón, Sinchiroca, Aquise, Canqui, Carvajal, Pe-
rea, Gargallo, Inca, Franch]
Y se quiere encontrar el primer elemento cuyo apellido comienza con “Pe”
(no apellidos iguales a “Pe”, sino los que comienza con “Pe”). En ese caso
es necesario mandar la función de comparación para se compare sólo los dos
primeros caracteres de los apellidos con el valor buscado, como sucede con
la siguiente instrucción:
>>bsecuencial(v,0,"Pe",function(a,b){return a==b.substr(0,2) ? 0 : 1;})
1
Que como se puede ver, informa que el segundo elemento tiene un nombre
que comienza con “Pe”. Para obtener la lista de todos los elementos cuyos
apellidos comienzan con “Pe”, se procede como en el ejemplo anterior:
>>r=[]; p=0; while((p=bsecuencial(v,p,"Pe",function(a,b){return
a==b.substr(0,2) ? 0: 1;}))>0){r.push(p); p++;}; r
[1, 39, 96]
INTERCALACIÓN Y BÚSQUEDA - 173 -
x1 x2 x3 x4 x5 x6 x7
1 3 5 9 11 21 22
x1 x2 x3 x4 x5 x6 x7
1 3 5 9 11 21 22
x1 x2 x3
1 3 5
x3
5
x1 x2 x3 x4 x5 x6 x7
1 3 5 9 11 21 22
x5 x6 x7
11 21 22
x5
11
recibir x, v
j = Nº de elementos en x -1
i =0
k = cociente((i+j)/2)
[x k = v]
[else] [else]
[else] [xk > v]
[(xk-1=v) y (k>0)]
i = k+1 j = k-1 k = k-1
[else]
[i > j]
devolver -1 devolver k
do{
k=quot(i+j,2);
if (!fc(v,x[k])) {
while (!fc(v,x[k-1]) && k>0) k--; return k;}
if (fc(v,x[k])<0) j=k-1; else i=k+1;
} while(i<=j);
return -1;
}
Como de costumbre, si no se manda una función de comparación, el método
genera una por defecto, la cual funciona bien si el valor buscado se compa-
ra directamente con los valores (como un todo) de los elementos.
Por ejemplo, si se genera y ordena un vector con 100 números enteros com-
prendidos entre 1 y 200:
>>randseed=1; x=round(rand(100,1,200)).sort(function(a,b){return a-b;})
[4, 5, 6, 11, 16, 21, 25, 26, 26, 29, 29, 30, 37, 38, 41, 44, 44, 51, 52,
53, 54, 57, 60, 61, 64, 64, 66, 68, 69, 71, 71, 72, 73, 73, 75, 77, 82, 83,
85, 90, 91, 92, 99, 104, 104, 105, 106, 107, 110, 110, 110, 110, 116, 116,
118, 119, 130, 132, 134, 138, 138, 139, 140, 141, 141, 142, 144, 146, 147,
148, 153, 154, 157, 158, 159, 159, 160, 162, 162, 162, 167, 168, 170, 172,
173, 173, 174, 181, 182, 183, 185, 186, 187, 191, 191, 191, 197, 199, 199,
200]
Y se quiere ubicar la posición (el índice) del primer elemento que con-
tiene el número 71, la función de comparación por defecto es suficiente:
>>bbinaria(x,71)
29
Entonces el primer número 71 se encuentra en el elemento con el índice
29. Sin embargo, si se genera y ordena una lista con 100 nombres femeninos:
- 176 - Hernán Peñaranda V.
recibir x, v
n = Nº de elementos en x
[(v<x i) o (v>xj )]
[m>10]
m=m/10; d=d*10
devolver -1
k=i
[v=xk]
[v<x k]
[(k>0) y (v=x k) ]
k=k+d k=k-1
k<=j
j=k
devolver k
i=k-d+1; d=d/10
[d>0]
devolver -1
>>x[8323]
14571
Y verificando además que el elemento anterior, no contiene el número bus-
cado:
>>x[8322]
14570
Como de costumbre, si la lista contiene datos estructurados o si la bús-
queda es parcial, para la realizar la búsqueda (así como para ordenar la
lista) se debe mandar además la función de comparación.
Por ejemplo, si con el siguiente constructor, que genera un registro
aleatorio con los campos nombre, dirección y teléfono:
>>genreg=function(){this.nombre=generarApellido()+" " +generarApellido()+"
"+(round(random(0,1))?generarNombreF():generarNombreM()), this.direccion=
generarCalle()+" "+round(random(1,1000)), this.telefono=6400000+
round(random(1,99999))};
Se crea una lista con 100 registros y se la ordena por el campo nombre
(con el método Quick-Sort):
>>randseed=1; y=[]; for(i=0;i<100;i++) y.push(new genreg()); quick(y,
function(a,b){return a.nombre==b.nombre?0:a.nombre>b.nombre?1:-1;}); y
[{nombre:Abascal Artigas Nieves, direccion:Gregorio Pacheco 146,
telefono:6433777}, {nombre:Alcázar Lobo Dora, direccion:Pasje Estrada 361,
telefono:6409438}, {nombre:Aramburu Lucas Abib, direccion:George Rouma 241,
telefono:6413086}, {nombre:Aznar Coello Deyanira, direccion:Pilinco 948,
telefono:6439524}, {nombre:Baena Iniesta Natasha, direccion:Potosí 946,
telefono:6413130}, {nombre:Balaguer Torrents Niceto, direccion:Miguel Antel
Valda 488, telefono:6403718}, {nombre:Barragán Alemán Rene,
direccion:Regimiento Azurduy 699, telefono:6487688}, {nombre:Barranco Ruano
Samantha, direccion:Warnes 414, telefono:6493413}, {nombre:Batlle
Montserrat Victoria, direccion:La Paz 531, telefono:6489559},
{nombre:Batlle Siripaca Diego, direccion:Villa Serrano 927,
telefono:6436577}, {nombre:Bernat Nebot Vladimiro, direccion:Nataniel
Aguirre 534, telefono:6442246}, {nombre:Bernat Pujol Iris, direccion:Tomás
Katari 716, telefono:6403039}, {nombre:Blanes Novoa Adelgunda,
direccion:Potosí 505, telefono:6444283}, {nombre:Blázquez Almeida Casimiro,
direccion:George Rouma 102, telefono:6428543}, {nombre:Bolaños Barrios
Recaredo, direccion:Tarija 979, telefono:6492216}, {nombre:Bonilla
Huarahuara Saverio, direccion:Guillermo Loayza 598, telefono:6444718},
{nombre:Borrell Carbajo Hina, direccion:J. Prudencio Bustillos 843,
telefono:6406911}, {nombre:Bou Mulet Marite, direccion:Uruguay 979,
telefono:6404826}, {nombre:Busquets Amo Leila, direccion:Isabel Acrelo 609,
telefono:6441985}, {nombre:Cabañas Bello Omar, direccion:Demetrio Canelas
652, telefono:6452073}, {nombre:Camps Llanque Ximena, direccion:Iturricha
143, telefono:6463745}, {nombre:Canquichoque Estévez Oberto,
direccion:Emilio Hochman 431, telefono:6436026}, {nombre:Carani Caparrós
Danae, direccion:Ravelo 572, telefono:6438342}, {nombre:Carani Garay
Aspasia, direccion:Cobija 959, telefono:6428170}, {nombre:Cardona Salcedo
Naim, direccion:Osvaldo Molina 113, telefono:6402535}, {nombre:Casares
Rosales Hermalindo, direccion:Regimiento Azurduy 348, telefono:6444288},
{nombre:Castells Huertas Tecla, direccion:Estudiantes 967,
telefono:6435792}, {nombre:Castelló Barrios Cedric, direccion:Urriolagoitia
826, telefono:6446085}, {nombre:Castrillo Lorenzo Velasco, direccion:Peru
128, telefono:6490414}, {nombre:Chana Carmona Elfida, direccion:J. A.
Martinez 974, telefono:6404413}, {nombre:Charca Mora Ivana,
direccion:Avenida del Maestro 570, telefono:6488671}, {nombre:Chico Moreno
Yajaira, direccion:Sebastian Garcia 377, telefono:6444295}, {nombre:Chiuchi
INTERCALACIÓN Y BÚSQUEDA - 179 -
8.5. EJERCICIOS
Para presentar los ejemplos y ejercicios del tema, debe crear una carpeta
con el nombre “tema8” y guardar en la misma todos los archivos HTML creados
(ejemplos y ejercicios).
1. Cree una página HTML con tres “textarea”, dos botones y las etiquetas
(label) que sean necesarias. En el primer “textarea” se deben mostrar
los 3000 elementos de un vector con números aleatorios comprendidos en-
tre 1 y 5000 ordenados ascendentemente con el método de selección. En el
segundo se deben mostrar los 2350 elementos de un vector con números en-
teros aleatorios comprendidos entre 1 y 4800 ordenados ascendentemente
con el método de burbuja. En el tercer “textarea” se deben mostrar los
elementos intercalados de los vectores de los dos primeros “textarea”.
INTERCALACIÓN Y BÚSQUEDA - 181 -
Los elementos deben ser generados al hacer clic en uno de los botones y
la intercalación debe tener lugar haciendo clic en el otro.
2. Cree una página HTML con dos “textarea”, dos botones, dos “input text” y
las etiquetas (label) que sean necesarias. En el primer “textarea” se
deben mostrar los 3000 elementos de un vector con registros aleatorios
con los campos apellido paterno, apellido materno y nombres (1 o 2). En
el segundo se deben mostrar los registros ordenados por los campos ape-
llido paterno + apellido materno + nombres. Los registros deben ser ge-
nerados al hacer clic en uno de los botones y deben ser ordenados, con
una combinación entre los métodos de selección y de intercalación, al
hacer clic en el otro. En los “input text” se debe mostrar el tiempo re-
querido para ordenar los registros por el método combinado y el método
de selección por si solo.
3. Cree una página HTML con un “textarea”, dos “input text”, un “button” y
las etiquetas (label) que sean necesarias. En el “textarea” se deben
mostrar los elementos de un vector con 10000 números enteros aleatorios
comprendidos entre 0 y 20000, en uno de los “input text” se debe intro-
ducir el valor a buscar y en el otro se debe mostrar la posición del va-
lor buscado. Se debe hacer clic en el botón tanto para comenzar la bús-
queda con el método de búsqueda secuencial, como para continuar la bús-
queda y ubicar el siguiente valor en el vector.
4. Cree una página HTML con un “textarea”, dos “input text”, un “button” y
las etiquetas (label) que sean necesarias. En el “textarea” se deben
mostrar los elementos de un vector con 1000 nombres masculinos aleato-
rios, en uno de los “input text” se debe introducir el nombre a buscar,
el cual puede ser un nombre completo o parcial y en el otro se debe mos-
trar la posición del valor buscado. Se debe hacer clic en el botón tanto
para comenzar la búsqueda con el método de búsqueda secuencial, como
para continuar la búsqueda y ubicar el siguiente valor en el vector.
5. Cree una página HTML con un “textarea”, dos “input text”, un “button” y
las etiquetas (label) que sean necesarias. En el “textarea” se deben
mostrar los elementos de un vector con 10000 números enteros aleatorios
comprendidos entre 1 y 15000, ordenados ascendentemente con el método
Shell. En uno de los “input text” se debe introducir el valor a buscar y
en el otro se debe mostrar la posición del valor buscado. Se debe hacer
clic en el botón para comenzar la búsqueda con el método de búsqueda bi-
naria.
6. Cree una página HTML con un “textarea”, dos “input text”, un “button” y
las etiquetas (label) que sean necesarias. En el “textarea” se deben
mostrar los elementos de un vector con 2000 números nombres masculinos
aleatorios, ordenados descendentemente con el método Quick-Sort. En uno
de los “input text” se debe introducir el valor a buscar, el cual puede
ser un nombre completo o parcial y en el otro se debe mostrar la posi-
ción del valor buscado. Se debe hacer clic en el botón para comenzar la
búsqueda con el método de búsqueda binaria.
7. Cree una página HTML con un “textarea”, dos “input text”, un “button” y
las etiquetas (label) que sean necesarias. En el “textarea” se deben
mostrar los elementos de un vector con 20000 números enteros comprendi-
dos entre 1 y 30000, ordenados descendentemente con el método Shell. En
uno de los “input text” se debe introducir el valor a buscar y en el
otro se debe mostrar la posición del valor buscado. Se debe hacer clic
en el botón para comenzar la búsqueda con el método de búsqueda secuen-
- 182 - Hernán Peñaranda V.
cial indexada.
8. Cree una página HTML con un “textarea”, dos “input text”, un “button” y
las etiquetas (label) que sean necesarias. En el “textarea” se deben
mostrar los elementos de un vector con 1000 registros aleatorios con los
campos nombre (con un apellido y un nombre), teléfono y fecha de naci-
miento. Los registros deben estar ordenados descendentemente, con el mé-
todo Shell, por el campo nombre. En uno de los “input text” se debe in-
troducir el nombre a buscar, el cual puede ser completo o parcial y en
el otro se debe mostrar la posición del valor buscado. Se debe hacer
clic en el botón para comenzar la búsqueda con el método de búsqueda se-
cuencial indexada.