Introducción a las estructuras de datos
Estructuras de Datos en JavaScript para Desarrolladores
Estructuras de Datos: Conceptos Básicos y Aplicaciones Prácticas
Almacenamiento de Datos en Memoria con JavaScript
Arrays y strings
Construcción de Arrays con Clases en JavaScript
Construcción de Arrays con Clases en JavaScript
Eliminar elementos de un array en JavaScript: método POP y DELETE
Playground: crea tu propia implementación de unshift
Playground: crea tu propia implementación de shift
Inmutabilidad de Strings y Almacenamiento en Memoria
Hash Table
Conceptos y Construcción de Hash Tables en JavaScript
Implementación de Hash Table en JavaScript: Método Set
Implementación del método get en hash table JavaScript
Playground: implementa el metodo Delete
Playground: implementa el método getAllKeys
Linked List
Estructuras de Datos: Listas Enlazadas en JavaScript
Estructura y Creación de una Lista Enlazada Simple en JavaScript
Métodos para Manipular Nodos en Listas Enlazadas
Inserción de nodos en listas enlazadas en JavaScript
Implementación de Listas Doblemente Enlazadas en Programación
Stacks
Stacks: Concepto y Operaciones Básicas en JavaScript
Implementación de Stacks en JavaScript: Métodos Push y Peek
Queues
Colas: Estructura de Datos y Operaciones Básicas
Implementación de Colas (Queues) en JavaScript
Trees
Estructuras de Datos: Árboles Binarios y Búsqueda en JavaScript
Construcción y validación de un Árbol de Búsqueda Binaria en JavaScript
Graphs
Conceptos básicos de grafos: tipos y aplicaciones prácticas
Representación de Grafos en JavaScript: Listas y Matrices
Construcción de Grafos: Método Lista de Adyacencia en JavaScript
Cierre
Estructuras de Datos con JavaScript: Práctica y Aplicación
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Las listas enlazadas son estructuras de datos esenciales en el ámbito de la programación. Si alguna vez te has preguntado cómo se añaden nodos al principio o al final de una lista enlazada, estás en el lugar correcto. Aquí desglosaremos los métodos para llevar a cabo estas operaciones: append
para agregar nodos al final y prepend
para insertarlos al principio.
append
y cómo funciona?El método append
es una funcionalidad comúnmente usada en estructuras de datos dinámicas como arrays y strings, y su propósito es simple: agregar un elemento al final de la estructura. En el contexto de una lista enlazada, append
se encarga de añadir un nodo al final, convirtiéndose en la nueva cola (tail) de la lista.
append
:next
del último nodo el nuevo nodo.# Crear un nuevo nodo
nuevo_nodo = NodoConValor(valor)
# Vincular nuevo nodo al final de la lista
tail.next = nuevo_nodo
# Actualizar la referencia de tail
self.tail = nuevo_nodo
# Incrementar la longitud de la lista
self.longitud += 1
prepend
?Por otro lado, el método prepend
nos permite insertar un nodo al inicio de la lista, lo que convierte dicho nodo en la nueva cabeza (head).
prepend
:append
, generamos un nodo nuevo con el valor deseado.next
del nuevo nodo el actual nodo cabeza.append
, incrementamos el tamaño de la lista.# Crear un nuevo nodo
nuevo_nodo = NodoConValor(valor)
# Vincular a la nueva cabeza
nuevo_nodo.next = self.head
# Actualizar la referencia de head
self.head = nuevo_nodo
# Incrementar la longitud de la lista
self.longitud += 1
Enfrentar la lógica de listas enlazadas puede ser un reto al principio, pero aquí van algunos consejos para entenderlo mejor:
Adentrarse en el mundo de las estructuras de datos es una habilidad invaluable para cualquier programador. Al aplicar estos métodos, no solo estarás comprendiendo un concepto fundamental, sino que también estarás preparando el terreno para operaciones más complejas, como insertar nodos en posiciones específicas dentro de la lista. ¡Continúa aprendiendo!
Aportes 91
Preguntas 4
Algo que me ayudo bastante a la hora de entender esta clase fue que estamos jugando bastante con la referencia de JavaScript. Recuerda mantener la idea de que no estamos guardando los valores de los objetos en sí, si no el lugar [referencia] de donde se encuentran en el memory heap.
El memory Heap es donde se guardan todos los objetos, debido a que los objetos necesitan una mayor cantidad de memoria a diferencia que los números, cadenas o boleanos, la desventaja es que el memory heap es lento por lo cual se necesita dar una ubicación de donde se está guardado. Si deseas saber más acerca de este tema puedes revisar este video creado por el profesor del curso de fundamentos de javascript
😉 Mi explicación del código según a lo que entendí
class MySinglyLinkedList {
constructor(value) {
// creamos el inicio de nuestro SinglyLinkedList
this.head = {
value,
next: null,
};
// Aqui sucede la magia ✨
// Todo lo que modifiquemos en los atributos de tail
// se modificará en la estructura inicial
// por la RERENCIA!
this.tail = this.head;
this.length = 1;
}
append(value) {
// aquí estamos creando un nuevo nodo
const newNode = new Node(value);
// Como mencionamos anteriormente
// si modificamos la cola por la REFERENCIA
// se modificará la estructura inicial! 🖊
this.tail.next = newNode;
// Pero aun tail sigue apuntando a la CABEZA
// de la estructura inicial entonces es momento
// de apuntar al nuevo nodo creado para que posteriormente
// podamos agregar más nodos! 🚀
this.tail = newNode;
// Finalmente aumentamos el tamaño definido de
// nuestra estructura 👨🔧
this.length++;
return this;
}
💚 Cualquier correción o comentario es bienvenido!
Creo que para esta clase es importante entender también que cuando generamos un objeto en JS y luego igualamos otra variable a la variable anterior lo que hacemos es que apuntamos desde las dos variables al mismo espacio en memoria, por eso cuando decimos:
this.head = new Node(value)
this.tail = this.head
Cada vez que hagamos un cambio en this.tail ese cambio también va a afectar a this.head, por eso en el método append, cuando le decimos:
this.tail.next = newNode
A su vez también cambiamos el valor this.head.next, luego hacemos que this.tail apunte al espacio en memoria de newNode diciéndole:
this.tail = newNode
La próxima vez que cambiemos this.tail ya no va a afectar a this.head.
Gracias a esto es que podemos aplicar los métodos append y prepend de esta manera, esto lo podemos probar haciendo en el constructor de SinglyLinkedList lo siguiente:
this.head = {
value: value,
next: null
}
this.tail = {...this.head}
De esa manera this.tail ya no estará apuntando al espacio en memoria que ocupa this.head sino que pasará a ocupar uno nuevo, y los cambios que se hagan en this.tail no afectaran a this.head por ende el método de append la primera vez que se llama no hará que mute this.head. Esto es un problema porque no es el comportamiento que queremos, pero es importante que entendamos que no siempre la mutabilidad en JS es mala (aunque la querramos evitar en la mayoría de los casos) y qué podemos sacarle provecho sabiéndola utilizar. La otra opción es evitar que los objetos muten y tener control sobre lo que ocurre tanto en this.tail como en this.head.
Un poco de ayuda grafica, saludos 😃
Al inicio:
Intermedio :
Es simple, de hecho me recuerda mucho a los callbacks hell jajaja, simplemente se trata de crear un nuevo nodo y meterlo dentro del next
del nodo que está actualmente como la cola.
.
Y para la cabeza, lo único que hicimos fue, agarrar la cabeza actual, que ya contenía toda nuestra lista de nodos hijos, y meterla en una nueva cabeza, de esa forma pudimos hacer un prepend ^^
La logica es parecida al callback hell, es ir anidando punteros a direcciones en memoria de cada uno de los nuevos nodos, esto a final queda una estractura de cuando anidamos callbacks.
.
Para practicar la logica de programacion y que se les sea mas facil implementar en el codigo lo que se nos pide, yo les recomiendo hacer algo de pseudo codigo.
En lo personal yo hago un dibujo y escribo lo que deberia de hacer paso a paso. Esa es la manera en que practico mi logica. Te la recomiendo quizás a ti tambein te sirva como me sirve a mi
Reto insert:
TIP: Para comentar todas las líneas juntas:
simplemente aprietan Ctrl + K + C.
TIP: Para quitar el comment a todas las líneas juntas:
simplemente aprietan Ctrl + K + U.
Saludos!!
// 1 --> 2 --> 3 --> 4 --> 5 --> null
// let singlyLinkedLis = {
// head: {
// value: 1,
// next: {
// value: 2,
// next: {
// value: 3,
// next: {
// value: 4,
// next: null
// }
// }
// }
// }
// }
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class MySinglyLinkedList {
constructor(value) {
this.head = {
value,
next: null
}
this.tail = this.head;
this.length = 1;
}
append(value) {
const newNode = new Node(value);
this.tail.next = newNode;
this.tail = newNode;
this.length++;
return this;
}
prepend(value) {
const newNode = new Node(value);
newNode.next = this.head;
this.head = newNode;
this.length++;
return this;
}
}
let myLikedList = new MySinglyLinkedList(1);
console.log(myLikedList);
console.log(myLikedList.append(2));
console.log(myLikedList.prepend(0));
buen dia, cuando se agrega un nuevo nodo en la lista con el metodo insert con un solo parametro, se genera un undefine como lo de la imagen.
insert(index, value) {
//add a node "outside" the list (=> invalid)
if(index < 0 || index > this.length) {
return null;
} else if(index === 0) {
//add a node to the beginning of the list
return this.prepend(value);
} else if(index === this.length) { //>=
//add a node to the end of the list
return this.append(value)
} else {
const newNode = new Node(value);
const firstPointer = this.getTheIndex(index - 1);
const holdingPointer = firstPointer.next;
firstPointer.next = newNode;
newNode.next = holdingPointer;
this.length++;
return this;
}
}
getTheIndex(index) {
let counter = 0;
let currentNode = this.head;
while(counter !== index) {
currentNode = currentNode.next;
counter++;
}
return currentNode;
}
De verdad le aplaudo a este profesor. De lo mejor que hay en platzi. Joya!
No dejen ir al gran Diego De Granda
Callback Hell puro.
Después de entender la solución de append (me tomó tiempo. Mucho. Tiempo.), conseguí generar el prepend por mi cuenta 🥲
Append y Prepend
Considerando el caso en que la LinkedList
esté vacía.
append(value) {
const newNode = new Node(value);
if (!this.head) {
this.head = newNode;
this.tail = newNode;
this.length++;
return this;
}
this.tail.next = newNode;
this.tail = newNode;
this.length++;
return this;
}
prepend(value) {
const newNode = new Node(value);
if (!this.head) {
this.head = newNode;
this.tail = newNode;
this.length++;
return this;
}
newNode.next = this.head;
this.head = newNode;
this.length++;
return this;
}
insert($_item, $_position) {
const node = new ENode($_item);
let pointer = this.head;
if($_position > this.length){
throw new Error("List index out of bounds")
}
if($_position == 0){
this.addFirst($_item); // prepend
return;
}
while ($_position > 1) {
pointer = pointer.next;
$_position--;
}
node.next = pointer.next
pointer.next = node;
this.length++
}
en esta clase no entiendo por completo y es que no se para que puede servir esta estructura algun ejemplo por que solo veo en consola
class MySinglyLinkedList {
constructor(value) {
this.head = {
value: value,
next: null
}
this.tail = this.head;
this.length = 1;
};
prepend(value) {
const newNode = new Node(value);
newNode.next = this.head;
this.head = newNode;
this.length++;
return this;
};
};
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class MySinglyLinkedList {
constructor(value) {
this.head = {
value: value,
next: null,
}
this.tail = this.head;
this.length = 1;
}
append(value) {
const newNode = new Node(value);
this.tail.next = newNode;
this.tail = newNode;
this.length++;
return this;
}
prepend(value) {
const newNode = new Node(value);
newNode.next = this.head;
this.head = newNode;
this.length++;
return this;
}
}
let myLinkedList = new MySinglyLinkedList(1);
aqui con micho esfuerzo hice un metodo para agregar un nodo en cualquier posicion indicada
add (index,value) {
const newNode = new Node(value);
let actualNode = this.head
let previusNode = this.head
for (let i = 1; i < index; i++) {
if (i == index - 1) {
previusNode = actualNode
}
if (actualNode.next) {
actualNode = actualNode.next
} else {
return
}
}
newNode.next = actualNode
previusNode.next = newNode
this.length++
return this;
}
Me recordó a la clase de punteros en C, en el 2009. No solo variables sino espacios de memoria.
🤯🤯
La clase es muy clara pero considero que el profesor debió haber echo un pequeño recordatorio de que el tail apunta a la referencia del último valor del linkedList, esta es la razón por que al reasignar el next del tail se modifica el valor en el linkedList.
Sin esto claro, el código funciona bien pero no queda claro porque y creo que puede confundir bastante, pero el tema de la clase es super claro y se entiende perfecto.
Para cualquiera que tenga esta duda y quiera entender en detalle como funcionan los valores por referencia les dejo este articulo que deja super claro el tema.
https://www.javascripttutorial.net/javascript-primitive-vs-reference-values/
addNode(value){
let node = new Node(value);
this.tail.next=node;
this.tail = node;
}
Creo que aqui se debio hacer mas mencion a la diferencia entre pasar valores por Referencia y Valor, ya que es la base para entender los metodos de Append y prepend
Cuando usamos palabras reservadas o metodos, entiendo que todo nace del súper prototipo, pero como es que esta construido el super prototipo. Estamos construyendo estas estructuras gracias a la capa de abstracción anterior pero tarde o temprano llegamos al super prototype, ¿Como esta construido el super prototype?
Para agregar en cualquier lado:
insert(value,pos){
if(pos == 0){
this.prepend(value);
}else if(pos >= this.length - 1){
this.append(value);
}else{
const node = new Node(value);
const datatoInsert = this.explore(this.head,pos);
node.next = datatoInsert.next;
datatoInsert.next = node;
this.length++;
}
}
explore(nodeActual,limit){
if(limit == 0){
return nodeActual;
}else{
return this.explore(nodeActual.next,limit - 1);
}
}
El prepend:
prepend(value){
const node = new Node(value);
node.next = this.head;
this.head = node;
this.length++;
}
Hice este metodo para imprimir los datos en formato de linked list. Una ayuda para entender mejor.
print() {
let result = "";
let currentNode = this.head;
while (currentNode) {
if (!currentNode.next) {
result += ` ${currentNode.data}`;
} else {
result += ` ${currentNode.data} -->`;
}
currentNode = currentNode.next;
}
return result;
}
Yo hice el Prepend un poco diferente pero funciona igual:
prepend(value) {
const body = this.head;
const newNode = new Nodo(value);
this.head = newNode;
this.head.next = body;
this.length++;
return this;
}
mi ejercicio esta en python pero creo que para las personas que esten haciendo este curso por la forma que crea las estructuras de datos le servira o vera otra manera de realizarlo.
<
class Node:
def __init__(self,data) -> None:
self.data = data
self.next = None
class LinkendList:
def __init__(self) -> None:
self.head = None
self.tail = self.head
self.size = 0
def insert(self,data):
"""insert method
This method allow us add a new item at the end of the LinkedList.
Args:
data (_type_): value that will be take the next node to add.
"""
new_item = Node(data)
if not self.head:
self.head = new_item
self.tail = self.head
elif self.size == 1:
self.tail = new_item
self.head.next = self.tail
else:
current = self.tail
current.next = new_item
self.tail = current.next
new_linkedList = LinkendList()
new_linkedList.insert(23)
new_linkedList.insert(40)
new_linkedList.insert(20)
current = new_linkedList.head
while current :
print(current.data,end=' -> ')
current = current.next>
class MyNode {
value: String|Number|Array<any>
next: any
constructor(value: String|Number|Array<any>) {
this.value = value
this.next = null
}
}
// Singly linked list
class MyLinkList {
public head: MyNode
public tail: MyNode
public length: number
constructor(value: String|Number|Array<any>) {
this.head = new MyNode(value)
this.tail = this.head
this.length = 1;
}
append(value: String|Number|Array<any>) {
const newNode = new MyNode(value)
this.tail.next = newNode
this.tail = newNode
this.length++
return this
}
preppend(value: String|Number|Array<any>) {
const newNode = new MyNode(value)
newNode.next = this.head
this.head = newNode
this.length++
return this
}
}
Aproveche el curso para escribir mis primeras líneas de TypeScript lo cual recomiendo, lo hace ligeramente más retador mientras aprendes algo extra. URL TypeScript playground y la documentación de TypeScript
Es excelente, es la misma logica que se usa para el patron de una cadena de responzabilidad. https://refactoring.guru/es/design-patterns/chain-of-responsibility
Así lo hice yo
newNode(value){
this.tail.next = new Node(value);
this.tail = this.tail.next;
this.length++;
}
Mi solucion a los retos con la implementacion de un metodo que imprime a la singly linked list como si fuera un array normal
class Node {
constructor(value, next = null) {
this.value = value;
this.next = next;
}
}
class SinglyLinkedList {
constructor(value) {
this.head = new Node(value);
this.tail = this.head;
this.length = 1;
}
append(value) {
const newNode = new Node(value);
this.tail.next = newNode;
this.tail = newNode;
this.length++;
}
prepend(value) {
this.head = new Node(value, this.head);
this.length++;
}
print() {
let current = this.head;
let linkedList = [];
while (current != null) {
linkedList.push(current.value);
current = current.next;
}
console.log(linkedList);
}
}
Cree el método a través de una función recursiva
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class SinglyLinkedList {
constructor(value) {
this.head = { value, next: null };
this.tail = new Node(value);
this.length = 1;
}
_assignNext(instance, newNode) {
if (instance.next === null) {
instance.next = newNode;
return;
}
this._assignNext(instance.next, newNode);
}
append(value) {
this._assignNext(this.head, new Node(value));
this.length++;
}
}
const pageNavigator = new SinglyLinkedList("htps://platzi.com");
console.log(pageNavigator.length, pageNavigator.head);
pageNavigator.append("htps://digital.dev.greatminds.dev/");
console.log(pageNavigator.length, pageNavigator.head);
pageNavigator.append("htp://localhost:3000/");
console.log(pageNavigator.length, pageNavigator.head);
Este es mi aporte a la comunidad
<code>
function Nodo(value){
this.value = value,
this.next = null
}
class SingleLinkedList {
constructor(value) {
this.head = {
value : value,
next : null
}
this.tail = this.head
this.length = 1
}
****}
Me acuerdo cuando en la Universidad alcance a ver este tema pero con Java, la verdad esto de las listas es muy divertido, llámenme loco jajajajja
Mi solución al insertar implementado en TypeScript:
insert(value: T, position: number): void {
if (position >= this._length) return this.append(value);
if (position <= 0) return this.prepend(value);
const node = new Node(value);
let current = this.head;
let previous = this.head;
for (let i = 0; i < position; i++) {
previous = current;
current = current!.next;
}
previous!.next = node;
node.next = current;
this._length++;
}
Esta es la alternativa usando recursividad (es menos óptima que la del profe porque él usa el tail como acceso directo y no tiene que recorrer la estructura completa) pero la recursividad es algo que se pide mucho en pruebas técnicas para Amazon, google, etc así que nunca está de mas practicarla
append(value,current){
//console.log(!current)
if(!current){
current=this.head
}
if(current.next==null){
let nodo=new Nodo(value)
current.next=nodo
this.tail=nodo
}else{
this.append(value,current.next)
}
}
Les comparto mi solución a la implementación del método insert(value, position). Criterios de aceptación que definí para una lista de N nodos:
insert(value, position) {
if(position > 0 && position <= this.length +1) {
if(position == 1) {
this.prepend(value);
return this;
}
if(position == this.length +1) {
this.append(value);
return this;
}
let newNode = new MyNode(value);
let nextNode = this.head;
for(let i = 1; i < position -1; i++) {
nextNode = nextNode.next;
}
let tempNode = nextNode.next;
nextNode.next = newNode;
newNode.next = tempNode;
this.length++;
return this;
}
return undefined;
}
<code>
public getNode(indexValue : number) : Node | null{
let currentNode : Node | null = this.head.next
if (currentNode){
while(currentNode.value !== indexValue){
let nextNode : Node | null = currentNode.next
if (nextNode){
currentNode = nextNode
}else{
return null
}
}
}else{
return null
}
return currentNode
}
public insertNodeAfter(previousNodeValue : number, value : number) : void{
let newNode : Node = new Node(value)
let previousNode : Node | null = this.getNode(previousNodeValue)
if (previousNode){
let nodeToReplace : Node | null = previousNode.next
previousNode.next = newNode
newNode.next = nodeToReplace
this.length = this.length + 1
}
}
<code>
esto me funciona
My code of append function
append(value){
if (this.length = 1) {
this.head.next = new Node(value);
this.tail = this.head.next;
this.length++;
} else if (this.length > 1) {
let current = this.head;
while ( current.next ) {
current = current.next;
}
current.next = new Node(value)
this.tail = current.next;
this.length++;
}
Despues de un buen rato consegui resolver el reto
Ojo: Este codigo va dentro de la clase de mySingleLinkedList
insert(value)
{
if(this.length > 1)
{
const div = Math.round(this.length/2)
const newNode = new Node(value)
this.view(this.head,div,newNode)
return this
}
this.append(value)
}
// No sabia que nombre ponerle a esta funcion y como la inicie view por esa era su funcion antes
view(node, veces, newNode)
{
veces--
if(veces === 0)
{
newNode.next = node.next
node.next = newNode
this.length++
this.view2(this.head,1)
return this
}
}
Así lo hice yo, ahora a ver como se hace
insert(value, pos){
const newNode = new Node(value);
let tail;
let nodes = [this.head];
if(pos >= 0 && pos <= this.length - 1){
for(let i = 0; i <= pos; i++){
if(nodes[nodes.length - 1].next){
if(i == pos - 1){
tail = nodes[nodes.length - 1].next;
nodes[nodes.length - 1].next = newNode;
}
nodes.push(nodes[nodes.length - 1].next);
}else{
nodes[nodes.length - 1].next = tail;
this.length++;
return this.head;
}
}
}else{
if(pos <= this.length){
this.prepend(newNode);
}else{
this.append(newNode);
}
}
}
Así implemente yo los metodos append y prepend:
class Node {
constructor(value){
this.value = value;
this.next = null
}
}
class MySinglyLinkedList {
constructor(value) {
this.head = {
value: value,
next: null
}
this.tail = this.head;
this.length = 1;
}
append(value){
let newNode = new Node(value)
let lastNode = this.head;
for(let i = 1; i < this.length; i++){
lastNode = lastNode.next;
}
lastNode.next = newNode;
this.length++;
this.tail = newNode;
return this;
}
prepend(value) {
let newNode = new Node(value);
newNode.next = this.head
this.head = newNode;
this.length++;
return this;
}
}
Este fue el reto de la anterior clase así fue que lo hice
class Node {
constructor(value) {
this.value = value
this.next = null
}
};
class mySinglyLinkedList {
constructor(value) {
this.head = {
value: value,
next: null
}
this.tail = this.head;
this.length = 1;
}
push(value) {
this.tail.next = new Node(value);
this.tail = this.tail.next
this.length++
return this.head;
}
};
const myLinkedList = new mySinglyLinkedList(1);
myLinkedList.push(2);
myLinkedList.push(5);
myLinkedList.push(4);
myLinkedList.push(5);
myLinkedList.push(3);
myLinkedList.push(8);
myLinkedList.length;
Mi solución para agregar un elemento en un índice cualquiera:
insert( index, value ) {
if( index < 0 ) return;
if( index >= this.length-1 )return this.append(value);
if (index === 0) return this.prepend(value);
const newNode = new Node( value );
let nodeAt = this.head;
for ( let i = 1 ; i <= this.length ; i++) {
if(i === index){
newNode.next = nodeAt.next;
nodeAt.next = newNode;
this.length++
return this;
}else{
nodeAt = nodeAt.next
}
}
return this
}
Git hub copilot lo hizo por mi, anyway era la lógica que tenia en mente desarrollar 😄
constructor(value) {
this.head = new Node(value);
this.tail = this.head;
this.length = 1;
}
append(value) {
const newNode = new Node(value);
this.tail.next = newNode;
this.tail = newNode;
this.length++;
}
Método append (position es diferente a index, dado que comienza desde 1):
insert (value, position) {
const newNode = new Node(value);
let prevNode;
let node = this.head;
let nextNode;
for (let i = 1; i < position; i++) {
if (i == position - 1) {
prevNode = node;
nextNode = node.next;
}
node = node.next;
}
prevNode.next = newNode;
newNode.next = nextNode;
this.lenght++;
return this;
}
Mi solución al reto 😄:
class node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class singleLinkedList {
constructor(value) {
this.head = {
value : value,
next : null
}
this.tail = this.head;
this.length = 1;
}
append(newValue) {
this.tail.next = new node(newValue);
this.tail = this.tail.next;
this.length+=1;
}
}
let myLinkedList = new singleLinkedList(10);
Aquí les comparto mi metodo insert
insert(value, numInsertNode) {
const node = new Node(value);
let nodeSelected = this.head;
if(numInsertNode > this.length) {
numInsertNode = this.length;
}
for(let i = 0; i < this.length; i++) {
if(i === numInsertNode){
node.next = nodeSelected;
}
nodeSelected = nodeSelected.next;
}
let insertNode = this.head;
for(let i = 0; i <= numInsertNode; i++) {
if(i === numInsertNode -1){
insertNode.next = node;
break;
}
insertNode = insertNode.next;
}
if(this.length === numInsertNode){
this.tail = node;
}
this.length++;
return this;
}
class Node {
constructor(value){
this.value = value;
this.next = null;
}
}
class MySinglyLinKedList {
//Se genera con un valor
constructor(value){
this.head = {
value: value,
next: null,
}
this.tail = this.head;
this.length = 1;
}
checknode(node){
if (!node.next){
return node;
}
return this.checknode(node.next);
}
//Problema es que solo actualiza ese primer next
//Tenemos que crear otro next
append(value){
//Recibir el valor del nodo
let current = new Node(value);
//Creamos que vaya al siguiente next creado
const lastNode = this.checknode(this.head);
lastNode.next = current
//Cambiamos el valor next del head
this.tail = current;
this.length++;
return this.head;
}
}
let myLinkedList = new MySinglyLinKedList(1);
console.log(myLinkedList.append(2))
console.log(myLinkedList.append(3))
Mi método append()
append(value){
const newNode = new Node(value);
this.tail.next = newNode;
this.tail = newNode;
this.length++;
}
Convierte tu LinkedList a un array
toArray() {
const arr = [];
let n = this.head;
do {
arr.push(n.value);
n = n.next;
} while (n);
return arr;
}
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class LinkedL {
constructor(value) {
this.head = {
value,
next: null,
};
this.tail = this.head;
this.len = 1;
}
append(val) {
const n = new Node(val);
this.tail.next = n;
this.tail = n;
this.len++;
}
}
const l = new LinkedL(1);
for (let i = 0; i < 14; i++) {
l.append(i);
}
console.log(l);
Les comparto el método toString
para que puedan imprimir los valores de la SingleLinkedList
de manera más visual:
toString() {
let current = this.head
let linkedList = `${[current.value]} -> `
while(current.next) {
current = current.next
linkedList += `${[current.value]} -> `
}
linkedList += 'null'
return linkedList
}
metodo append con explicacion
append(value){
this.length++
// se crea un nodo, unico e irrepetible. solo referenciable.
const node = new Node(value)
/* la primera vez:
this.tail.next apunta a this.head.next por lo que los dos apuntan hacia node
entonces:
this.head ==
this.tail ==
{value: 1, next: node} ==
{value: 1, next: {value: 2, next: null}}
vv
en la siguente linea this.tail ahora apunta unicamenxd7 te al node al que se asigno a head.
entonces:
this.tail !== this.tail
this.tail == node
this.head == {value: 1, next: node}
this.head == {value: 1, next: this.tail}
por lo que tail termina apuntando a la ultima posicion de head, y en las siguientes veces que sea convocada la funcion los cambios de tail seran reflejados la ultima posicion de head
*/
this.tail.next = node
this.tail = node
// while(curr.next !== null) curr = curr.next
// curr.next = node
}
append(value){
this.length++
let curr = this.head
const node = new Node(value)
while(curr.next !== null) curr = curr.next
curr.next = node
}
Creo que así no era JAJAJAJAJAJ.
//Asi es como yo hize el mecanismo para agregar un nuevo nodo, sin embargo creo que el del profesor va a estar mejor haha.
append(value){
const linkNode = new NodeLink(value);
this.recorrer(this.head, linkNode); // Este metodo nos va a servir para recorrer el objeto en todas sus profundidades
}
recorrer(obj, node) { // Recibe dos parametros, el objeto que queremos que recorra y el nodo que queremos que agregue
for (let properties in obj) { // properties representa cada uno de los index/keys que tiene el objeto
if (this.isObject(obj[properties])) { // Verifica si el value de la key que esta recorriendo es un objeto por el metodo isObject() definida abajo
this.recorrer(obj[properties], node); // Si alguno de los values del objeto es otro objeto se va a llamar a ella misma, usando recursividad
} else if (obj[properties] === null ) { // Si no, entonces miremos si esos values tiene null, que es el value del next
obj[properties] = node; // Si lo encuentra entonces vas a asignar a ese value el nodo que le pasamos como parametro
this.tail = node; // Lo va a volver la cola de la linked list
this.length++; // Vamos a aumentar el registro
return this.head; // Y vamos a retornar this.head
}
}
}
isObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]'; // Nos metemos en el prototype de toString() para añadirle un this que sea el objeto que queremos verificar si es un objeto, si ese string sale a dicha representacion, devuelve true
}
Inicia explicación
Yo lo hice un poco diferente, dejo el metodo prepend y el codigo completo explicado como tambien el resultado
// Metodo para agregar un nodo al inicio.
// Este metodo recibira el valor que tendra el nodo.
preppend(value) {
// Creamos nuestro nuevo nodo, este recibira el valor que contendra y el valor de next,
// Que en este caso sera this.head, esto quiere decir que el valor que este en este momento en el head de nuestra linkedList
// Sera el siguiente del nuevo nodo
const newNode = new Node(value, this.head);
//Validamos si existe un nodo en el head, es decir, si nuestra LinkedList No esta Vacia
if (!this.head) {
// Si no existe un valor en el head quiere decir que nuestra linkedList esta vacia
// Entonces el nodo que estamos agregando es el primer nodo por lo cual sera el head y el tail a la vez
this.tail = newNode;
}
// Si no se cumple la validacion anterior quiere decir que nuestra linkedList tiene elementos.
// Entonces al head tenemos que apuntarlo al nuevo nodo
this.head = newNode;
// Por ultimo Incrementamos en 1 la longitud de la LinkedList
this.length++
}
código final
// creación del Nodo, que recibe como parametro las propiedades que tendra dicho nodo
class Node {
// Como sabemos en una SinglyLinkedList los nodos solo tendran dos valores
constructor(value,next) {
this.value = value; //value, que sera el dato que contendra el nodo
this.next = next; // next, que hará referencia al siguiente nodo
}
}
// Creacion de la clase SinglyLinkedList que contendra toda la logica de nuestra LinkedList
class SinglyLinkedList {
// Esta clase tendra como propiedades el head y el tail el cual estaran inicializados en null
// esto quiere decir que empezaremos con una LinkedList Vacia y por ende su longitud sera 0
constructor(){
this.head = null;
this.tail = null;
this.length = 0;
}
// implementacion del metodo append, este agregara un nodo al final de la LinkedList
// y recibira como parametro el valor que contendra el nodo que se insertara
append(value) {
const newNode = new Node(value, null);
// hacemos una validacion si existe algun nodo al final de la LinkedList.
if(this.tail) {
// Si existe un nodo al final, entonces decimos que su next sera el nuevo nodo que creamos
this.tail.next = newNode;
} else {
// Si no existe quiere decir que nuestra LinkedList esta vacia.
// Esto quiere decir que el Nodo que esta agregando es el primero
// Como es el primero entonces ese nodo sera el head y el tail a la vez.
// por lo cual al head le asignamos el nuevo nodo
this.head = newNode;
}
// Colocamos al nodo creado como el tail
this.tail = newNode;
// Incrementamos en 1 la longitud de nuestra lista
this.length ++;
}
// Metodo para agregar un nodo al inicio.
// Este metodo recibira el valor que tendra el nodo.
preppend(value) {
const newNode = new Node(value, this.head);
if (!this.head) {
this.tail = newNode;
}
this.head = newNode;
this.length++
}
}
Solución
Algo así quedó:
class MySinglyLinkedList {
constructor(value) {
this.head = {
value: value,
next: null
};
this.tail = this.head;
this.length = 1;
}
append(value) {
let currentNode = this.head;
let newNode = new Node(value);
this.head = newNode;
this.head.next = currentNode;
if (currentNode.next == null) {
this.tail = currentNode;
}
this.length++;
}
}
I implemented the append method with a recursive method so I didn’t have to use the tail prop. The list and trees can be handled with recursion.
append(value){
let newNode = this.searchTail(this.head, value);
this.tail = newNode;
this.length++;
}
searchTail(node, value){
if(!node.next){
const newNode = new Node(value);
node.next = newNode;
return newNode;
}else{
return this.searchTail(node.next, value)
}
}
Reto terminado
insert(index,value){
const newNode = new Node(value);
let target = this.head;
let slice = undefined;
for (let i = 1; i < index; i++) {
target = target.next;
}
slice = target.next;
target.next = newNode;
target.next.next = slice;
return console.log(this.head);
}
asi fue mi solución:
append(value){
const newNode = new Node(value);
this.recursiveMethod(this.head,newNode)
this.length ++;
return this.head;
}
recursiveMethod(obj, newNode){
if(obj.next === null){
return obj.next = newNode;
}
for(let prop in obj){
if(prop === 'next')
{
this.recursiveMethod(obj[prop],newNode);
}
}
}
class myNode {
constructor(value) {
this.data = value;
this.next = null;
}
}
class MySinglyLinkedList {
constructor() {
this.head = null;
this.tail = this.head;
this.length = 0;
}
append(value) {
const newNode = new myNode(value);
if (this.head === null) {
this.head = newNode;
} else {
this.next = newNode;
}
this.tail = newNode;
this.length++;
return this;
}
}
let mySinglyLinkedList = new MySinglyLinkedList();
antes de seguir con el curso aca dejo mis metodos para comparar despues
append(value) {
this.tail.next = new Node(value)
this.tail = this.tail.next
this.length++
return this.tail
}
prepend(value) {
let newHead = new Node(value)
newHead.next = this.head
this.head = newHead
this.length++
return this.head
}
re mal amigo 😂
insert(value, position){
for(let i=0; i<this.length; i++){
if(Object.keys(this.head.next) < 1 ){
if(this.head.value === position){
this.prepend(value)
this.length ++;
}
}
}
return this
}
Orale! Vamos a intentarlo carnales
Aqui les dejo otra forma mas simplificada de hacer el prepend (Ecma)
prepend(value) {
let newNode = new node(value)
this.head = {...newNode, next: this.head}
this.length ++;
return this;
}
ejercicio del append resulto antes de ver el video
class Nodo {
constructor(value) {
this.value = value;
this.next = null;
}
getNodo(){
return{
value:this.value,
next: this.next,
}
}
}
class MySinglyLinkedList {
constructor(value) {
this.head = {
value: value,
next: null,
};
this.tail = this.head;
this.length = 1;
}
append(value){
this.tail = new Nodo(value).getNodo();
this.length++;
this.head.next = this.tail;
return this.head;
}
}
Estoy en el minuto 8:58 espero que esta solucion sea la correcta 😄
MY NOTES FROM NODES TO THE LIST 😄
class Node{
constructor(value){
this.value = value;
this.next = null;
}
}
class MySinglyLinkedList{
constructor(value){
this.head = {
value: value,
next: null,
}
this.tail = this.head;
this.length = 1;
}
append(value){
//generamos una constante en la cual vamos a generar un nuevo
//Nodo que se va a colocar en la cola de nuestra lista
//Hacemos una instancia de la clase que crea nuestros nodos
const newNode = new Node(value);
//Le asignamos a la cola el nuevo nodo pero para la fila el ultimo nodo
//Que habia en la fila sigue siendo la fila
this.tail.next = newNode;
//Luego le indicamos a la fila que el ultimo nodo es el que creamos
this.tail = newNode;
//Incrementamos la logintud de nuestra lista
this.length++;
return this;
}
prepend(){
const newNode = new Node(value);
newNode.next = this.head;
this.head = newNode;
this.length++;
return this;
}
}
let myLinkedList = new MySinglyLinkedList(1);
mi humilde aporte
{
// 1 2 3 4 5
if(nodeNumber > this.length){
return undefined;
}else if(nodeNumber === 0){
this.prepend(value);
return this;
}else if(nodeNumber === this.length -1){
this.append(value);
return this;
}
const newNode = new Node(value);
let pointer = this.head;
for(let i = 0; i < (nodeNumber - 1); i++){
pointer = pointer.next;
}
newNode.next = pointer.next;
pointer.next = newNode;
this.length++;
return this;
}
Prácticamente el ejemplo que se genera en esta clase juega con las referencias por eso al momento de modificar el head tail se ve afectado
Mi solución:
class Node {
constructor (value) {
this.value = value;
this.next = null;
}
}
class MySinglyLinkedList {
constructor(value) {
this.head = new Node(value);
this.tail = this.head;
this.length = 1;
}
append(value) {
const newNode = new Node(value);
this.tail.next = newNode;
this.tail = newNode;
this.length++;
}
}
Método insert
insert(value, index){
if(index<this.length){
let currentNode = this.head;
let before;
for(let i=0;i<this.length;i++){
if(i===index-1){
let node = new Node(value);
node.next = currentNode;
before.next = node;
this.length++;
return this;
}
before = currentNode;
currentNode = currentNode.next;
}
}else{
return "overflow"
}
}
Mi insert para el reto 😊
insert(value, position) {
if(position <= this.length) {
if (position === 0) this.prepend(value)
else if (position === (this.length)) this.append(value)
else {
let aux = this.head
let newNodo = new Nodo(value)
for(let i = 1; i < position; i++){
aux = aux.next
}
newNodo.next = aux.next
aux.next= newNodo
this.length++
}
}
}```
Ahí va la implementación del método insert:
insert ( value, position ){
if( position === 0)
this.prepend( value )
else if( position === this.length )
this.append( value )
else {
const insertedNode = new Node( value )
let previousNode = this.head
for( let i=1; i < position; i++){
previousNode = previousNode.next
}
let nextNode = previousNode.next
insertedNode.next = nextNode
previousNode.next = insertedNode
}
this.length += 1
return this
}
Solución al reto
insert(value, index) {
if (index === 0) {
this.prepend(value);
return;
}
if (index === this.length) {
this.append(value);
return;
}
const newNode = new Node(value);
let auxNode = this.head;
for (let i = 0; i < index-1; i++) {
auxNode = auxNode.next;
}
newNode.next = auxNode.next;
auxNode.next = newNode;
this.length++;
return this;
}
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?