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": { 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/linked-list/circular-linked-list/node.ts b/src/modules/linked-list/circular-linked-list/node.ts new file mode 100644 index 0000000..ed7a933 --- /dev/null +++ b/src/modules/linked-list/circular-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/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/linked-list/singly-linked-list/singly-linked-list.ts b/src/modules/linked-list/singly-linked-list/singly-linked-list.ts new file mode 100644 index 0000000..174d861 --- /dev/null +++ b/src/modules/linked-list/singly-linked-list/singly-linked-list.ts @@ -0,0 +1,33 @@ +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; + } +} + \ 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 new file mode 100644 index 0000000..288abca --- /dev/null +++ b/tests/singly-linked-list.test.ts @@ -0,0 +1,16 @@ +import { SinglyLinkedList } from '../src/modules/linked-list/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]); + }); +}); 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]); + }); +});