Vous êtes sur la page 1sur 58

ALGORITMOS Y

PROGRAMACIÓN
Clase 6
Tipo abstracto de datos

Dr. Lic. Waldo Hasperué


Temario

• Tipo abstracto de datos (TAD)

• TAD Pila

• TAD Cola
Tipo de dato

• En C#, y en otros lenguajes también, existe el concepto


de tipo de dato.

• Un tipo de dato define el dominio (posibles valores) y las


operaciones que se pueden hacer sobre los datos.

• También definen las operaciones entre diferentes tipos de


datos y la conversión entre uno y otro.
Tipo de dato
Tipo de dato Dominio Operaciones
byte 0..255
suma, resta,
int –2.147.483.648...2.147.483.647
multiplicación, división,
1.5 × 10−45 a 3.4 × 1038 resto
float
con precisión de 7 dígitos
bool true, false and, or, not
Letras, dígitos, símbolos, Concatenación para
char
caracteres especiales formar un string
Concatenación,
string Secuencia de caracteres
indexación
Tipo abstracto de datos
• Un tipo abstracto de datos (TAD), especifica
• Un conjunto de operaciones que pueden llevar a cabo
• La semántica de las operaciones (lo que hace cada operación).

• El conjunto de operaciones también se la


denomina como interfaz pública

• No especifica como se implementan dichas


operaciones.
Tipo abstracto de datos
• La implementación interna del TAD está oculta al
programa cliente que lo usa.

• Sólo se puede modificar el estado interno del


TAD con las operaciones definidas por el mismo.
Ventajas del uso de TADs
• Abstracció́ n: Los usuarios de un TAD no
necesitan conocer sus detalles de
implementación. Solo sabe que hace.

• Reutilización: un TAD puede ser utilizado en


distintos desarrollos de aplicaciones.

• Corrección: el código de un TAD, probado y


testeado, disminuye la presencia de errores en
un desarrollo.
TAD Pila
• ¿Qué es una Pila?
TAD Pila
• Una pila es una colección, lo que significa que es una
estructura de datos que contiene múltiples elementos.

• Los elementos que se almacenan en una pila pueden ser


de cualquier tipo. Por esta cualidad, a la pila se la conoce
como tipo de dato genérico.

• La pila implementa una estructura “último en entrar


primero en salir” (LIFO - “last in, first out” en inglés),
porque el elemento añadido en último lugar es el primero
que se extrae.
TAD Pila
• Las operaciones básicas que se pueden realizar con una
pila son apilar (push) y desapilar (pop).

push pop

Al momento de
Todo nuevo extraer un
elemento es elemento, se
colocado al saca el que
tope de la pila está en el tope
TAD Pila
• Las operaciones apilar (push) y desapilar (pop)
constituyen las operaciones mínimas necesarias para
manipular una pila.

• Otras operaciones:
• Tope (top): devuelve el elemento en el tope de la pila sin sacarlo
de la pila.
• Está Vacía (isEmpty): devuelve true si la pila no tiene elementos
TAD Pila
• Las pilas son colecciones de elementos ¿Qué
estructura de datos que conocemos podríamos
usar para almacenar los elementos?
TAD Pila
• Las pilas son colecciones de elementos ¿Qué
estructura de datos que conocemos podríamos
usar para almacenar los elementos?

Los ArrayList
son una buena
opción
TAD Pila
• ¿Cómo se puede implementar?

• Se puede usar directamente el ArrayList


TAD Pila
static public void push(ArrayList pila, int e){
pila.Add(e);
}
static public int pop(ArrayList pila){
int e = (int)pila[pila.Count – 1];
pila.RemoveAt(pila.Count – 1);
return e;
}
TAD Pila
• ¿Cómo se usaría?

static public void Main(){


ArrayList pila = new ArrayList();
push(pila, 4);
push(pila, 10);
push(pila, -23);
Console.WriteLine(pop(pila));
}
TAD Pila
• ¿Cuál son los potenciales problemas de esta implementación?

static public void Main(){


ArrayList pila = new ArrayList();
push(pila, 4);
push(pila, 10);
push(pila, -23);
Console.WriteLine(pop(pila));

pila.Clear();
Console.WriteLine(pila[0]);
pila.RemoveAt(1);
}
TAD Pila
• ¿Cuál son los potenciales problemas de esta implementación?

static public void Main(){


ArrayList pila = new ArrayList();
push(pila, 4);
push(pila, 10); Nada impide que
usemos el ArrayList
push(pila, -23); como tal. Accediendo
Console.WriteLine(pop(pila)); a cualquier método de
la clase ArrayList.
pila.Clear();
Console.WriteLine(pila[0]);
pila.RemoveAt(1);
}
TAD Pila

• ¿Cómo se puede evitar el uso incorrecto en una Pila?

• ¿Qué mecanismos conocemos que garanticen el


encapsulamiento?
TAD Pila
• En C# todos los TAD estarán implementados
cada uno en una clase.

• En el constructor de la clase se inicializan todas


las variables internas del uso de TAD.

• Las operaciones del TAD serán métodos de


instancia.
TAD Pila
public class Pila {
private ArrayList elementos;

public Pila {
elementos = new ArrayList();
}
}
TAD Pila
public class Pila {

public void push(object elemento) {


elementos.Add(elemento);
}

public object pop(){


object elemento = elementos[elementos.Count-1];
elementos.RemoveAt(elementos.Count-1);
return elemento;
}


}
TAD Pila
public class Pila {

public void push(object elemento) {


elementos.Add(elemento);
}

public object pop(){


object elemento = elementos[elementos.Count-1];
elementos.RemoveAt(elementos.Count-1);
return elemento;
}
El tipo object permite
… almacenar en la pila
} elementos de
cualquier tipo de datos
TAD Pila
public class Pila {

public bool isEmpty() {


return elementos.Count == 0;
}

public object top(){


object elemento = elementos[elementos.Count-1];
return elemento;
}


}
TAD Pila
• ¿Cómo se usa?

static public void Main(){


Pila pila = new Pila();
pila.push(4);
pila.push("Hola");
pila.push(-23.98);
Console.WriteLine(pila.pop());
}
TAD Pila
• ¿Cómo se usa?

static public void Main(){


Pila pila = new Pila();
pila.push(4);
pila.push("Hola");
pila.push(-23.98); Ya no es posible
hacer estas
Console.WriteLine(pila.pop()); acciones porque no
son métodos de la
pila.Clear(); clase Pila.
De esta forma
pila.RemoveAt(1); garantizamos el
Console.WriteLine(pila[5]); uso correcto de
} una pila.
TAD Pila
• ¿Cómo se usa?

static public void Main(){


Pila pila = new Pila();
pila.push(4);
pila.push("Hola");
pila.push(-23.98);
Console.WriteLine(pila.pop()); Tampoco es posible
acceder al ArrayList
interno de la pila,
pila.elementos.Clear(); ya que fue
pila.RemoveAt(1); declarado como
private
Console.WriteLine(pila[5]);
}
TAD Pila
• Para procesar todos los elementos de una Pila

static public void Main(){


Pila pila = new Pila();
pila.push(4);
pila.push("Hola");
pila.push(-23.98);

while(! pila.isEmpty())
Console.WriteLine(pila.pop());
}
TAD Pila
Usos del TAD Pila:

• Invertir colecciones

• Determinar palíndromos

• Evaluación de operaciones aritméticas postfija

• Ejecución de soluciones recursivas


TAD Pila
Usos del TAD Pila:

• Historial de navegación en los browser de


internet.

• Manejo de la operación "deshacer".

• Implementación del juego Torre de Hanoi


TAD Cola
• ¿Qué es una Cola?
TAD Cola
• Una cola es una colección, lo que significa que es una
estructura de datos que contiene múltiples elementos.

• Los elementos que se almacenan en una cola pueden ser


de cualquier tipo. Por esta cualidad, a la cola se la
conoce como tipo de dato genérico.

• La cola implementa una estructura “primero en entrar


primero en salir” (FIFO - “first in, first out” en inglés),
porque el elemento añadido en primer lugar es el primero
que se extrae.
TAD Cola
• Las operaciones básicas que se pueden realizar con una
cola son encolar (push o enqueue) y desencolar (pop o
dequeue).
Al momento de
extraer un
push elemento, se
saca el primero
de la cola

Todo nuevo
elemento es
colocado al pop
final de la cola
TAD Cola
• Las operaciones encolar (push) y desencolar (pop)
constituyen las operaciones mínimas necesarias para
manipular una cola.

• Otras operaciones:
• Tope (top): devuelve el elemento que está en el principio de la cola
sin sacarlo.
• Está Vacía (isEmpty): devuelve true si la cola no tiene elementos
TAD Cola
• Las pilas son colecciones de elementos ¿Qué
estructura de datos que conocemos podríamos
usar para almacenar los elementos?

• ¿Cuáles son las diferencias con la Pila?


