๐ ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Linked List)์ ๊ฐ๋
์ฐ๊ฒฐ ๋ฆฌ์คํธ(Linked List) ๋ ๋ฐ์ดํฐ๋ฅผ ์ฐ์์ ์ธ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ ์ฅํ๋ ๋ฐฐ์ด๊ณผ๋ ๋ค๋ฅด๊ฒ,
๊ฐ ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋ ์์น๊ฐ ์๋ก ๋จ์ด์ ธ ์๋ ์๋ฃ๊ตฌ์กฐ์ด๋ค.
์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๊ฐ ๋ฐ์ดํฐ๊ฐ ๋
ธ๋(Node)๋ก ๊ตฌ์ฑ๋์ด ์์ผ๋ฉฐ, ์ด ๋
ธ๋๋ ๋ ๊ฐ์ง ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ค:
๋ฐ์ดํฐ: ๋
ธ๋์ ์ ์ฅ๋ ๊ฐ
๋ค์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ(๋งํฌ): ๋ค์ ๋
ธ๋์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์
๐ ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Linked List)์ ํน์ง
- ๋์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น : ๋ฐฐ์ด์ ํฌ๊ธฐ๊ฐ ๊ณ ์ ๋์ด ์์ง๋ง, ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ํ์์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๋ ธ๋๋ฅผ ์ถ๊ฐํ ์ ์๋ค.
- ๋
ธ๋ ์ถ๊ฐ/์ญ์ ๊ฐ ํจ์จ์ : ์ฐ๊ฒฐ ๋ฆฌ์คํธ์์๋ ์ค๊ฐ์ ๋
ธ๋๋ฅผ ์ฝ์
ํ๊ฑฐ๋ ์ญ์ ํ ๋ ์ ์ฒด ๊ตฌ์กฐ๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ,
๋ช ๊ฐ์ ํฌ์ธํฐ๋ง ์์ ํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ๋ฐฐ์ด๋ณด๋ค ํจ์จ์ ์ด๋ค.
โ๏ธ ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Linked List)์ ๊ตฌ์กฐ
๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋จ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Singly Linked List) ๋ก,
๊ฐ ๋
ธ๋๊ฐ ๋ค์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ๋ฅผ ๊ฐ์ง๋ค.
[๋ฐ์ดํฐ | ๋ค์ ๋
ธ๋] -> [๋ฐ์ดํฐ | ๋ค์ ๋
ธ๋] -> [๋ฐ์ดํฐ | ๋ค์ ๋
ธ๋] -> null
์ฌ๊ธฐ์ null
์ ๋ง์ง๋ง ๋
ธ๋๋ฅผ ์๋ฏธํ๋ฉฐ, ๋ ์ด์ ์ฐ๊ฒฐ๋ ๋
ธ๋๊ฐ ์๋ค๋ ๋ป์ด๋ค.
๐ ์ฃผ์ ์ฐ์ฐ
- ์ฝ์
: ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ์ํ๋ ์์น์ ์ถ๊ฐํ๋ ๊ฒ.
์ฒซ ๋ฒ์งธ ์์น, ์ค๊ฐ ์์น, ๋ง์ง๋ง ์์น์ ์ฝ์ ํ ์ ์๋ค. - ์ญ์ : ์ํ๋ ์์น์ ์๋ ๋
ธ๋๋ฅผ ์ ๊ฑฐํ๋ ๊ฒ.
๋ ธ๋๋ฅผ ์ญ์ ํ ๋๋ ํด๋น ๋ ธ๋๋ก ๊ฐ๋ ๋งํฌ๋ฅผ ๋๊ณ , ์ด์ ๋ ธ๋๊ฐ ์ญ์ ๋ ๋ ธ๋์ ๋ค์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ํ๋ค. - ํ์ : ํน์ ๋ฐ์ดํฐ๋ฅผ ์ฐพ๊ธฐ ์ํด ์ฒซ ๋ ธ๋๋ถํฐ ์์ฐจ์ ์ผ๋ก ํ์ํ๋ค.
์์
์ฐ๊ฒฐ ๋ฆฌ์คํธ์ 3๊ฐ์ ๋ฐ์ดํฐ(1, 2, 3)๋ฅผ ์ ์ฅํ๋ค๊ณ ํ๋ฉด :
[1 | next] -> [2 | next] -> [3 | null]
๋ง์ฝ ์ค๊ฐ์ 4๋ฅผ ์ถ๊ฐํ๊ณ ์ถ๋ค๋ฉด, 2์ 3 ์ฌ์ด์ ์๋ก์ด ๋ ธ๋๋ฅผ ์ฝ์ ํ๋ฉด ๋๋ค :
[1 | next] -> [2 | next] -> [4 | next] -> [3 | null]
โจ ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Linked List)์ ๋์ ๊ตฌํํ๊ธฐ
์ฐ์ ๋ค์๊ณผ ๊ฐ์ด ํ๋์ Node
๋ฅผ ์ถ์ํ ํด์ class๋ฅผ ์ ์ธํด์คฌ๋ค.
- LinkeList.mjs
export class Node{ constructor(data, next = null){ this.data = data; this.next = next; } }
Node
์ ๋์์ ํ
์คํธํ๊ธฐ ์ํด ๊ฐ Node
์ธ์คํด์ค๋ค์ ์์ฑ ํnode.next
ํ๋กํผํฐ์ ๋ค์ ์์์ Node
๋ฅผ ์ฐธ์กฐ๋๊ฒ ์ฐ๊ฒฐํ ๋ค
node1
์ .data
ํ๋กํผํฐ์ ์ ๊ทผํด node1
์ ๋ฐ์ดํฐ๋ฅผ ํ์ธ ํ๊ณ node1.next
์ ์ฐธ์กฐ์ํจ node2
์ .data
ํ๋กํผํฐ์ ์ ๊ทผํด ํ์ธnode1
์์ node1.next
์ธ node2
์ ์ ๊ทผํด node2
์ .next
ํ๋กํผํฐ๊ฐ ์ฐธ์กฐํ๋ node3
์ .data
์ ์ ๊ทผํด ์ถ๋ ฅํด๋ณด์๋ค.
- test.mjs
import { Node } from './Node.mjs'
// 1. Node ์ธ์คํด์ค ์์ฑ
const node1 = new Node(1);
const node2 = new Node(2);
const node3 = new Node(3);
// 2. ๊ฐ Node์ next ํ๋กํผํฐ์ ๋ค์ Node๋ฅผ ์ฐธ์กฐํ ์ ์๊ฒ ์ฐ๊ฒฐ
node1.next = node2;
node2.next = node3;
// 3. ๊ฐ Node์ next ํ๋กํผํฐ๋ฅผ ํ๊ณ ์ฐ๊ฒฐ๋ Node๋ฅผ ํ์ธ
console.log(node1.data); // 1
console.log(node1.next.data); // 2
console.log(node1.next.next.data); // 3
์์ ๊ฐ์ด ๊ฐ `Node`๊ฐ ์ ์ฐ๊ฒฐ๋๊ฒ์ ํ์ธํ ์ ์๋ค.
๊ทธ๋ฆฌ๊ณ ๋ค์๊ณผ ๊ฐ์ด ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Linked List) ๋ฅผ LinkedList๋ก ์ถ์ํํด class๋ก ๊ตฌํํ๊ณ
์ฐ๊ฒฐ ๋ฆฌ์คํธ(Linked List)์ ๋์์ ๋ฉ์๋๋ก ๊ฐ๊ฐ ๊ตฌํํ์๋ค.
// * ์ฐ๊ฒฐ ๋ฆฌ์คํธ ์ถ์ ์๋ฃํ
// 1. ๋ชจ๋ ๋ฐ์ดํฐ ์ถ๋ ฅ -> printAll();
// 2. ๋ชจ๋ ๋ฐ์ดํฐ ์ ๊ฑฐ -> clear();
// 3. ์ํ๋ ์ธ๋ฑ์ค์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
-> insertAt(index, data);
// 4. ๋ง์ง๋ง ๋ฐ์ดํฐ ๋ค์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
-> insertLast(data);
// 5. ์ํ๋ ์ธ๋ฑ์ค์ ๋ฐ์ดํฐ๋ฅผ ์ญ์ -> deleteAt(index);
// 6. ๋ง์ง๋ง ๋ฐ์ดํฐ๋ฅผ ์ ๊ฑฐ -> deleteLast();
// 7. ์ํ๋ ์ธ๋ฑ์ค์ ์๋ ๋ฐ์ดํฐ ์ฝ๊ธฐ -> getNodeAt(index);
export class LinkedList {
constructor(){
// ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ์์ Node๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
this.head = null;
// ์ด ์ ์ฅ๋ Node์ ์
this.count = 0;
}
/**
* ์ํ๋ ์ธ๋ฑ์ค์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
* @param {number} index - ์ฝ์
ํ ์์น index
* @param {any} data - ์ฝ์
ํ ๋ฐ์ดํฐ
*/
insertAt(index, data){
// ์์ธ ์ฒ๋ฆฌ
if(index > this.count || index < 0) throw new Error('๋ฒ์๋ฅผ ๋์ด๊ฐ์ต๋๋ค.');
// ์๋ก์ด Node ์์ฑ
let newNode = new Node(data);
if(index === 0){
// ๋ฆฌ์คํธ์ ๊ฐ์ฅ ์๋ถ๋ถ์ ์ฝ์
ํ ๊ฒฝ์ฐ
// 1. ์์ฑ๋ Node์ next๊ฐ head๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ์ค์
newNode.next = this.head;
// 2. ์์ฑ๋ Node๋ฅผ head๋ก ์ค์
this.head = newNode;
}else{
// ์๋ถ๋ถ ์ฝ์
์ ์ ์ธํ ์ํ๋ ์ธ๋ฑ์ค์ ์ฝ์
ํ ๊ฒฝ์ฐ
// head์์ ๋ถํฐ ์์ํ๊ธฐ ๋๋ฌธ์ head๋ก ์ด๊ธฐํ
let currentNode = this.head;
// ๋ชฉํ ์ธ๋ฑ์ค ๋ฐ๋ก ์ ๊น์ง next๋ฅผ ์ด์ฉํด currentNode๋ฅผ ์ด๋์ํจ๋ค.
for(let i=0; i<index -1; i++){
currentNode = currentNode.next;
}
// 1. ์๋ก์ด Node๊ฐ currentNode์ next Node๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ์ค์
newNode.next = currentNode.next;
// 2. currentNode๊ฐ ์๋ก์ด Node๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ์ค์
currentNode.next = newNode
}
// ์๋ก์ด Node๊ฐ ์ฝ์
๋์์ผ๋ count๋ฅผ ์ฆ๊ฐ
this.count++;
}
/**
* ๋ชจ๋ ๋ฐ์ดํฐ ์ถ๋ ฅ
* @returns {string} - ๋ชจ๋ Node์ data๋ฅผ ํ๋์ ๋ฌธ์์ด์ ๋ด์ ๋ฐํ
*/
printAll(){
let currentNode = this.head;
let text = '['
while(currentNode){
text += currentNode.data
currentNode = currentNode.next;
if(currentNode) text += ', ';
}
text += ']';
console.log(text);
return text;
}
/**
* ๋ชจ๋ ๋ฐ์ดํฐ ์ ๊ฑฐ
*/
clear(){
this.head = null; // head ์ด๊ธฐํ
this.count = 0; // count ์ด๊ธฐํ
}
/**
* ๋ง์ง๋ง ๋ฐ์ดํฐ ๋ค์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
* @param {any} data - ์ฝ์
ํ ๋ฐ์ดํฐ
*/
insertLast(data){
this.insertAt(this.count, data);
}
/**
* ์ํ๋ ์ธ๋ฑ์ค์ ๋ฐ์ดํฐ๋ฅผ ์ญ์
* @param {number} index - ์ ๊ฑฐํ ์์น index
* @return {{data: number, next: {data: number, next: any} | null}} - ์ ๊ฑฐ๋ ๋
ธ๋์ ๋ฐ์ดํฐ์ ๊ทธ ๋ค์ ๋
ธ๋์ ๋ํ ์ ๋ณด.
*/
deleteAt(index){
// ์์ธ ์ฒ๋ฆฌ
if(index >= this.count || index < 0) throw new Error('์ ๊ฑฐํ ์ ์์ต๋๋ค.');
let currentNode = this.head;
if(index === 0){
// ๋ฆฌ์คํธ์ ๊ฐ์ฅ ์๋ถ๋ถ์ ์ ๊ฑฐํ ๊ฒฝ์ฐ
// ๋ฐํํ๊ธฐ ์ํด ์ญ์ ๋ Node๋ฅผ ์ ์ฅ
const deleteNode = this.head;
// head๋ฅผ ๋ค์ Node์ธ head.next๋ก ์ค์
this.head = this.head.next;
// ์ ๊ฑฐํ์ผ๋ฏ๋ก count๋ฅผ ๋ด๋ฆฐ๋ค.
this.count--;
// ์ญ์ ํ Node ๋ฐํ
return deleteNode;
}else{
// ๋ฆฌ์คํธ์ ๊ฐ์ฅ ์๋ถ๋ถ์ ์ ์ธํ ์์น๋ฅผ ์ ๊ฑฐํ ๊ฒฝ์ฐ
// ์ ๊ฑฐํ Node ์ด์ Node๊น์ง ์ํํด ์ ๊ฑฐํ Node์ ์ด์ Node๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ํ๋ค.
for(let i=0; i<index -1; i++){
currentNode = currentNode.next;
}
// currentNode.next๊ฐ ์ฐธ์กฐํ๊ณ ์๋ ๋ค์ Node ์ฆ, ์ ๊ฑฐํด์ผ ํ Node๋ฅผ ์ ์ฅ
let deleteNode = currentNode.next;
// ์ ๊ฑฐํ Node์ next Node๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ํ๋ค.
currentNode.next = currentNode.next.next;
// ์ ๊ฑฐํ์ผ๋ฏ๋ก count๋ฅผ ๋ด๋ฆฐ๋ค.
this.count--;
// ์ญ์ ํ Node ๋ฐํ
return deleteNode;
}
}
/**
* ๋ง์ง๋ง ๋ฐ์ดํฐ๋ฅผ ์ ๊ฑฐ
* @return {{data: number, next: {data: number, next: any} | null}} - ์ ๊ฑฐ๋ ๋
ธ๋์ ๋ฐ์ดํฐ์ ๊ทธ ๋ค์ ๋
ธ๋์ ๋ํ ์ ๋ณด.
*/
deleteLast(){
return this.deleteAt(this.count - 1);
}
/**
* ์ํ๋ ์ธ๋ฑ์ค์ ์๋ ๋ฐ์ดํฐ ์ฝ๊ธฐ
* @param {number} index - ์ฝ๊ณ ์ํ๋ Node์ index
* @return {{data: number, next: any}} - ํด๋น Node ๋ฐํ
*/
getNodeAt(index){
// ์์ธ ์ฒ๋ฆฌ
if(index >= this.count || index < 0) throw new Error('๋ฒ์๋ฅผ ๋์ด๊ฐ์ต๋๋ค.');
let currentNode = this.head;
// currentNode๊ฐ ํด๋น index๊น์ง ์ํํ๋ค.
for(let i=0; i< index ; i++){
currentNode = currentNode.next;
}
// ์ต์ข
์ ์ผ๋ก ์ด๋ํ Node๋ฅผ ๋ฐํ
return currentNode;
}
}
์ฐ๊ฒฐ ๋ฆฌ์คํธ(Linked List) ์ ์ถ์ ์๋ฃํ์ ์ ์ํ๊ณ , ์ด๊ฑธ ๋ฐํ์ผ๋ก ๊ตฌํํ ๋ค ๊ฐ ๋์์ ํ ์คํธํด๋ณด์๋ค.
- test.mjs
import { Node, LinkedList } from './LinikedList.mjs'
const list = new LinkedList();
console.log('===== insertAt() ๋ค์ฏ ๋ฒ ํธ์ถ =====');
list.insertAt(0,0); // 0๋ฒ์งธ ์์น์ ๋ฐ์ดํฐ 0 ์ฝ์
list.insertAt(1,1); // 1๋ฒ์งธ ์์น์ ๋ฐ์ดํฐ 1 ์ฝ์
list.insertAt(2,2); // 2๋ฒ์งธ ์์น์ ๋ฐ์ดํฐ 2 ์ฝ์
list.insertAt(3,3); // 3๋ฒ์งธ ์์น์ ๋ฐ์ดํฐ 3 ์ฝ์
list.insertAt(4,4); // 4๋ฒ์งธ ์์น์ ๋ฐ์ดํฐ 4 ์ฝ์
list.printAll(); // ๋ฐ์ดํฐ ๋ฆฌ์คํธ ์ถ๋ ฅ -> "[0, 1, 2, 3, 4]"
console.log('===== clear() ํธ์ถ =====');
list.clear(); // ๋ชจ๋ ๋ฐ์ดํฐ ์ ๊ฑฐ
list.printAll(); // ๋ฐ์ดํฐ ๋ฆฌ์คํธ ์ถ๋ ฅ -> "[]"
console.log('===== insertLast() ํธ์ถ =====');
list.insertLast(0); // ๋ง์ง๋ง ๋ฐ์ดํฐ ๋ค์ ๋ฐ์ดํฐ 0์ ์ฝ์
list.insertLast(1); // ๋ง์ง๋ง ๋ฐ์ดํฐ ๋ค์ ๋ฐ์ดํฐ 1์ ์ฝ์
list.insertLast(2); // ๋ง์ง๋ง ๋ฐ์ดํฐ ๋ค์ ๋ฐ์ดํฐ 2์ ์ฝ์
list.printAll(); // ๋ฐ์ดํฐ ๋ฆฌ์คํธ ์ถ๋ ฅ -> "[0, 1, 2]"
console.log('===== deleteAt() ํธ์ถ =====');
list.deleteAt(0); // 0๋ฒ์งธ index ์ ๊ฑฐ
list.printAll(); // ๋ฐ์ดํฐ ๋ฆฌ์คํธ ์ถ๋ ฅ, "[1, 2]"
list.deleteAt(1); // 0๋ฒ์งธ index ์ ๊ฑฐ
list.printAll(); // ๋ฐ์ดํฐ ๋ฆฌ์คํธ ์ถ๋ ฅ, "[1]"
console.log('===== deleteLast() ํธ์ถ =====');
list.insertLast(5); // ๋ง์ง๋ง ๋ฐ์ดํฐ ๋ค์ ๋ฐ์ดํฐ 5์ ์ฝ์
, "[1, 5]"
list.deleteLast(); // ๋ง์ง๋ง ๋ฐ์ดํฐ๋ฅผ ์ ๊ฑฐ
list.deleteLast(); // ๋ง์ง๋ง ๋ฐ์ดํฐ๋ฅผ ์ ๊ฑฐ
list.printAll(); // ๋ฐ์ดํฐ ๋ฆฌ์คํธ ์ถ๋ ฅ -> "[]"
console.log('===== getNodeAt() ํธ์ถ =====');
list.insertLast(1); // ๋ง์ง๋ง ๋ฐ์ดํฐ ๋ค์ ๋ฐ์ดํฐ 1์ ์ฝ์
list.insertLast(2); // ๋ง์ง๋ง ๋ฐ์ดํฐ ๋ค์ ๋ฐ์ดํฐ 2์ ์ฝ์
list.insertLast(3); // ๋ง์ง๋ง ๋ฐ์ดํฐ ๋ค์ ๋ฐ์ดํฐ 3์ ์ฝ์
list.insertLast(4); // ๋ง์ง๋ง ๋ฐ์ดํฐ ๋ค์ ๋ฐ์ดํฐ 4์ ์ฝ์
list.insertLast(5); // ๋ง์ง๋ง ๋ฐ์ดํฐ ๋ค์ ๋ฐ์ดํฐ 5์ ์ฝ์
, "[1, 2, 3, 4, 5]"
const secondNode = list.getNodeAt(2); // 2๋ฒ์งธ ์ธ๋ฑ์ค์ ์๋ ๋ฐ์ดํฐ ์ฝ๊ธฐ
console.log(secondNode); // Node { data: 3, next: Node { data: 4, next: Node { data: 5, next: null } }}
์ฅ์
๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํจ์จ์ ์ผ๋ก ์ฌ์ฉ ๊ฐ๋ฅ.
ํฌ๊ธฐ๊ฐ ์ ๋์ ์ด๋ฏ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ง์ด ์ถ๊ฐ/์ญ์ ํ ์ ์์.
์ฝ์
๊ณผ ์ญ์ ๊ฐ ๋ฐฐ์ด๋ณด๋ค ํจ์จ์ .
๋จ์
ํน์ ์์น์ ๋ฐ์ดํฐ๋ฅผ ์ฐพ๊ธฐ ์ํด์๋ ์ฒ์๋ถํฐ ์ฐจ๋ก๋๋ก ํ์ํด์ผ ํ๋ฏ๋ก ์ ๊ทผ ์๋๊ฐ ๋๋ฆผ.
๋
ธ๋๋ง๋ค ํฌ์ธํฐ๋ฅผ ์ ์ฅํด์ผ ํ๋ฏ๋ก ์ถ๊ฐ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ด ๋ฐ์ํจ.
์ด๋ ๊ฒ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋ฐฐ์ด๊ณผ ๋ฌ๋ฆฌ ๋ฐ์ดํฐ์ ์ฝ์
/์ญ์ ๊ฐ ๋น๋ฒํ ์ํฉ์์ ๋งค์ฐ ์ ์ฉํ๊ฒ ์ฐ์ด๋ ์๋ฃ๊ตฌ์กฐ๋ค.
'๐งช Computer science > Data Structure' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ Data Structure ] ๐ก ํ(Queue) (0) | 2025.01.02 |
---|---|
[ Data Structure ] ๐ฅ ์คํ(Stack) (0) | 2025.01.02 |