[SOLUCIONADO] C# Estructuras dinámicas: Listas tipo Pila

Iniciado por Noporfavor, Junio 21, 2016, 08:38:46 AM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Junio 21, 2016, 08:38:46 AM Ultima modificación: Julio 03, 2016, 12:22:55 PM por Gabriela
Hola,

antes que nada:

Código: csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ListasTipoPila1
{
    class Pila
    {
        class Nodo
        {
            public int info;
            public Nodo sig;
        }

        private Nodo raiz;

        public Pila()
        {
            raiz = null;
        }

        public void Insertar(int x)
        {
            Nodo nuevo;
            nuevo = new Nodo();
            nuevo.info = x;
            if (raiz == null)
            {
                nuevo.sig = null;
                raiz = nuevo;
            }
            else
            {
                nuevo.sig = raiz;
                raiz = nuevo;
            }
        }

        public int Extraer()
        {
            if (raiz != null)
            {
                int informacion = raiz.info;
                raiz = raiz.sig;
                return informacion;
            }
            else
            {
                return int.MaxValue;
            }
        }

        public void Imprimir()
        {
            Nodo reco=raiz;
            Console.WriteLine("Listado de todos los elementos de la pila.");
            while (reco!=null)
            {
                Console.Write(reco.info+"-");
                reco=reco.sig;
            }
            Console.WriteLine();
        }

        static void Main(string[] args)
        {
            Pila pila1=new Pila();
            pila1.Insertar(10);
            pila1.Insertar(40);
            pila1.Insertar(3);
            pila1.Imprimir();
            Console.WriteLine("Extraemos de la pila:"+pila1.Extraer());
            pila1.Imprimir();
            Console.ReadKey();
        }
    }
}

Ahora bien, la duda seria esta:

En el metodo Insertar se encuentra este pedazo:

else
            {
                nuevo.sig = raiz;
                raiz = nuevo;
            }


Porque, si la lista esta vacia, apunta sig hacia raiz? Para que el nodo no se extienda infinitamente?

Gracias y saludos

Junio 21, 2016, 03:02:40 PM #1 Ultima modificación: Junio 21, 2016, 03:07:28 PM por grep
Estás enfocándote solo en una parte del if-else. Veamos:

Código: php

if (raiz == null)
{
  nuevo.sig = null;
  raiz = nuevo;
}
else
{
  nuevo.sig = raiz;
  raiz = nuevo;
}



1.- Cuando creas una instancia Pila, su campo raiz es null.

2.- Cuando ejecutas por primera vez Insertar(...) sobre la instancia de Pila entonces se ejecuta el primer bloque de este if-else. Aquí raiz por primera vez referencia a una instancia Nodo. Esta instancia de Nodo no tiene un nodo que le siga (su campo sig es null)

3.- Cuando vuelves ejecutar Insertar(...) sobre la instancia de Pila entonces se ejecuta el segundo bloque de este if-else. Ahora raiz referencia a una NUEVA instancia de Nodo. Esta NUEVA instancia de Nodo si tiene un nodo que le siga (el nodo al que raiz referenciaba en el paso 2).

4.- Si vuelves a ejecutar Insertar(...), vuelve a repetirse el paso 3.


La respuesta a tu primer pregunta es porque así está diseñado. El primer Nodo ingresado siempre va a referenciar a null.

Por esta razón el método Imprimir() recorre los Nodos hasta que encuentra null.

¿Para que la lista no se extienda infinitamente?: si

Junio 27, 2016, 12:23:02 PM #2 Ultima modificación: Junio 27, 2016, 09:27:31 PM por rollth
Hola grep,

ahora tengo problemas con el metodo Extraer:
public int Extraer()
        {
            if (raiz != null)
            {
                int informacion = No tienes permitido ver los links. Registrarse o Entrar a mi cuenta;
                raiz = raiz.sig;
                return informacion;
            }
            else
            {
                return int.MaxValue;
            }
        }

Lei que si la lista no está vacía guardamos en una variable local la información del primer nodo:
int informacion = No tienes permitido ver los links. Registrarse o Entrar a mi cuenta;



