Introducción a C#
Por Nacho Cabanes, versión 0.93 de 16-abr-2010

8. Punteros y gestión dinámica de memoria

8.1. ¿Por qué usar estructuras dinámicas?

Hasta ahora teníamos una serie de variables que declaramos al principio del programa o de cada función. Estas variables, que reciben el nombre de ESTÁTICAS, tienen un tamaño asignado desde el momento en que se crea el programa.

Este tipo de variables son sencillas de usar y rápidas... si sólo vamos a manejar estructuras de datos que no cambien, pero resultan poco eficientes si tenemos estructuras cuyo tamaño no sea siempre el mismo.

Es el caso de una agenda: tenemos una serie de fichas, e iremos añadiendo más. Si reservamos espacio para 10, no podremos llegar a añadir la número 11, estamos limitando el máximo. Una solución sería la de trabajar siempre en el disco: no tenemos límite en cuanto a número de fichas, pero es muchísimo más lento.

Lo ideal sería aprovechar mejor la memoria que tenemos en el ordenador, para guardar en ella todas las fichas o al menos todas aquellas que quepan en memoria.

Una solución "típica" (pero mala) es sobredimensionar: preparar una agenda contando con 1000 fichas, aunque supongamos que no vamos a pasar de 200. Esto tiene varios inconvenientes: se desperdicia memoria, obliga a conocer bien los datos con los que vamos a trabajar, sigue pudiendo verse sobrepasado, etc.

La solución suele ser crear estructuras DINÁMICAS, que puedan ir creciendo o disminuyendo según nos interese. En los lenguajes de programación "clásicos", como C y Pascal, este tipo de estructuras se tienen que crear de forma básicamente artesanal, mientras que en lenguajes modernos como C#, Java o las últimas versiones de C++, existen esqueletos ya creados que podemos utilizar con facilidad.

Algunos ejemplos de estructuras de este tipo son:

Y la cosa se va complicando: en los árboles cada elemento puede tener varios sucesores (se parte de un elemento "raíz", y la estructura se va ramificando), etc.

Todas estas estructuras tienen en común que, si se programan correctamente, pueden ir creciendo o decreciendo según haga falta, al contrario que un array, que tiene su tamaño prefijado.

Veremos ejemplos de cómo crear estructuras dinámicas de estos tipos en C#, y después comentaremos los pasos para crear una estructura dinámica de forma "artesanal".

8.2. Una pila en C#

Para crear una pila tenemos preparada la clase Stack. Los métodos habituales que debería permitir una pila son introducir un nuevo elemento en la cima ("apilar", en inglés "push"), y quitar el elemento que hay en la cima ("desapilar", en inglés "pop"). Este tipo de estructuras se suele llamar también con las siglas "LIFO" (Last In First Out: lo último en entrar es lo primero en salir). Para utilizar la clase "Stack" y la mayoría de las que veremos en este tema, necesitamos incluir en nuestro programa una referencia a "System.Collections".

Así, un ejemplo básico que creara una pila, introdujera tres palabras y luego las volviera a mostrar sería:

/*---------------------------*/
/*  Ejemplo en C#            */
/*  pila1.cs                 */
/*                           */
/*  Ejemplo de clase "Stack" */
/*                           */
/*  Introduccion a C#,       */
/*    Nacho Cabanes          */
/*---------------------------*/
 
using System;
using System.Collections;
 
public class ejemploPila1  {
 
   public static void Main()  {
 
      string palabra;
 
      Stack miPila = new Stack();
      miPila.Push("Hola,");
      miPila.Push("soy");
      miPila.Push("yo");
 
      for (byte i=0; i<3; i++) {
        palabra = (string) miPila.Pop();
        Console.WriteLine( palabra );
      }
 
   }
 
}
 

cuyo resultado sería:


yo
soy
Hola,

La implementación de una pila en C# es algo más avanzada: permite también métodos como:

8.3. Una cola en C#

Podemos crear colas si nos apoyamos en la clase Queue. En una cola podremos introducir elementos por la cabeza ("Enqueue", encolar) y extraerlos por el extremo opuesto, el final de la cola ("Dequeue", desencolar). Este tipo de estructuras se nombran a veces también por las siglas FIFO (First In First Out, lo primero en entrar es lo primero en salir). Un ejemplo básico similar al anterior, que creara una cola, introdujera tres palabras y luego las volviera a mostrar sería:

/*---------------------------*/
/*  Ejemplo en C#            */
/*  cola1.cs                 */
/*                           */
/*  Ejemplo de clase "Queue" */
/*                           */
/*  Introduccion a C#,       */
/*    Nacho Cabanes          */
/*---------------------------*/
 
using System;
using System.Collections;
 
public class ejemploCola1  {
 
   public static void Main()  {
 
      string palabra;
 
      Queue miCola = new Queue();
      miCola.Enqueue("Hola,");
      miCola.Enqueue("soy");
      miCola.Enqueue("yo");
 
      for (byte i=0; i<3; i++) {
        palabra = (string) miCola.Dequeue();
        Console.WriteLine( palabra );
      }
 
   }
 
}
 

que mostraría:


Hola,
soy
yo

Al igual que ocurría con la pila, la implementación de una cola que incluye C# es más avanzada que eso, con métodos similares a los de antes: