mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-11-10 11:09:43 +08:00
Inserting, removing, accessing, modifying, by index, on linked list with tests
This commit is contained in:
parent
819f38f792
commit
3303051d75
@ -87,6 +87,28 @@ export default class LinkedList {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* @param {*} value
|
||||
* @param {number} index
|
||||
* @return {LinkedList}
|
||||
*/
|
||||
setAtIndex(value, index) {
|
||||
if (index < 0) {
|
||||
return this;
|
||||
} else {
|
||||
let count = 0;
|
||||
let currentNode = this.head;
|
||||
while (currentNode) {
|
||||
if (count === index) break;
|
||||
currentNode = currentNode.next;
|
||||
count += 1;
|
||||
}
|
||||
if (currentNode) {
|
||||
currentNode.value = value;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {*} value
|
||||
@ -128,6 +150,36 @@ export default class LinkedList {
|
||||
return deletedNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} index
|
||||
* @return {LinkedListNode}
|
||||
*/
|
||||
deleteAtIndex(index) {
|
||||
if (!this.head || index < 0) {
|
||||
return null;
|
||||
}
|
||||
let deletedNode = null;
|
||||
if (index === 0) {
|
||||
deletedNode = this.head;
|
||||
this.head = this.head.next;
|
||||
} else {
|
||||
let count = 1;
|
||||
let currentNode = this.head;
|
||||
while (currentNode) {
|
||||
if (count === index) break;
|
||||
currentNode = currentNode.next;
|
||||
count += 1;
|
||||
}
|
||||
if (currentNode) {
|
||||
deletedNode = currentNode.next;
|
||||
if (deletedNode) {
|
||||
currentNode.next = deletedNode.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
return deletedNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} findParams
|
||||
* @param {*} findParams.value
|
||||
@ -158,6 +210,26 @@ export default class LinkedList {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {*} index
|
||||
* @return {LinkedListNode}
|
||||
*/
|
||||
findByIndex(index) {
|
||||
if (!this.head || index < 0) {
|
||||
return null;
|
||||
} else if (index === 0) {
|
||||
return this.head;
|
||||
}
|
||||
let count = 0;
|
||||
let currentNode = this.head;
|
||||
while (currentNode) {
|
||||
if (count === index) break;
|
||||
currentNode = currentNode.next;
|
||||
count += 1;
|
||||
}
|
||||
return currentNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {LinkedListNode}
|
||||
*/
|
||||
@ -239,7 +311,9 @@ export default class LinkedList {
|
||||
* @return {string}
|
||||
*/
|
||||
toString(callback) {
|
||||
return this.toArray().map((node) => node.toString(callback)).toString();
|
||||
return this.toArray()
|
||||
.map((node) => node.toString(callback))
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,6 +47,26 @@ describe('LinkedList', () => {
|
||||
expect(linkedList.toString()).toBe('1,4,2,3,10');
|
||||
});
|
||||
|
||||
it('should insert node to linked list', () => {
|
||||
const linkedList = new LinkedList();
|
||||
|
||||
linkedList.append(1).append(2).append(3).append(4).append(5);
|
||||
|
||||
expect(linkedList.toString()).toBe('1,2,3,4,5');
|
||||
|
||||
linkedList.setAtIndex(5, -2);
|
||||
expect(linkedList.toString()).toBe('1,2,3,4,5');
|
||||
|
||||
linkedList.setAtIndex(12, 3);
|
||||
expect(linkedList.toString()).toBe('1,2,3,12,5');
|
||||
|
||||
linkedList.setAtIndex(55, 0);
|
||||
expect(linkedList.toString()).toBe('55,2,3,12,5');
|
||||
|
||||
linkedList.setAtIndex(0, 55);
|
||||
expect(linkedList.toString()).toBe('55,2,3,12,5');
|
||||
});
|
||||
|
||||
it('should delete node by value from linked list', () => {
|
||||
const linkedList = new LinkedList();
|
||||
|
||||
@ -93,6 +113,34 @@ describe('LinkedList', () => {
|
||||
expect(linkedList.toString()).toBe('');
|
||||
});
|
||||
|
||||
it('should delete node at index from linked list', () => {
|
||||
const linkedList = new LinkedList();
|
||||
|
||||
expect(linkedList.delete(5)).toBeNull();
|
||||
|
||||
linkedList.append(1);
|
||||
linkedList.append(2);
|
||||
linkedList.append(3);
|
||||
linkedList.append(4);
|
||||
linkedList.append(5);
|
||||
|
||||
expect(linkedList.head.toString()).toBe('1');
|
||||
expect(linkedList.tail.toString()).toBe('5');
|
||||
|
||||
let deletedNode = linkedList.deleteAtIndex(3);
|
||||
expect(deletedNode.value).toBe(4);
|
||||
expect(linkedList.toString()).toBe('1,2,3,5');
|
||||
|
||||
linkedList.deleteAtIndex(1);
|
||||
expect(linkedList.toString()).toBe('1,3,5');
|
||||
|
||||
deletedNode = linkedList.delete(-5);
|
||||
expect(deletedNode).toBeNull();
|
||||
|
||||
deletedNode = linkedList.delete(10);
|
||||
expect(deletedNode).toBeNull();
|
||||
});
|
||||
|
||||
it('should delete linked list tail', () => {
|
||||
const linkedList = new LinkedList();
|
||||
|
||||
@ -157,9 +205,7 @@ describe('LinkedList', () => {
|
||||
const nodeValue1 = { value: 1, key: 'key1' };
|
||||
const nodeValue2 = { value: 2, key: 'key2' };
|
||||
|
||||
linkedList
|
||||
.append(nodeValue1)
|
||||
.prepend(nodeValue2);
|
||||
linkedList.append(nodeValue1).prepend(nodeValue2);
|
||||
|
||||
const nodeStringifier = (value) => `${value.key}:${value.value}`;
|
||||
|
||||
@ -174,9 +220,7 @@ describe('LinkedList', () => {
|
||||
linkedList.append(1);
|
||||
expect(linkedList.find({ value: 1 })).toBeDefined();
|
||||
|
||||
linkedList
|
||||
.append(2)
|
||||
.append(3);
|
||||
linkedList.append(2).append(3);
|
||||
|
||||
const node = linkedList.find({ value: 2 });
|
||||
|
||||
@ -184,6 +228,21 @@ describe('LinkedList', () => {
|
||||
expect(linkedList.find({ value: 5 })).toBeNull();
|
||||
});
|
||||
|
||||
it('should find node by index', () => {
|
||||
const linkedList = new LinkedList();
|
||||
|
||||
expect(linkedList.findByIndex(5)).toBeNull();
|
||||
linkedList.append(1);
|
||||
expect(linkedList.findByIndex(0).value).toBe(1);
|
||||
|
||||
linkedList.append(2).append(3);
|
||||
|
||||
const node = linkedList.findByIndex(2);
|
||||
expect(node.value).toBe(3);
|
||||
expect(linkedList.findByIndex(5)).toBeNull();
|
||||
expect(linkedList.findByIndex(-3)).toBeNull();
|
||||
});
|
||||
|
||||
it('should find node by callback', () => {
|
||||
const linkedList = new LinkedList();
|
||||
|
||||
@ -192,12 +251,16 @@ describe('LinkedList', () => {
|
||||
.append({ value: 2, key: 'test2' })
|
||||
.append({ value: 3, key: 'test3' });
|
||||
|
||||
const node = linkedList.find({ callback: (value) => value.key === 'test2' });
|
||||
const node = linkedList.find({
|
||||
callback: (value) => value.key === 'test2',
|
||||
});
|
||||
|
||||
expect(node).toBeDefined();
|
||||
expect(node.value.value).toBe(2);
|
||||
expect(node.value.key).toBe('test2');
|
||||
expect(linkedList.find({ callback: (value) => value.key === 'test5' })).toBeNull();
|
||||
expect(
|
||||
linkedList.find({ callback: (value) => value.key === 'test5' })
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('should create linked list from array', () => {
|
||||
@ -230,7 +293,9 @@ describe('LinkedList', () => {
|
||||
expect(node).toBeDefined();
|
||||
expect(node.value.value).toBe(2);
|
||||
expect(node.value.customValue).toBe('test2');
|
||||
expect(linkedList.find({ value: { value: 2, customValue: 'test5' } })).toBeNull();
|
||||
expect(
|
||||
linkedList.find({ value: { value: 2, customValue: 'test5' } })
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('should find preferring callback over compare function', () => {
|
||||
@ -258,10 +323,7 @@ describe('LinkedList', () => {
|
||||
const linkedList = new LinkedList();
|
||||
|
||||
// Add test values to linked list.
|
||||
linkedList
|
||||
.append(1)
|
||||
.append(2)
|
||||
.append(3);
|
||||
linkedList.append(1).append(2).append(3);
|
||||
|
||||
expect(linkedList.toString()).toBe('1,2,3');
|
||||
expect(linkedList.head.value).toBe(1);
|
||||
|
Loading…
Reference in New Issue
Block a user