Pero verdaderamente se refiere a raiz? O al primer nodo con el numero 10?

Gracias y saludos

En un poco ambiguo hablar de un "primer nodo" ya que no sabemos si el que escribe hace referencia al nodo ingresado al principio o el nodo que la pila puede debe extraer primero.

Pero estamos hablando de una Pila, osea, una estructura que acumula objetos, en donde el primero que se puede extraer es el último que se ha ingresado.

Observa:

Código: csharp

pila1.Insertar(10);
pila1.Insertar(40);
pila1.Insertar(3);
...
Console.WriteLine("Extraemos de la pila:"+pila1.Extraer());


Vemos que main ejecuta tres veces "Insertar" y una sola vez "Extraer". El primer nodo en insertar tiene la información 10, mientras que el primer nodo que la pila debe devolver es el que tiene la información 3.

Pero verdaderamente se refiere a raiz? Si, en este caso raiz apunta al último nodo insertado (el que tiene el número 3).

Al primer nodo con el numero 10? No, ese es el primer nodo ingresado, pero el último nodo que puede extraerse.

No he comprendido la imagen que has subido,

Saludos

Hola grep,
ouuuuhh.... Ahora empieza de nuevo... el lio que tuve en el otro metodo lo tengo en este ahora

int informacion = No tienes permitido ver los links. Registrarse o Entrar a mi cuenta;

En informacion se guarda la informacion de raiz. Pero, como dibuje, raiz es null; no tiene informacion. No entiendo.

Perdon pero estructuras dinamicas es hasta ahora la peor parte de c#, que por ahora estoy pasando.

Gracias y saludos

Tu método "Extraer" siempre va a retornar un entero.

Código: csharp

        public int Extraer()
        {
            if (raiz != null)
            {
                int informacion = raiz.info;
                raiz = raiz.sig;
                return informacion;
            }
            else
            {
                return int.MaxValue;
            }
        }


Si raiz es null, entonces lo que "Extraer" retorna es el máximo valor que puede tener una variable int (return int.MaxValue;).

De acuerdo;

pero no entiendo que es lo que se guarda en informacion.

Podrias, si queres, explicarme esta linea?: int informacion = No tienes permitido ver los links. Registrarse o Entrar a mi cuenta;

Gracias y saludos

int informacion = No tienes permitido ver los links. Registrarse o Entrar a mi cuenta; crea una variable denominada "informacion", y copia el velor del campo "info", que se encuentra en el nodo al que referencia "raiz".

La primera vez que ejecutes el método Extraer, "informacion" va a copiar el valor 3, ya que raiz referencia al último nodo insertado, y este último nodo insertado tiene su campo info con el valor 3.

Si quieres mas o menos un dibujo, es así:



Si no comprendes esa línea, entonces estas pasando por alto conceptos fundamentales de Programación Orientada a Objetos (POO). Deberías leer un poco sobre términos como tipos (o clases), referencia y tipo valor vs tipo referencia.

Hola grep,

ahora lo entendi esa linea gracias a vos.

Te agradeceria si me explicaras tambien esta linea :) : raiz = raiz.sig;

El que lo explica escribio esto: Avanzamos raiz al segundo nodo de la lista, ya que borraremos el primero

Pero yo no entiendo eso

Gracias y saludos

Junio 28, 2016, 04:46:54 PM #9 Ultima modificación: Junio 28, 2016, 04:49:26 PM por grep
Código: csharp
raiz = raiz.sig;


El estado de Pila1 cambiará, raiz ahora referenciará al nodo con información 40:

Pasas de esto:



A esto:



Como vez el nodo que tiene la información 3, que fue el ultimo nodo que insertaste, ya no es referenciado por ninguna variable. La máquina virtual de C# se va a percatar de esto, y va a borrar toda existencia de ese nodo. Esto es basicamente la característica de recolección de basura.

Hola grep,

la variable informacion guarda el numero 3

Cuando leo esta linea: raiz = raiz.sig;

