domingo, 29 de octubre de 2017

Listas, Colas, Pilas y Conjuntos en C# - Parte 5/6: BitArray

Índice

1. Introducción
2. Palabras Clave
3. La Clase BitArray
4. Conclusiones
5. Literatura & Enlaces

1. Introducción

La razón de ser de la clase que estudia en este artículo destaca además por su crecimiento dinámico, pero su gestión eficiente en memoria de los valores booleanos: inclusive superior a un arreglo o una List genérica de elementos bool.

2. Palabras Clave

  • Arreglo
  • bool
  • Crecimiento dinámico
  • Eficiencia
  • Lista

3. La Clase BitArray

Internamente la clase BitArray usa un único bit por cada elemento del arreglo, en lugar de los ocho bits (byte) que cupa un elemento bool en una colección de tipo arreglo o List<T> (Albahari, 2012).

Lo anterior se traduce en eficiencia en almacenamiento.

Por otra parte, el crecimiento de esta clase está relacionado de forma directa con la adición o remoción de un elemento: la propiedad Length cambia de acuerdo al número de unidades agregadas o removidas.

Entre los métodos, por su parte, esenciales y particulares a esta clase se hallan:
  • And: lleva a cabo la operación bitwise (Operadores Bitwise (Bit a Bit) en C#) de y o conjugación lógica.
  • Or: realiza la operación bitwise de o inclusivo.
  • Xor: realiza la operación bitwise de o exclusivo.
  • Not: niega o invierte cada unos de los valores del arreglo de bits.
Los primeros tres métodos listados reciben como argumento un elemento BitArray: la operación lógica se lleva bit a bit en en el arreglo dado respecto al que invoca el método.

A continuación un ejemplo de uso básico:

4. Conclusiones

Se presentó el uso básico de la clase BitArray para la manipulación de elementos booleanos que ocupan un único bit en memoria: esto evidencia un alto nivel de eficiencia frente a otras soluciones como List<T> o un arreglo básico elementos bool.

El último artículo de esta serie comprenderá el estudio de las clases genéricas HashSet<T> y SortedSet<T>.

5. Literatura & Enlaces

Albahari, J., Albahari, B. (2012). C# 5.0 in a Nutshell. United States: O'Reilly Media.
BitArray Class (System.Collections) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.collections.bitarray%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
Operadores Bitwise (Bit a Bit) en C# (2017). Recuperado desde: https://ortizol.blogspot.com.co/2013/07/operadores-bitwise-bit-bit-en-c.html


O

domingo, 22 de octubre de 2017

Listas, Colas, Pilas y Conjuntos en C# - Parte 4/6: Stack y Stack(T)

Índice

1. Introducción
2. Palabras Clave
3. Clase No-Genérica Stack
4. Clase Genérica Stack≶T>
5. Conclusiones
6. Literatura & Enlaces

1. Introducción

Este artículo describe la estructura de datos o colección Stack (versión no-genérica y genérica) que organiza los elementos como una pila y sigue el esquema último en entrar primero en salir o LIFO. Se describe la funcionalidad de los métodos principales Push (insertar un elemento) y Pop (remover un elemento); y además, Peek: el cual se usa para obtener el elemento a la cabeza de la pila.

2. Palabras Clave

  • Colección
  • Estructura de datos
  • LIFO
  • Pila
  • Stack

3. Clase No-Genérica Stack

La clase Stack (namespace System.Collections) es la clase que organiza sus elementos siguiendo un esquema LIFO (last-in-last-out), lo que quiere decir es que a medida que se van insertando elementos cada uno de éstos se apila sobre su antecesor y tiene mayor precedencia para ser manipulado. La Figura 1 ilustra el comportamiento de esta estructura:
Pila o Stack
Figura 1. Pila o Stack.
Esta clase corresponde con la versión no-genérica e implementa las interfaces de colecciones ICollection y IEnumerable.

El crecimiento y decrecimiento de esta estructura es dinámico: a medida que se insertan elementos está crece, lo contrario ocurre cuando se remueven elementos ("Stack Class", 2017).

Se puede hablar de tres operaciones básicas:
  • Push: inserta un elemento en la pila, en la parte superior. Mientras que el conteo (Count) sea menor que la capacidad, el rendimiento de la operación es de O(1).
  • Pop: remueve un elemento de la pila. Complejidad O(1).
  • Peek: toma (sin remover) el elemento a la cabeza de la pila. Complejidad o rendimiento O(1).
Un ejemplo de uso básico podría ser:

4. Clase Genérica Stack<T>

Este artefacto o clase representa la versión genérica de esta estructura tipo LIFO. Se halla en el nombre de espacio System.Colletions.Generic. A diferencia de su contraparte no-genérica, cuenta con mayor rendimiento ya que no hace uso de las operaciones boxing y unboxing (Boxing y Unboxing en C#).


Similar a una cola o Queue, esta estructura se usa para el almecenamiento temporal de elementos que siguen una lógica de tratamiento de acuerdo al esquema último-en-entrar-primero-en-salir.


También cuenta con los métodos básicos Push, Pop y Peek.


Vale apuntar que esta clase cuenta con una versión para acceso concurrente: System.Collections.Concurrent.ConcurrentStack<T>; para permitir que múltiples threads acceden a los elementos de la pila ("Stack(T) Class", 2017).


La versión de ejemplo de uso en genéricos queda de la siguiente forma:


5. Conclusiones

En este artículo se presentó la colección o estructura de datos que sigue el esquema de organización de sus elementos basado en LIFO: el último elemento que es insertado a la pila es el primero en salir. Se describieron, grosso modo, las operaciones elementales: Push, Pop y Peek.

En el siguiente artículo se describirá la clase BitArray: colección de valores booleanos compactados.

6. Literatura & Enlaces


Albahari, J., Albahari, B. (2012). C# 5.0 in a Nutshell. United States: O'Reilly Media.

Stack Class (System.Collections) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.collections.stack(v=vs.110).aspx
Stack(T) Class (System.Collections.Generic) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/3278tedw(v=vs.110).aspx
Boxing y Unboxing en C# (2017). Recuperado desde: https://ortizol.blogspot.com.co/2014/03/boxing-y-unboxing-en-c.html



O

domingo, 15 de octubre de 2017

Listas, Colas, Pilas y Conjuntos en C# - Parte 3/6: Queue y Queue(T)

Índice

1. Introducción
2. Palabras Clave
3. Clase No-Genérica Queue
4. Clase Genérica Queue<T>
5. Conclusiones
6. Literatura & Enlaces

1. Introducción

Esta tercera parte se centra en el estudio de dos estructuras basadas en FIFO (First-In-First-Out): primer elemento en entrar, primero en salir. Esta colección se asemaja a una cola de espera, aplicable a modelos que reflejen procesos donde los elementos o entidades son procesados o atentidos a medida que llegan al sistema de espera. C# en particular, cuenta con clases para las operaciones de agregar -Enqueue- y retirar -Dequeue-, e inclusive Peek para obtener el primer elemento a procesar sin removerlo de la estructura. Se estudian las versiones no-genérica y genérica.

2. Palabras Clave

  • Cola de espera
  • Colección
  • Estructura de datos
  • FIFO
  • Genéricos

2. Clase No-Genérica Queue

Esta clase representa una estructura de datos FIFO que acomoda sus elementos de acuerdo al orden en que llegan a la estructura: el primero en llegar será el que ocupe la posición de mayor prioridad de procesamiento, es decir, que está al frente (head) de la estructura. Ocurre lo contrario para los elementos que tienen la prioridad más baja: deberán esperar a ser atentidos al final respecto a los elementos que ocupan posiciones cercanas al frente.
Representación gráfica de una cola de espera
Figura 1. Representación gráfica de una cola de espera ("Stack and Queue", 2017).
La clase Queue ("Queue Class", 2017) se halla en el namespace de estructuras no-genéricas System.Collections. Implementa los protocolos o interfaces ICollections e IEnumerable (Interfaces ICollection y IList en C# - Parte 1/2) propios para operaciones comunes de colecciones y enumeración de los elementos de la estructura, respectivamente.

Entre las utilidades principales de Queue está la de servir como almacenamiento de datos de elementos que requiren acceso en el mismo orden en que fueron puestos en la cola de espera ("Queue Class", 2017).

Para lograr lo anterior, se cuentan con tres métodos u operaciones elementales:
  • Enqueue: o agregar al final de la estructura.
  • Dequeue: o remover al frente de la estructura.
  • Peek: o retornar el elemento al frente de la estructura (no es removido de la colección).
A medida que se agregan elementos a la cola de espera está irá cambiando su tamaño de forma dinámica. En C#, el factor de crecimiento es de 2.0 ("Queue Class", 2017).

Adicionalmente, la colección permite la agregación elementos null y duplicados.

Un ejemplo de uso sencillo podría ser:

Queue cola = new Queue();
cola.Enqueue("C#");
cola.Enqueue("es");
cola.Enqueue("génial");

System.out.println(cola.Dequeue()); // C#
System.out.println(cola.Peek()); // es
System.out.println(cola.Dequeue()); // es

3. Clase Genérica Queue<T;gt

Queue<T> comparte varias de las características y comportamientos de su contraparte no-genérica: colocación de elementos, crecimiento dinámico, métodos de acceso y mutación, entre otros más; pero se distingue en contener elementos a partir de un tipo paramétrico: no es necesario realizar conversiones (casting), y por consiguiente las operaciones de boxing y unboxing no son necesarias.

Existe una versión de este tipo de estructura para operaciones concurrentes o paralelas: ConcurrentQueue<T>. Esta clase permite el acceso concurrente a los elementos de la colección usando diferentes threads ("Queue(T) Class", 2017).

De acuerdo con Albahari (2012), internamente las colas están compuestas por un arreglo que se redimensiona según es requerido, e índices para indicar el final (tail) y principio (head). Esto ayuda que las operaciones de adición y remoción de elementos sean muy eficientes.

Ejemplo de uso básico:

var queuePrimos = new Queue<int>();
queuePrimos.Enqueue(2);
queuePrimos.Enqueue(3);
queuePrimos.Enqueue(5);

// Exportación a un arreglo:
int[] arrPrimos = queuePrimos.ToArray();

Console.WriteLine(queuePrimos.Count); // 3
Console.WriteLine(queuePrimos.Peek()); // 2
Console.WriteLine(queuePrimos.Dequeue()); // 2
Console.WriteLine(queuePrimos.Dequeue()); // 3

// Generación de excepción:
Console.WriteLine(queuePrimos.Dequeue()); // No hay más elementos

4. Conclusiones

Se exploraron las características fundamentales de las clases Queue y Queue<T>: su estructura FIFO (first-in-first-out), manipulación de elementos con los métodos Enqueue y Dequeue, y obtención del primer elemento en entrar con Peek. Estos métodos son comunes tanto para la versión no-genérica y genérica. Se escribieron algunos ejemplos de uso que presentan las funciones más básicas. Se reconoció la existencia la clase ConcurrentQueue<T>.

5. Literatura & Enlaces

Albahari, J., Albahari, B. (2012). C# 5.0 in a Nutshell. United States: O'Reilly Media.
Queue Class (System.Collections) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.collections.queue(v=vs.110).aspx
Interfaces ICollection y IList en C# - Parte 1/2 (2017). Recuperado desde: https://ortizol.blogspot.com.co/2017/08/interfaces-icollection-y-ilist-en-csharp-parte-1-2.html
Computer Algorithms: Stack and Queue (2017). Recuperado desde: http://www.stoimen.com/blog/2012/06/05/computer-algorithms-stack-and-queue-data-structure/
Queue(T) Class (System.Collections.Generic) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/7977ey2c(v=vs.110).aspx


O

domingo, 1 de octubre de 2017

Listas, Colas, Pilas y Conjuntos en C# - Parte 2/6: LinkedList(T)

Índice

1. Introducción
2. Palabras Clave
3. Clase LinkedList<T>
3.1 Estructura
3.2 Inserción
3.3 Implementaciones
3.4 Ejemplo de uso
4. Conclusiones
5. Literatura & Enlaces

1. Introducción

Pasamos ahora estudiar otra estructura de datos o colección para la organización de piezas de datos en una lista doblemente enlazada: su característica distintiva es el doble enlace entre nodos -cada nodo conoce su antecesor y sucesor. Como ya veremos, la operación de inserción es mucho más eficiente aunque encontrar el lugar de inserción tome tiempo de procesador y espacio de memoria considerables.

2. Palabras Clave

  • Colección
  • Estructura de Datos
  • Lista
  • Lista doblemente enlazada

3. Clase LinkedList<T>

3.1 Estructura

Empecemos por ver una versión gráfica de la organización de un objeto de esta clase:
Organización gráfica clase LinkedList(T)
Figura 1. Organización gráfica clase LinkedList<T> (Albahari, 2012). 
Vemos que el objeto LinkedList está compuesto por dos campos que referencian el primer (First) y último (Last) elemento de la lista. Por otra parte, cada elemento de la lista está representado por un objeto LinkedListNode<T>; éste está integrado por tres partes fundamentales:
  • Anterior (Previous)
  • Siguiente (Next)
  • Valor (Value)
Cada uno de estos campos son referencias a otros objetos LinkedListNode<T>. El valor (value) contiene la información concreta de cada nodo: alguna instancia de objeto que agrupa datos de una entidad del mundo del problema.

3.2 Inserción

La inserción entre nodos no cuenta con un mecanismo basado en índices. En su lugar, es necesario recorrer la estructura hasta encontrar el lugar concreto: esto puede ser indicando el o los valores de las entidades relacionadas con el punto de inserción.

La búsqueda binaria ("Búsqueda binaria", 2017), de acuerdo con Albahari (2012), no es posible llevarla a cabo a razón del argumento anterior: no existen índices para el acceso a elementos, y este tipo de algoritmo requiere ir reduciendo el área o campo de búsqueda por cada iteración o recursión.

3.3 Implementaciones

La clase LinkedList<T> implementa las interfaces para enumeración de elementos -IEnumerable<T>-, y operaciones comunes de colecciones con ICollection≶T> (Interfaces ICollection y IList en C# - Parte 2/2). Debido a que los elementos de un objeto de esta clase no permite manipulaciones a partir de índices, ésta no implementa la interfaz IList<T>.

3.4 Ejemplo de uso

Veamos una demostración de código sencilla de un objeto de esta clase. El código que viene a continuación es adaptado de Albahari (2012):

var notas = new LinkedList<string>();
notas.AddFirst("do");
notas.AddLast("so");

notas.AddAfter(notas.First, "re");
notas.AddAfter(notas.First.Next, "mi");
notas.AddBefore(notas.Last, "fa");

// Contenido: do re mi fa so

notas.RemoveFirst();
notas.RemoveLast();

// Contenido: re mi fa

LinkedListNode<string> nota = notas.Find("mi");
notas.Remove (nota);
notas.AddFirst (nota);

// Contenido: mi re fa

foreach(string n in notas){
    Console.WriteLine(n);
}

4. Conclusiones

Comprendimos el uso esencial de la clase genérica LinkedList<T>. Una estructura de datos que nos permite representar información que mantenga una relación lineal de antecesor/sucesor. Notamos que esta clase es especial: no usa un índice para manipular los elementos integrales.

En la tercera parte de esta serie nos centraremos en el estudio de dos clases de colección: Queue<T> y Queue.

5. Literatura & Enlaces




O