TAD Cola
• Las pilas son colecciones de elementos ¿Qué
estructura de datos que conocemos podríamos
usar para almacenar los elementos?
• Los ArrayList son una buena opción

• ¿Cuáles son las diferencias con la Pila?


• La diferencia se encuentra en que elemento es retirado de la cola.
• Ahora se quita el primer elemento agregado, no el último.
TAD Cola
public class Cola {
private ArrayList elementos;

public Cola {
elementos = new ArrayList();
}
}
TAD Cola
public class Cola {

public void push(object elemento) {


elementos.Add(elemento);
}

public object pop(){


object elemento = elementos[0];
elementos.RemoveAt(0);
return elemento;
}


}
TAD Cola
public class Cola {

public void push(object elemento) {


elementos.Add(elemento);
}

public object pop(){


object elemento = elementos[0];
elementos.RemoveAt(0);
return elemento;
}
El tipo object permite
… almacenar en la pila
} elementos de
cualquier tipo de datos
TAD Cola
public class Cola {

public bool isEmpty() {


return elementos.Count == 0;
}

public object top(){


object elemento = elementos[0];
return elemento;
}


}
TAD Cola
• ¿Cómo se usa?

static public void Main(){


Cola cola= new Cola();
cola.push(4);
cola.push("Hola");
cola.push(-23.98);
Console.WriteLine(cola.pop());
}
TAD Cola
• Para procesar todos los elementos de una Cola

static public void Main(){


Cola cola = new Cola();
cola.push(4);
cola.push("Hola");
cola.push(-23.98);

while(! cola.isEmpty())
Console.WriteLine(cola.pop());
}
TAD Cola
Usos del TAD Cola:

• Representar colas en la vida real


• Banco
• Correo
• Oficina de atención

• En informática
• Cola de impresión
• Cola de procesos
Ejercicio 1

Escriba una función que reciba una pila y dos valores:


valor_a_buscar y valor_a_reemplazar y que devuelva una
pila donde, toda ocurrencia de valor_a_buscar sea
reemplazada por valor_a_reemplazar . La pila devuelta
debe volver con sus valores en el mismo orden en que
estaban.
NOTA: Los métodos que acepta una pila son pop, push y
isEmpty.
Ejercicio 1
Pila reemplazo(Pila pila, int buscar, int reemplazar){
Pila temporal = new Pila();
while(! pila.isEmpty()){
int v = (int)(pila.pop());
if(v == buscar)
temporal.push(reemplazar)
else
temporal.push(v);
}
Pila nueva = new Pila();
while(! temporal.isEmpty())
nueva.push(temporal.pop());
return nueva;
}
Ejercicio 1 Recorremos la pila
recibida por parámetro
Pila reemplazo(Pila pila, int buscar, int reemplazar){
Pila temporal = new Pila();
while(! pila.isEmpty()){
int v = (int)(pila.pop());
if(v == buscar)
temporal.push(reemplazar)
else
temporal.push(v);
}
Pila nueva = new Pila();
while(! temporal.isEmpty())
nueva.push(temporal.pop());
return nueva;
}
Ejercicio 1 Sacamos un elemento
de la pila
Pila reemplazo(Pila pila, int buscar, int reemplazar){
Pila temporal = new Pila();
while(! pila.isEmpty()){
int v = (int)(pila.pop());
if(v == buscar)
temporal.push(reemplazar)
else
temporal.push(v);
}
Pila nueva = new Pila();
while(! temporal.isEmpty())
nueva.push(temporal.pop());
return nueva;
}
Si el valor sacado es
Ejercicio 1 igual al buscado,
ponemos en la pila
temporal el valor de
Pila reemplazo(Pila pila, int buscar, int
reemplazar){ reemplazo
Pila temporal = new Pila();
while(! pila.isEmpty()){
int v = (int)(pila.pop());
if(v == buscar)
temporal.push(reemplazar)
else
temporal.push(v);
}
Pila nueva = new Pila();
while(! temporal.isEmpty())
nueva.push(temporal.pop());
return nueva;
}
Al finalizar esta
Ejercicio 1 operación, la pila
temporal tiene todos los
valores pero en orden
Pila reemplazo(Pila pila, int buscar, int
reemplazar){ invertidos.
Pila temporal = new Pila(); Usamos una tercer pila
while(! pila.isEmpty()){ para "dar vuelta" los
int v = (int)(pila.pop()); valores que están en
temporal
if(v == buscar)
temporal.push(reemplazar)
else
temporal.push(v);
}
Pila nueva = new Pila();
while(! temporal.isEmpty())
nueva.push(temporal.pop());
return nueva;
}
Ejercicio 2
Escriba un TAD NumeroComplejo con la siguiente
especificación:

NumeroComplejo(double real, double imaginaria);


NumeroComplejo sumar(NumeroComplejo nc);
NumeroComplejo restar(NumeroComplejo nc);
double parteReal;
double parteImaginaria;
string ToString();
bool Equals(NumeroComplejo nc);
Ejercicio 2
class NumeroComplejo{
private double real, imaginaria;
public NumeroComplejo(double real, double imag){
this.real = real;
imaginaria = imag;
}
public NumeroComplejo sumar(NumeroComplejo nc){
return new NumeroComplejo(this.real + nc.parteReal,
this.imaginaria + nc.parteImaginaria);
}
public NumeroComplejo restar(NumeroComplejo nc){
return new NumeroComplejo(this.real - nc.parteReal,
this.imaginaria - nc.parteImaginaria);
}
public double parteReal{
get { return real; }
}
public double parteImaginaria{
get { return imaginaria; }
}
}
Ejercicio 2 (cont.)
class NumeroComplejo{

public override string ToString() {


if(imaginaria < 0)
return real + " - " + Math.Abs(imaginaria) + "i";
else
return real + " + " + Math.Abs(imaginaria) + "i";
}

public override bool Equals(object obj) {


NumeroComplejo nc = (NumeroComplejo)obj;
return (this.real == nc.parteReal) && (this.imaginaria == nc.parteImaginaria);
}
}
Ejercicio 2 (Uso)
public static void Main(string[] args) {
NumeroComplejo nc1 = new NumeroComplejo(3, 6);
NumeroComplejo nc2 = new NumeroComplejo(-3, -6);
NumeroComplejo nc3 = new NumeroComplejo(0, 0);

Console.WriteLine("(" + nc1 + ") - (" + nc2 + ") = (" + nc1.restar(nc2) + ")");

Console.WriteLine(nc1.sumar(nc2).Equals(nc3));

Console.ReadKey();
}
Ejercicio 2 (Uso) Aquí se llama
implícitamente al
método ToString()
public static void Main(string[] args) {
NumeroComplejo nc1 = new NumeroComplejo(3, 6);
NumeroComplejo nc2 = new NumeroComplejo(-3, -6);
NumeroComplejo nc3 = new NumeroComplejo(0, 0);

Console.WriteLine("(" + nc1 + ") - (" + nc2 + ") = (" + nc1.restar(nc2) + ")");

Console.WriteLine(nc1.sumar(nc2).Equals(nc3));

Console.ReadKey();
}
Ejercicio 2 (Uso)
public static void Main(string[] args) {
NumeroComplejo nc1 = new NumeroComplejo(3, 6);
NumeroComplejo nc2 = new NumeroComplejo(-3, -6);
NumeroComplejo nc3 = new NumeroComplejo(0, 0);

Console.WriteLine("(" + nc1 + ") - (" + nc2 + ") = (" + nc1.restar(nc2) + ")");

Console.WriteLine(nc1.sumar(nc2).Equals(nc3));

Console.ReadKey();
}
A nc1 se le suma nc2,
y al resultado devuelto
se los compara con c3
Ejercicio 3

Agregue a la clase NumeroComplejo dos métodos


estáticos:

NumeroComplejo i();
NumeroComplejo Parse(string nc);

Nota: El método Parse espera recibir un string de la forma


x ± yi
Ej: 3 - 5i, -4 + 2i, 0 + 2i, -5 - 0i
Ejercicio 3
class NumeroComplejo{

public static NumeroComplejo Parse(string nc) {


string [] partes = nc.Split(new char[]{'-', '+'});
double real = Double.Parse(partes[0]);
partes[1] = partes[1].SubString(0, partes[1].Length - 1);
double img = Double.Parse(partes[1]);
if (nc.IndexOf("+") > 0 )
return new NumeroComplejo(real, img);
else
return new NumeroComplejo(real, -img);
}

public static NumeroComplejol i() {


return new NumeroComplejo(0, 1);
}
}
Ejercicio 3 (Uso)
public static void Main(string[] args) {

NumeroComplejo nc1 = NumeroComplejo.i();

NumeroComplejo nc2 = NumeroComplejo.Parse("3 + 4i");

NumeroComplejo nc3 = NumeroComplejo.Parse("3 - 9i");

Console.ReadKey();
}

Vous aimerez peut-être aussi