entiendo que raiz apunta al campo sig del nodo 3. Que habla en contra de que esto no es asi? Y de ser asi porque ha de ser eliminado el nodo 3?

Gracias y saludos

Junio 29, 2016, 03:20:01 PM #11 Ultima modificación: Junio 29, 2016, 03:28:48 PM por grep
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Hola grep,

la variable informacion guarda el numero 3

Cuando leo esta linea: raiz = raiz.sig;

entiendo que raiz apunta al campo sig del nodo 3. Que habla en contra de que esto no es asi? Y de ser asi porque ha de ser eliminado el nodo 3?

Gracias y saludos

En C# existen dos clasificaciones de tipos:

* Tipos valor
* Tipos referencia

Los tipos valor copian, como es la variable "informacion".

Los tipos referencia referencian, como es la variable "raiz".

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Cuando leo esta linea: raiz = raiz.sig;

entiendo que raiz apunta al campo sig del nodo 3.

No. En primer lugar la variable "raiz" referencia, no apunta. Por último, no referencia al campo "sig" del nodo 3, si no que referencia a lo que referencia el campo "sig" del nodo 3.

Parece un trabalenguas, pero no es dificil de entender. Las imágenes que he subido explican la idea.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
la variable informacion guarda el numero 3

Cuando leo esta linea: raiz = raiz.sig;

... Que habla en contra de que esto no es asi?

No habla en contra. Te explico con mis palabras lo que sucede.

Código: csharp
        public int Extraer()
        {
            if (raiz != null)
            {
                int informacion = raiz.info;
                raiz = raiz.sig;
                return informacion;
            }
            else
            {
                return int.MaxValue;
            }
        }


1.- public int Extraer() Entramos en el método Extraer
2.- if (raiz != null) "raiz" referencia a un objeto que no sea null? pues si, al nodo con info 3.
3.- int informacion = No tienes permitido ver los links. Registrarse o Entrar a mi cuenta; crear una variable de tipo int (entero, es un tipo valor) llamada "informacion" y copiar el valor del campo "info" del objeto al que referencia raiz. Como raiz referencia al Nodo 3, entonces "informacion" copia el valor 3.
4.- raiz = raiz.sig; que "raiz" referencie al objeto al que referencia el campo "sig" del objeto al que actualmente referencia raiz. Como raiz referencia al Nodo 3, y el Nodo 3 referencia al Nodo 2 en su campo "sig", entonces ahora "raiz" va a referenciar al Nodo 2.
5.- return informacion; retornar el valor que contenga "informacion". Entonces Extraer retorna el número 3.


No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Y de ser asi porque ha de ser eliminado el nodo 3?

Cuando raiz referencie al Nodo 2, que sucede en el punto (4), ningún otra variable, campo o propiedad va a referenciar a Nodo 3. Por lo tanto será borrado automáticamente.

Citar
Como raiz referencia al Nodo 3, y el Nodo 3 referencia al Nodo 2 en su campo "sig", entonces ahora "raiz"
va a referenciar al Nodo 2.

Pero mira lo que dice aqui:

if (raiz == null)
{
  nuevo.sig = null;
  raiz = nuevo;
}
else
{
  nuevo.sig = raiz;
  raiz = nuevo;
}

En esta parte:

else
{
  nuevo.sig = raiz;
  raiz = nuevo;
}

En esta parte:

nuevo.sig = raiz;

Osea que el campo sig del nodo 3 referencia a raiz y raiz por su parte referencia al nodo 3.
Como es posible, entonces, que el campo sig del nodo 3 referencia al nodo 2?

Gracias y saludos

Junio 30, 2016, 01:10:24 PM #13 Ultima modificación: Junio 30, 2016, 01:25:53 PM por grep
El problema es que no comprendes la idea de referencia.

Solo se puede referenciar a objetos, no a variables, campos o propiedades.

Piensa en estas variables, campos o propiedades como simples etiquetas.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Pero mira lo que dice aqui:

if (raiz == null)
{
  nuevo.sig = null;
  raiz = nuevo;
}
else
{
  nuevo.sig = raiz;
  raiz = nuevo;
}

