์ฐ๊ฒฐ ๋ฆฌ์คํธ, ๋งํฌ๋ ๋ฆฌ์คํธ(linked list)๋ ๊ฐ ๋ ธ๋๊ฐ ๋ฐ์ดํฐ์ ํฌ์ธํฐ๋ฅผ ๊ฐ์ง๊ณ ํ ์ค๋ก ์ฐ๊ฒฐ๋์ด ์๋ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ์๋ฃ ๊ตฌ์กฐ์ด๋ค. ์ด๋ฆ์์ ๋งํ๋ฏ์ด ๋ฐ์ดํฐ๋ฅผ ๋ด๊ณ ์๋ ๋ ธ๋๋ค์ด ์ฐ๊ฒฐ๋์ด ์๋๋ฐ, ๋ ธ๋์ ํฌ์ธํฐ๊ฐ ๋ค์์ด๋ ์ด์ ์ ๋ ธ๋์์ ์ฐ๊ฒฐ์ ๋ด๋นํ๊ฒ ๋๋ค.
๊ณ ๊ตฌ๋ง ์ค๊ธฐ
โ ๊ณ ๊ตฌ๋ง ์ค๊ธฐ๋ผ๊ณ ์๊ฐํด๋ณด๊ธฐ. ์ฒ์ ์์ ๋ถ๋ถ๋ง ์๊ณ ์๋ค, ๊ทธ ์์ ๋ถ๋ถ์ ํ๊ณ ๋ค์ด๊ฐ๋ค ๋ณด๋ฉด ๊ณ ๊ตฌ๋ง(data)๊ฐ ๊ณ์ ์ค์ค์ด ๋์จ๋ค. ์์(์ฃผ์) - ์ฐ๊ฒฐ(link) - ๋(null pointer or circular)
์์ ์์๊ฐ ์กด์ฌํจ์ ๊ธฐ์ตํ๊ธฐ.
๋ ธ๋(Node)์ ๋งํฌ(Link)๋ก ๊ตฌ์ฑ๋๋ฉฐ, ๋ ธ๋๋ ์ค์ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋ ํ๋์ ๋จ์์ด๊ณ , ๋งํฌ๋ ๋ ธ๋๊ฐ์ ์์น์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ ์์ด ์ฐ๊ฒฐ๋ฆฌ์คํธ์ ์์๋ฅผ ์ ์งํ ์ ์๋๋ก ํ๋ ์ฐ๊ฒฐ๊ณ ๋ฆฌ๋ผ ํ ์ ์๋ค.
๋ ธ๋์ ์์์ ์ head, ๋์ ์ tail์ด๋ผ ๋ถ๋ฅด๋ฉฐ ๋ ธ๋์ ์ถ๊ฐ, ์ญ์ , ํ์์ด ๊ฐ๋ฅํ๋ค.
๋ฐฐ์ด๋ฆฌ์คํธ
์ฅ์
๋จ์
์ฐ๊ฒฐ ๋ฆฌ์คํธ
ํ์๊ณผ ์ ๋ ฌ์ ์์ฃผ ํ๋ค๋ฉด ๋ฐฐ์ด ๋ฆฌ์คํธ
์ถ๊ฐ์ ์ญ์ ๊ฐ ๋ง๋ค๋ฉด ์ฐ๊ฒฐ ๋ฆฌ์คํธ
์ฐ์๋๋ ํญ๋ชฉ๋ค์ด ํฌ์ธํธ๋ก ์ฐ๊ฒฐ๋์ด ์๋ค.
๋ง์ง๋ง ํญ๋ชฉ์ Null์ ๊ฐ๋ฆฌํค๊ณ ์์. (๋ง์ง๋ง์ด๋ผ ์ฐ๊ฒฐํ ๋ ธ๋๊ฐ ์๊ธฐ ๋๋ฌธ)
ํ๋ก๊ทธ๋จ์ด ์ํ๋๋ ๋์ ํฌ๊ธฐ๊ฐ ๋์ ์ผ๋ก ์ปค์ง๊ฑฐ๋ ์์์ง.
๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ ๋ญ๋น๊ฐ ์ ์ง๋ง ํฌ์ธํฐ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํ์ํจ.
๋ฐฐ์ด์ ๋นํด ๋ฐ์ดํฐ์ ์ถ๊ฐ์ ์ฝ์ ์ ์ฉ์ด.
๋จ๋ฐฉํฅ(์๋ฐฉํฅ์ด๋ผ๋) ์์ฐจ์ ์ผ๋ก ํ์ํ์ง ์์ผ๋ฉด ์์์ ์ ๊ทผ์ด ๋ถ๊ฐํ๊ธฐ ๋๋ฌธ์ ํ์ ์๋๊ฐ ๋จ์ด์ง.
๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ๋ ๊ฑด ๊ฐ์ฒด ํ ๋น์.
๋งํฌ๋ฅผ ๋์ด ๋ฒ๋ฆฌ๋ฉด ๋ฐ์ดํฐ๊ฐ ์ญ์ ๋๊ธฐ ๋๋ฌธ์ (JS๊ธฐ์ค) ๋ง์ฝ head์์ ๋ ธ๋๋ฅผ ์ ์ฒด ์ญ์ ํ๊ณ ์ถ๋ค๋ฉด head์ ์๋ ๋งํฌ๋ฅผ ๋์ด ๋ฒ๋ฆฌ๊ธฐ๋ง ํ๋ฉด ๋๋ค.
์์ ์ด๋ฏธ์ง๋ฅผ ์ฝ๋๋ก ๋ณธ๋ค๋ฉด.
head: {0: 'apple', next: {1: 'banana', next: {2: 'dream', next: null}}}}
tail: {2: 'dream', next: null}
data2๋ฅผ ์ญ์ ํด ์ฃผ๋ ๊ฒ์ด ์๋๋ผ, data1์ ๋งํฌ๋ฅผ 2๊ฐ ์๋ 3์ผ๋ก ๋ค์ ์ฐ๊ฒฐ์ ํด์ฃผ๋ฉด data2๋ head์์ ์๋์ผ๋ก ๋น ์ง๊ฒ๋์ด ์์ด์ง๋ค. ์ถ๊ฐ๋ ๋ง์ฐฌ๊ฐ์ง์ด๋ค. 1๊ณผ 3 ์ฌ์ด์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ๊ฒ ๋๋ค๋ฉด 1์ ๋งํฌ๋ฅผ 3์ด์๋ ๋ฃ์ผ๋ ค๋ ๋ฐ์ดํฐ์ ์ฐ๊ฒฐํ๊ณ , ๋ฃ์ผ๋ ค๋ ๋ฐ์ดํฐ๋ฅผ 3์ผ๋ก ์ฐ๊ฒฐํด์ฃผ๋ฉด๋๋ค.
Singly linked list (์ผ๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ)
์ง๊ธ๊น์ง ์์ ์ค๋ช
๋ค์ด ๋ฐ๋ก ์ผ๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ด๋ค. ์ผ๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋
ธ๋์ ํฌ์ธํฐ(๋ค์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ๋งํฌ)๊ฐ ํ ๊ฐ์ธ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ธ๋ฐ, ์ด ๋ฆฌ์คํธ์ ์ฅ์ ์ ๋
ธ๋๋น ํฌ์ธํฐ ๋ฐ์ดํฐ๋ฅผ 4๋ฐ์ดํธ๋ง ์ฐจ์งํด์ ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ณด๋ค ๋ฐ์ดํฐ๋ฅผ ์๋ ์ ์๋ค๋ ์ ์ด๋ค. ๋ค๋ง ์ผ๋ฐฉํฅ์ด๊ธฐ ๋๋ฌธ์ ํ์ฌ ๋
ธ๋๋ ์ด์ ๋
ธ๋๋ก ๋์๊ฐ๋ ๋ฒ์ ๋ชจ๋ฅธ๋ค. ์ค์ง ์ง์ง๋ง์ด ์์ ๋ฟ.
Doubly linked list (์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ)
๋ ธ๋์ ํฌ์ธํฐ๊ฐ ๋ ๊ฐ ์๋ ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ธ๋ฐ, ์ผ๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋๊ฐ์ง๋ง ์์ ๋งํ ๊ฒ์ฒ๋ผ ๋ ธ๋์ ํฌ์ธํฐ๊ฐ ๋ ๊ฐ ์๋ค๋ ์ ์ด ๋ค๋ฅด๋ค ์ด ๋ ๊ฐ์ ํฌ์ธํฐ๋ ์ ๊ณผ ํ๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์๊ธฐ ๋๋ฌธ์ ์ผ๋ฐฉํฅ๊ณผ๋ ๋ฌ๋ฆฌ ์ด์ ์ผ๋ก ๊ฐ ์๋, ์ดํ๋ก๋ ๊ฐ ์๋ ์๋ค. ํฌ์ธํฐ๊ฐ ๋ ๊ฐ๊ฐ ์๊ฒผ์ผ๋ ๋ฐ์ดํฐ๋ ๋ ๋ฐฐ๋ก ๋จน๋๋ค. 8๋ฐ์ดํธ๋ฅผ ์ฐจ์งํฉ๋๋ค.
Circular linked list (ํํ ์ฐ๊ฒฐ ๋ฆฌ์คํธ)
์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ์๋ ํค๋์ ํ ์ผ์ด ๋ถ์ฌ์ ธ ์์ด, ์์ ๋ชจ์๊ณผ ๊ฐ๋ค๊ณ ํ์ฌ ํํ ๋ฆฌ์คํธ์ด๋ค. ํ ์ผ์ ํฌ์ธํฐ๊ฐ null์ ๊ฐ๋ฆฌํค๊ณ ์๋ ๊ฒ์ด ์๋ head๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์๋ ๊ฒ์ธ๋ฐ, ๋ ธ๋ 6 ๋ฒ์ ์๋ค๊ฐ 4 ๋ฒ์ผ๋ก ๊ฐ์ผ ๋๋ค๋ฉด, ์ผ๋ฐฉํฅ ๋ฆฌ์คํธ๋ ๋ค์ ์์ํด์ผ ๋์ง๋ง ํํ ๋ฆฌ์คํธ๋ 7, 8, 9, 10์ ์ง๋ ๋ค์ 0, 1, 2, 3, 4๋ก ๊ฐ ์ ์๋ค ์ฆ ์ํํ ๋ ์ข์ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ด๋ค.
LinkedList - Java ๊ตฌํ - Data Structure (์๋ฃ๊ตฌ์กฐ)
//์ฝ๋๋ egoing๋ ๊ฐ์ ์ฐธ์ดํ๋ฉฐ ์ค์ตํ์ต๋๋ค.
package com.hajni.lib;
import java.nio.channels.FileLockInterruptionException;
import java.util.ListIterator;
public class LinkedList {
private Node head; // ๋๊ฐ ์ฒซ๋ฒ์งธ์ธ๊ฐ.
private Node tail; // ์ ์ผ ๋์ ์๋๊ฐ.
private int size = 0;
private class Node {
private Object data; // ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋ ํ๋
private Node nexe; // ๋ค์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํ๋.
public Node(Object input) { // Node๊ฐ ์์ฑ๋์ด์์๋ ๊ฐ์ง๊ณ ์๋ ๊ฐ์ด input์ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ
this.data = input;
this.nexe = null;
}
public String toString() { // ๋
ธ๋์ ๋ด์ฉ์ ์ถ๋ ฅํด์ ํ์ธํ ์ ์๋ ๊ธฐ๋ฅ
return String.valueOf(this.data);
}
}
// ์ฒ์์ ์ถ๊ฐ
public void addFirst(Object input) {
Node newNode = new Node(input);
newNode.nexe = head; // ์๋ก์ด ๋
ธ๋์ ๋ค์ ๋
ธ๋๋ฅผ head์ง์
head = newNode; // head๋ก ์๋ก์ด ๋
ธ๋๋ฅผ ์ง์
size++;
if (head.nexe == null) {
tail = head;
}
}
// ๋์ ์ถ๊ฐ
public void addLast(Object input) {
Node newNode = new Node(input);
if (size == 0) {
addFirst(input);
} else {
/**
* ๋ง์ง๋ง ๋
ธ๋(tail)์ ๋ค์ ๋
ธ๋(next)๊ฐ ์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ํ๊ณ
* tail์ด ๊ฐ๋ฆฌํค๋ ๋
ธ๋๋ฅผ ์ ๋
ธ๋๋ก ๋ฐ๊ฟ์ค๋ค.
*/
tail.nexe = newNode;
tail = newNode;
size++;
}
}
// ๋
ธ๋ ์ถ๊ฐํ๊ธฐ ์ ํน์ ์์น ๋
ธ๋ ์ฐพ์๋
Node node(int index) {
Node x = head;
// x = x.nexe; -> ๋ง์ฝ index100๋ฒ์งธ๋ฅผ ๊ฐ์ ธ์ค๋ ค๋ฉด x 100 ์ํด์ผํ๋ค = ๋ฐ๋ณต๋ฌธ์ฌ์ฉํด์ผํจ.
for (int i = 0; i < index; i++) {
x = x.nexe;
}
return x;
}
// ํน์ ์์น ๋
ธ๋ ์ถ๊ฐ ๋ฉ์๋
public void add(int k, Object input) {
if (k == 0) {
addFirst(input);
} else {
Node temp1 = node(k - 1);
Node temp2 = temp1.nexe;
Node newNode = new Node(input);
/**
* ์ด์ ๋
ธ๋๊ฐ ๊ฐ๋ฆฌํค๋ ๋
ธ๋๋ฅผ ๋์ ๋ค
* ์ ๋
ธ๋๋ก ๋ณ๊ฒฝํด์ค๋ค.
* ๋ํ ์ ๋
ธ๋๊ฐ ๊ฐ๋ฆฌํค๋ ๋
ธ๋๋ temp2๋ก
* ์ค์ ํด์ค๋ค.
*/
temp1.nexe = newNode;
newNode.nexe = temp2;
size++;
if (newNode.nexe == null){
tail = newNode;
}
}
}
// ๋ฆฌ์คํธ ํ์ธ ์ฝ๋
public String toString(){
if (head == null){
return "[]";
}
Node temp = head;
String str = "[";
while(temp.nexe != null){
str += temp.data + " , ";
temp = temp.nexe;
}
str += temp.data;
return str + "]";
}
// ์ฒซ๋ฒ์งธ ๋
ธ๋ ์ญ์
public Object removeFirst(){
Node temp = head;
head = head.nexe;
Object returnData = temp.data; // ๋ฐ์ดํฐ ์ญ์ ์ ๋ฆฌํดํ ๊ฐ์ ์์ ๋ณ์์ ๋ด๋๋ค.
temp = null;
size--;
return returnData;
}
// ์ค๊ฐ ๋
ธ๋ ์ญ์
public Object remove(int k){
if (k == 0){
return removeFirst();
}
Node temp = node(k - 1); // ์ญ์ ํ ๋
ธ๋์ ์ด์ ๋
ธ๋
Node todoDeleted = temp.nexe; // ์ญ์ ํ ๋
ธ๋
temp.nexe = temp.nexe.nexe; // ์ญ์ ํ ๋
ธ๋์ ๋ค์ ๋
ธ๋
Object returnData = todoDeleted.data; // ์ญ์ ๋๋ ๋
ธ๋์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๊ธฐ ์ํ ์์๋ณ์
if (todoDeleted == tail){
tail = temp;
}
todoDeleted = null;
size--;
return returnData;
}
public Object removeLast(){
return remove(size - 1); //
}
public int size(){
return size;
}
public Object get(int k){
Node temp = node(k);
return temp.data;
}
public Object indexOf(Object data){
Node temp = head;
int index = 0;
while (temp.data != data){
temp = temp.nexe;
index++;
if (temp == null){
return -1; // ์ฐพ๊ณ ์ ํ๋ ์์๋ฅผ ์ฐพ์ง ๋ชปํ์ ๊ฒฝ์ฐ -1 ๋ฐํ
}
}
return index;
}
public ListIterator listIterator() {
return new ListIterator();
}
class ListIterator{
private Node lastReturned;
private Node next;
private int nextIndex;
ListIterator(){
next = head;
nextIndex = 0;
}
public Object next(){
lastReturned = next;
next = next.nexe;
nextIndex++;
return lastReturned.data;
}
public boolean hasNext(){
return nextIndex < size();
}
public void add(Object input){
Node newNode = new Node(input);
if (lastReturned == null){
// ์ฒ์์์น์ ๋
ธ๋๋ฅผ ์ถ๊ฐํ๋ ใ
๋
head = newNode;
newNode.nexe = next;
}else {
// ์ค๊ฐ์ ์ถ๊ฐํ๋ ์ฝ๋
lastReturned.nexe = newNode;
newNode.nexe = next;
}
lastReturned = newNode;
nextIndex++;
size++;
}
public void remove(){
if (nextIndex == 0){
throw new IllegalStateException();
}
LinkedList.this.remove(nextIndex - 1);
nextIndex--;
}
}
}