diff --git "a/JavaScript/07\354\243\274\354\260\250/assignment/7\354\243\274\354\260\250/\353\257\274\355\230\234/index.js" "b/JavaScript/07\354\243\274\354\260\250/assignment/7\354\243\274\354\260\250/\353\257\274\355\230\234/index.js" new file mode 100644 index 0000000..7f99a65 --- /dev/null +++ "b/JavaScript/07\354\243\274\354\260\250/assignment/7\354\243\274\354\260\250/\353\257\274\355\230\234/index.js" @@ -0,0 +1,146 @@ +/** + * 양방향 연결리스트는 각 노드의 prev와 next로 이동할 수 있어야 한다. + */ + + class Node { + constructor(value) { + this.prev = null; + this.value = value; + this.next = null; + } +} + +class DoublyLinkedList { + constructor() { + this.head = null; + this.tail = null; + this.length = 0; + } + + checkindexValidation (index) { + if (index < 0 || index > this.length - 1) return true; + } + + /** + * push를 통해 양방향 연결리스트 꼬리에 값을 추가할 수 있다. + */ + push(value) { + const newNode = new Node(value); + if (!this.head) { + this.head = newNode; + this.tail = newNode; + } else { + this.tail.next = newNode; + newNode.prev = this.tail; + this.tail = newNode; + } + this.length++; + return this; + } + /** + * insert를 통해 특정 인덱스의 노드에 삽입할 수 있어야 한다. + */ + insert(index, value) { + if(this.checkindexValidation(index)) return false + if (index === this.length - 1) return !!this.push(value); + + const newNode = new Node(value); + const previousNode = this.get(index); + const afterNode = previousNode.next; + newNode.next = afterNode; + + newNode.prev = previousNode; + previousNode.next = newNode; + afterNode.prev = newNode; + this.length++; + + return true; + } + +/** + * get을 통해 원하는 인덱스의 노드를 가져온다. + */ + get(index) { + if(this.checkindexValidation(index)) return false + let counter = 0; + let currentNode = this.head; + while (counter < index) { + currentNode = currentNode.next; + counter++; + } + return currentNode; + } + + /** + * shift를 통해 머리 노드를 가져온다. + */ + shift() { + const shiftedHead = this.head; + + if(!this.head) return undefined; + if(this.length === 1){ + this.head = null; + this.tail = null; + } else{ + this.head = shiftedHead.next; + this.head.prev = null; + } + this.length--; + return shiftedHead; + +} + + /** + * remove를 통해 원하는 인덱스의 노드를 삭제한다. + */ + remove(index) { + if (this.checkindexValidation(index)) return false; + if (index === 0) return this.shift(); + if (index === this.length-1) return this.pop(); + + const currentNode = this.get(index); + const previousNode = currentNode.prev; + const afterNode = currentNode.next; + + previousNode.next = afterNode; + afterNode.prev = previousNode; + this.length--; + + return currentNode; + } + + /** + * pop 메서드를 통해 꼬리 노드를 꺼낸다. + */ + pop() { + const poppedTail = this.tail; + + if(!this.head) return undefined; + if(this.length === 1){ + this.head = null; + this.tail = null; + } else{ + this.tail = poppedTail.prev; + this.tail.next = null; + } + this.length--; + + return poppedTail; + } + + /** + * update를 통해 원하는 인덱스의 노드를 수정할 수 있다. + */ + update(index, value) { + if(this.checkindexValidation(index)) return false + + const currentNode = this.get(index); + currentNode.value = value; + + return true; + } +} + +const list = new DoublyLinkedList(); + +module.exports = DoublyLinkedList; \ No newline at end of file diff --git "a/JavaScript/07\354\243\274\354\260\250/assignment/7\354\243\274\354\260\250/\353\257\274\355\230\234/index.test.js" "b/JavaScript/07\354\243\274\354\260\250/assignment/7\354\243\274\354\260\250/\353\257\274\355\230\234/index.test.js" new file mode 100644 index 0000000..15c9766 --- /dev/null +++ "b/JavaScript/07\354\243\274\354\260\250/assignment/7\354\243\274\354\260\250/\353\257\274\355\230\234/index.test.js" @@ -0,0 +1,46 @@ +const DoublyLinkedList = require("./index"); + +describe("양방향 연결리스트", () => { + let doublyLinkedList; + // 1,2,3이 순서대로 양방향 연결리스트에 들어있습니다. + beforeEach(() => { + doublyLinkedList = new DoublyLinkedList(); + doublyLinkedList.push(1).push(2).push(3); + }); + test("push 메서드로 3개를 추가하면 양방향 연결리스트의 길이는 3이다.", () => { + expect(doublyLinkedList.length).toBe(3); + }); + test("1,2,3을 차례대로 추가했을 때 머리노드 값은 1이고 꼬리노드 값은 3이다.", () => { + expect(doublyLinkedList.head.value).toBe(1); + expect(doublyLinkedList.tail.value).toBe(3); + }); + // 첫번째 머리노드(head)의 인덱스 번호는 0입니다. 두번째 노드의 인덱스 번호는 1입니다. + test("get 메서드로 두번째 노드를 추출한 값은 2이다.", () => { + const extractedNode = doublyLinkedList.get(1); + expect(extractedNode.value).toBe(2); + }); + test("insert 메서드로 두번째 노드 뒤에 2.5를 추가할 수 있다.", () => { + doublyLinkedList.insert(1, 2.5); + expect(doublyLinkedList.get(1).value).toBe(2); + expect(doublyLinkedList.get(2).value).toBe(2.5); + expect(doublyLinkedList.get(3).value).toBe(3); + expect(doublyLinkedList.length).toBe(4); + }); + test("remove 메서드로 원하는 인덱스의 값을 삭제할 수 있다.", () => { + doublyLinkedList.remove(1); + expect(doublyLinkedList.get(1).value).toBe(3); + expect(doublyLinkedList.length).toBe(2); + }); + test("pop 메서드로 꼬리 노드를 꺼낼 수 있다.", () => { + expect(doublyLinkedList.pop().value).toBe(3); + expect(doublyLinkedList.length).toBe(2); + }); + test("shift 메서드로 머리 노드를 꺼낼 수 있다.", () => { + expect(doublyLinkedList.shift().value).toBe(1); + expect(doublyLinkedList.length).toBe(2); + }); + test("update 메서드로 두번째 노드의 값을 변경할 수 있다.", () => { + doublyLinkedList.update(1, 10); + expect(doublyLinkedList.get(1).value).toBe(10); + }); +}); diff --git "a/JavaScript/07\354\243\274\354\260\250/assignment/7\354\243\274\354\260\250/\353\257\274\355\230\234/package.json" "b/JavaScript/07\354\243\274\354\260\250/assignment/7\354\243\274\354\260\250/\353\257\274\355\230\234/package.json" new file mode 100644 index 0000000..a94f4d5 --- /dev/null +++ "b/JavaScript/07\354\243\274\354\260\250/assignment/7\354\243\274\354\260\250/\353\257\274\355\230\234/package.json" @@ -0,0 +1,10 @@ +{ + "main": "index.js", + "type": "module", + "scripts": { + "test": "jest" + }, + "devDependencies": { + "jest": "^29.3.1" + } +}