En esta parte:

else
{
  nuevo.sig = raiz;
  raiz = nuevo;
}

En esta parte:

nuevo.sig = raiz;

Osea que el campo sig del nodo 3 referencia a raiz y raiz por su parte referencia al nodo 3.
Como es posible, entonces, que el campo sig del nodo 3 referencia al nodo 2?

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
... Osea que el campo sig del nodo 3 referencia a raiz ...

NO. El campo "sig" del Nodo 3 referencia a lo que referencia "raiz", osea al Nodo 2.

"sig" es un campo de un objeto tipo Nodo, y "raiz" es un campo de un objeto tipo Pila.

Por eso, como dije al principio, con esa linea de código NO estas referenciando a "raiz", ya que raiz es simplemente una etiqueta, no un objeto.

Si te fijas en las imágenes que he puesto, "raiz" es solo una etiqueta con una flecha. "sig" sería otra etiqueta con una flecha, no puedes tener una flecha de referencia de etiqueta a etiqueta, solo de etiqueta a un objeto (rectángulo blanco).

Por favor, lee atentamente la primera respuesta que de este hilo. Fíjate el punto (3).

Hola grep,
al fin entiendo el codigo; para hay que admitir que era un codigo muy complicado. Para gracias a que lo entendi pude entender tambien este codigo:

Código: php

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ListasTipoPila1
{
    class Pila
    {
        class Nodo
        {
            public int info;
            public Nodo sig;
        }

        private Nodo raiz;

        public Pila()
        {
            raiz = null;
        }

        public void Insertar(int x)
        {
            Nodo nuevo;
            nuevo = new Nodo();
            nuevo.info = x;
            if (raiz == null)
            {
                nuevo.sig = null;
                raiz = nuevo;
            }
            else
            {
                nuevo.sig = raiz;
                raiz = nuevo;
            }
        }

        public int Extraer()
        {
            if (raiz != null)
            {
                int informacion = raiz.info;
                raiz = raiz.sig;
                return informacion;
            }
            else
            {
                return int.MaxValue;
            }
        }

        public void Imprimir()
        {
            Nodo reco=raiz;
            Console.WriteLine("Listado de todos los elementos de la pila.");
            while (reco!=null)
            {
                Console.Write(reco.info+"-");
                reco=reco.sig;
            }
            Console.WriteLine();
        }

        public bool Vacia()
        {
            if (raiz == null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public int Cantidad()
        {
            int cant = 0;
            Nodo reco = raiz;
            while (reco != null)
            {
                cant++;
                reco = reco.sig;
            }
            return cant;
        }

        static void Main(string[] args)
        {
            Pila pila1=new Pila();
            pila1.Insertar(10);
            pila1.Insertar(40);
            pila1.Insertar(3);
            pila1.Imprimir();
            Console.WriteLine("La cantidad de nodos de la lista es:"+pila1.Cantidad());
            while (pila1.Vacia()==false)
            {
                Console.WriteLine(pila1.Extraer());
            }
            Console.ReadKey();
        }
    }
}


Pero tendria una duda aqui. Solo una duda:

public bool Vacia()
        {
            if (raiz == null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

Para que hace falta bool aqui? Tambien se puede escribir este metodo sin bool. O no?

Gracias y saludos

Junio 30, 2016, 02:28:15 PM #15 Ultima modificación: Junio 30, 2016, 02:36:12 PM por grep
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
        public bool Vacia()
        {
            if (raiz == null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

Para que hace falta bool aqui? Tambien se puede escribir este metodo sin bool. O no?

Forma parte del protitipo del método. Si dice bool, entonces en alguna parte dentro del método debe existir un return <algún valor booleano>;

Si observas un return <algún valor booleano>; entonces el método debe tener bool (o object, pero esto es un concepto muy vago) en su prototipo.

Viendo eso, sabes lo que un método debe retornar.

Si un método es void, entonces no retorna nada.

Hola grep,
muchisimas gracias por tu gran ayuda;

Este tema esta solucionado. Te debo una.

Gracias y saludos