From f4dbadf6bdf53cacc3eb1b51660a9f0db1f5661c Mon Sep 17 00:00:00 2001 From: areeba-rehman <106922554+areeba-rehman@users.noreply.github.com> Date: Wed, 15 May 2024 22:42:47 -0700 Subject: [PATCH 1/5] feat: create SinglyLinkedList. --- .../singly-linked-list/singly-linked-list.ts | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/modules/singly-linked-list/singly-linked-list.ts diff --git a/src/modules/singly-linked-list/singly-linked-list.ts b/src/modules/singly-linked-list/singly-linked-list.ts new file mode 100644 index 0000000..a182e61 --- /dev/null +++ b/src/modules/singly-linked-list/singly-linked-list.ts @@ -0,0 +1,32 @@ +import { Node } from './node'; + +export class SinglyLinkedList { + private head: Node | null; + + constructor() { + this.head = null; + } + + add(data: T): void { + const newNode = new Node(data); + if (!this.head) { + this.head = newNode; + } else { + let current = this.head; + while (current.next) { + current = current.next; + } + current.next = newNode; + } + } + + toArray(): T[] { + const result: T[] = []; + let current = this.head; + while (current) { + result.push(current.data); + current = current.next; + } + return result; + } +} From e410b40f501e897769ee24c9493e2700d4ef1dac Mon Sep 17 00:00:00 2001 From: areeba-rehman <106922554+areeba-rehman@users.noreply.github.com> Date: Wed, 15 May 2024 22:43:33 -0700 Subject: [PATCH 2/5] feat: Create Node. --- src/modules/singly-linked-list/node.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/modules/singly-linked-list/node.ts diff --git a/src/modules/singly-linked-list/node.ts b/src/modules/singly-linked-list/node.ts new file mode 100644 index 0000000..ed7a933 --- /dev/null +++ b/src/modules/singly-linked-list/node.ts @@ -0,0 +1,9 @@ +export class Node { + data: T; + next: Node | null; + + constructor(data: T) { + this.data = data; + this.next = null; + } +} From 8370b9cda24acc200bd0691733a5aa188297bc2f Mon Sep 17 00:00:00 2001 From: areeba-rehman <106922554+areeba-rehman@users.noreply.github.com> Date: Wed, 15 May 2024 22:44:56 -0700 Subject: [PATCH 3/5] test: Update SinglyLinkedList test. --- tests/singly-linked-list.test.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/singly-linked-list.test.ts diff --git a/tests/singly-linked-list.test.ts b/tests/singly-linked-list.test.ts new file mode 100644 index 0000000..137cdf6 --- /dev/null +++ b/tests/singly-linked-list.test.ts @@ -0,0 +1,17 @@ +import { SinglyLinkedList } from '../src/modules/singly-linked-list/singly-linked-list'; + +describe('SinglyLinkedList', () => { + it('should initialize empty', () => { + const list = new SinglyLinkedList(); + expect(list.toArray()).toEqual([]); + }); + + it('should add elements', () => { + const list = new SinglyLinkedList(); + list.add(1); + list.add(2); + list.add(3); + expect(list.toArray()).toEqual([1, 2, 3]); + }); +}); + From d355b8ba6c6af1a666dfacb747d7ae3a6f8acd2e Mon Sep 17 00:00:00 2001 From: areeba-rehman <106922554+areeba-rehman@users.noreply.github.com> Date: Sat, 25 May 2024 06:56:57 -0700 Subject: [PATCH 4/5] feat: Implement linked list --- .../circular-linked-list.ts | 43 ++++++++++++ .../circular-linked-list}/node.ts | 0 .../doubly-linked-list/doubly-linked-list.ts | 35 ++++++++++ .../linked-list/doubly-linked-list/node.ts | 11 +++ .../linked-list/singly-linked-list/node.ts | 9 +++ .../singly-linked-list/singly-linked-list.ts | 1 + .../linked-list/xor-linked-list/node.ts | 9 +++ .../xor-linked-list/xor-linked-list.ts | 67 +++++++++++++++++++ tests/circular-linked-list.test.ts | 37 ++++++++++ tests/doubly-linked-list.test.ts | 16 +++++ tests/singly-linked-list.test.ts | 3 +- tests/xor-linked-list.test.ts | 16 +++++ 12 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 src/modules/linked-list/circular-linked-list/circular-linked-list.ts rename src/modules/{singly-linked-list => linked-list/circular-linked-list}/node.ts (100%) create mode 100644 src/modules/linked-list/doubly-linked-list/doubly-linked-list.ts create mode 100644 src/modules/linked-list/doubly-linked-list/node.ts create mode 100644 src/modules/linked-list/singly-linked-list/node.ts rename src/modules/{ => linked-list}/singly-linked-list/singly-linked-list.ts (99%) create mode 100644 src/modules/linked-list/xor-linked-list/node.ts create mode 100644 src/modules/linked-list/xor-linked-list/xor-linked-list.ts create mode 100644 tests/circular-linked-list.test.ts create mode 100644 tests/doubly-linked-list.test.ts create mode 100644 tests/xor-linked-list.test.ts diff --git a/src/modules/linked-list/circular-linked-list/circular-linked-list.ts b/src/modules/linked-list/circular-linked-list/circular-linked-list.ts new file mode 100644 index 0000000..210deab --- /dev/null +++ b/src/modules/linked-list/circular-linked-list/circular-linked-list.ts @@ -0,0 +1,43 @@ +import { Node } from './node'; + +export class CircularLinkedList { + private head: Node | null; + private tail: Node | null; + + constructor() { + this.head = null; + this.tail = null; + } + + add(data: T): void { + const newNode = new Node(data); + if (!this.head) { + this.head = newNode; + this.tail = newNode; + newNode.next = this.head; + } else { + if (this.tail) { + this.tail.next = newNode; + } + this.tail = newNode; + this.tail.next = this.head; + } + } + + toArray(): T[] { + const result: T[] = []; + if (!this.head) return result; + + let current: Node | null = this.head; + do { + result.push(current.data); + current = current.next; + } while (current && current !== this.head); + + return result; + } + + getHead(): Node | null { + return this.head; + } +} diff --git a/src/modules/singly-linked-list/node.ts b/src/modules/linked-list/circular-linked-list/node.ts similarity index 100% rename from src/modules/singly-linked-list/node.ts rename to src/modules/linked-list/circular-linked-list/node.ts diff --git a/src/modules/linked-list/doubly-linked-list/doubly-linked-list.ts b/src/modules/linked-list/doubly-linked-list/doubly-linked-list.ts new file mode 100644 index 0000000..09ce55c --- /dev/null +++ b/src/modules/linked-list/doubly-linked-list/doubly-linked-list.ts @@ -0,0 +1,35 @@ +import { Node } from './node'; + +export class DoublyLinkedList { + private head: Node | null; + private tail: Node | null; + + constructor() { + this.head = null; + this.tail = null; + } + + add(data: T): void { + const newNode = new Node(data); + if (!this.head) { + this.head = newNode; + this.tail = newNode; + } else { + newNode.prev = this.tail; + if (this.tail) { + this.tail.next = newNode; + } + this.tail = newNode; + } + } + + toArray(): T[] { + const result: T[] = []; + let current = this.head; + while (current) { + result.push(current.data); + current = current.next; + } + return result; + } +} diff --git a/src/modules/linked-list/doubly-linked-list/node.ts b/src/modules/linked-list/doubly-linked-list/node.ts new file mode 100644 index 0000000..a52f33f --- /dev/null +++ b/src/modules/linked-list/doubly-linked-list/node.ts @@ -0,0 +1,11 @@ +export class Node { + data: T; + next: Node | null; + prev: Node | null; + + constructor(data: T) { + this.data = data; + this.next = null; + this.prev = null; + } +} diff --git a/src/modules/linked-list/singly-linked-list/node.ts b/src/modules/linked-list/singly-linked-list/node.ts new file mode 100644 index 0000000..ed7a933 --- /dev/null +++ b/src/modules/linked-list/singly-linked-list/node.ts @@ -0,0 +1,9 @@ +export class Node { + data: T; + next: Node | null; + + constructor(data: T) { + this.data = data; + this.next = null; + } +} diff --git a/src/modules/singly-linked-list/singly-linked-list.ts b/src/modules/linked-list/singly-linked-list/singly-linked-list.ts similarity index 99% rename from src/modules/singly-linked-list/singly-linked-list.ts rename to src/modules/linked-list/singly-linked-list/singly-linked-list.ts index a182e61..174d861 100644 --- a/src/modules/singly-linked-list/singly-linked-list.ts +++ b/src/modules/linked-list/singly-linked-list/singly-linked-list.ts @@ -30,3 +30,4 @@ export class SinglyLinkedList { return result; } } + \ No newline at end of file diff --git a/src/modules/linked-list/xor-linked-list/node.ts b/src/modules/linked-list/xor-linked-list/node.ts new file mode 100644 index 0000000..f3b9a46 --- /dev/null +++ b/src/modules/linked-list/xor-linked-list/node.ts @@ -0,0 +1,9 @@ +export class Node { + data: T; + xorPointer: number; + + constructor(data: T) { + this.data = data; + this.xorPointer = 0; + } +} diff --git a/src/modules/linked-list/xor-linked-list/xor-linked-list.ts b/src/modules/linked-list/xor-linked-list/xor-linked-list.ts new file mode 100644 index 0000000..8cbb5e1 --- /dev/null +++ b/src/modules/linked-list/xor-linked-list/xor-linked-list.ts @@ -0,0 +1,67 @@ +import { Node } from './node'; + +function xor(a: number, b: number): number { + return a ^ b; +} + +export class XORLinkedList { + private head: Node | null; + private tail: Node | null; + private nodes: Map>; + private idCounter: number; + + constructor() { + this.head = null; + this.tail = null; + this.nodes = new Map>(); + this.idCounter = 1; + } + + private getNodeId(node: Node | null): number { + if (!node) return 0; + for (let [id, n] of this.nodes.entries()) { + if (n === node) return id; + } + const newId = this.idCounter++; + this.nodes.set(newId, node); + return newId; + } + + private getNodeById(id: number): Node | null { + return this.nodes.get(id) || null; + } + + add(data: T): void { + const newNode = new Node(data); + if (!this.head) { + this.head = newNode; + this.tail = newNode; + } else { + const tailId = this.getNodeId(this.tail); + newNode.xorPointer = tailId; + if (this.tail) { + this.tail.xorPointer = xor(this.tail.xorPointer, this.getNodeId(newNode)); + } + this.tail = newNode; + } + this.getNodeId(newNode); + } + + toArray(): T[] { + const result: T[] = []; + if (!this.head) return result; + + let current: Node | null = this.head; + let prevId = 0; + let nextId: number; + + while (current !== null) { + result.push(current.data); + nextId = xor(prevId, current.xorPointer); + prevId = this.getNodeId(current); + current = this.getNodeById(nextId); + } + + return result; + } +} diff --git a/tests/circular-linked-list.test.ts b/tests/circular-linked-list.test.ts new file mode 100644 index 0000000..b2967fe --- /dev/null +++ b/tests/circular-linked-list.test.ts @@ -0,0 +1,37 @@ +import { CircularLinkedList } from '../src/modules/linked-list/circular-linked-list/circular-linked-list'; +import { Node } from '../src/modules/linked-list/circular-linked-list/node'; + +describe('CircularLinkedList', () => { + it('should initialize empty', () => { + const list = new CircularLinkedList(); + expect(list.toArray()).toEqual([]); + }); + + it('should add elements', () => { + const list = new CircularLinkedList(); + list.add(1); + list.add(2); + list.add(3); + expect(list.toArray()).toEqual([1, 2, 3]); + }); + + it('should maintain circular link', () => { + const list = new CircularLinkedList(); + list.add(1); + list.add(2); + list.add(3); + + const head = list.getHead(); + if (head) { + let current = head; + let count = 0; + do { + current = current.next as Node; + count++; + } while (current && current !== head && count <= 3); + + expect(count).toEqual(3); + expect(current).toBe(head); + } + }); +}); diff --git a/tests/doubly-linked-list.test.ts b/tests/doubly-linked-list.test.ts new file mode 100644 index 0000000..cf2c1ed --- /dev/null +++ b/tests/doubly-linked-list.test.ts @@ -0,0 +1,16 @@ +import { DoublyLinkedList } from '../src/modules/linked-list/doubly-linked-list/doubly-linked-list'; + +describe('DoublyLinkedList', () => { + it('should initialize empty', () => { + const list = new DoublyLinkedList(); + expect(list.toArray()).toEqual([]); + }); + + it('should add elements', () => { + const list = new DoublyLinkedList(); + list.add(1); + list.add(2); + list.add(3); + expect(list.toArray()).toEqual([1, 2, 3]); + }); +}); diff --git a/tests/singly-linked-list.test.ts b/tests/singly-linked-list.test.ts index 137cdf6..288abca 100644 --- a/tests/singly-linked-list.test.ts +++ b/tests/singly-linked-list.test.ts @@ -1,4 +1,4 @@ -import { SinglyLinkedList } from '../src/modules/singly-linked-list/singly-linked-list'; +import { SinglyLinkedList } from '../src/modules/linked-list/singly-linked-list/singly-linked-list'; describe('SinglyLinkedList', () => { it('should initialize empty', () => { @@ -14,4 +14,3 @@ describe('SinglyLinkedList', () => { expect(list.toArray()).toEqual([1, 2, 3]); }); }); - diff --git a/tests/xor-linked-list.test.ts b/tests/xor-linked-list.test.ts new file mode 100644 index 0000000..899fe00 --- /dev/null +++ b/tests/xor-linked-list.test.ts @@ -0,0 +1,16 @@ +import { XORLinkedList } from '../src/modules/linked-list/xor-linked-list/xor-linked-list'; + +describe('XORLinkedList', () => { + it('should initialize empty', () => { + const list = new XORLinkedList(); + expect(list.toArray()).toEqual([]); + }); + + it('should add elements', () => { + const list = new XORLinkedList(); + list.add(1); + list.add(2); + list.add(3); + expect(list.toArray()).toEqual([1, 2, 3]); + }); +}); From ac45b7954b60cd6556b69f1bce5ce0a5504e7687 Mon Sep 17 00:00:00 2001 From: areeba-rehman <106922554+areeba-rehman@users.noreply.github.com> Date: Sat, 25 May 2024 07:07:31 -0700 Subject: [PATCH 5/5] feat: linked list --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 2ee9cca..36139b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2994,7 +2994,7 @@ }, "node_modules/jest": { "version": "29.7.0", - "resolved": "https://verdaccio.dev.curogram.com/jest/-/jest-29.7.0.tgz", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "dependencies": {