Skip to content

Commit

Permalink
feat(LinkedList): add remove
Browse files Browse the repository at this point in the history
  • Loading branch information
sun0day committed Oct 12, 2022
1 parent 15337b2 commit a50c9d6
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
42 changes: 42 additions & 0 deletions packages/linked-list/index.test.ts
Expand Up @@ -64,4 +64,46 @@ describe('LinkedList', () => {
expect(list.size()).toBe(5)
expect(list.toArray()).toEqual([1, 3, 4, 2, 5])
})

it('should remove', () => {
const list = LinkedList.from([1, 2, 3, 4])
let removed = list.remove(node => node.value === 1)
expect(removed.value).toBe(1)
expect(removed.next).toBe(null)
expect(list.head().value).toBe(2)
expect(list.tail().value).toBe(4)
expect(list.size()).toBe(3)
expect(list.toArray()).toEqual([2, 3, 4])

removed = list.remove(node => node.value === 3)
expect(removed.value).toBe(3)
expect(removed.next).toBe(null)
expect(list.head().value).toBe(2)
expect(list.tail().value).toBe(4)
expect(list.size()).toBe(2)
expect(list.toArray()).toEqual([2, 4])

removed = list.remove(node => node.value === 4)
expect(removed.value).toBe(4)
expect(removed.next).toBe(null)
expect(list.head().value).toBe(2)
expect(list.tail().value).toBe(2)
expect(list.size()).toBe(1)
expect(list.toArray()).toEqual([2])

removed = list.remove(node => node.value === 2)
expect(removed.value).toBe(2)
expect(removed.next).toBe(null)
expect(list.head()).toBeNull()
expect(list.tail()).toBeNull()
expect(list.size()).toBe(0)
expect(list.toArray()).toEqual([])

removed = list.remove(node => node.value === 5)
expect(removed).toBeNull()
expect(list.head()).toBeNull()
expect(list.tail()).toBeNull()
expect(list.size()).toBe(0)
expect(list.toArray()).toEqual([])
})
})
52 changes: 52 additions & 0 deletions packages/linked-list/index.ts
Expand Up @@ -31,6 +31,20 @@ export class LinkedList<T> {
return value instanceof LinkedListNode ? value : new LinkedListNode(value)
}

/**
* create LinkedList from array, T = O(n)
*
* @template T
* @param {T[]} values - node value set
* @returns {LinkedList<T>}
*/
static from<T>(values: T[]) {
const list = new LinkedList<T>()
values.forEach(value => list.append(value))

return list
}

constructor() {
this._head = null
this._tail = null
Expand Down Expand Up @@ -103,6 +117,44 @@ export class LinkedList<T> {
this._size++
}

/**
* remove node, T = O(n)
*
* @param {LinkedListNode<T>) => boolean} compare - node which matches `compare` will be removed
* @returns {LinkedListNode<T> | null} - return removed node, if node not exist, return null
*/
remove(compare: (node: LinkedListNode<T>) => boolean) {
const shadowHead = new LinkedListNode(null, this._head)
let count = 0
let prev = shadowHead
let cur = prev

while (cur) {
// should ignore shadow head
if (count++ > 0 && compare(cur))
break

prev = cur
cur = cur.next
}

if (!cur)
return null

prev.next = cur.next
cur.next = null

if (cur === this._head)
this._head = prev.next

if (cur === this._tail)
this._tail = prev === shadowHead ? null : prev

this._size--

return cur
}

/**
* get head node
*
Expand Down

0 comments on commit a50c9d6

Please sign in to comment.