์ฐ๊ฒฐ ๋ฆฌ์คํธ(Linked List)
์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋จ์ด์ง ๊ณต๊ฐ์ ์๋ ๋ฐ์ดํฐ๋ค์ ํฌ์ธํฐ๋ฅผ ์ด์ฉํ์ฌ ์ฐ๊ฒฐ๋์ด ์๋ ์๋ฃ๊ตฌ์กฐ์ด๋ค. ๋ฐฐ์ด์ ์์ฐจ์ ์ผ๋ก ์ฐ๊ฒฐ๋์ด ์๋ ๊ณต๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ๋ ์๋ฃ๊ตฌ์กฐ์ฌ์ ๋ฐฐ์ด๊ณผ๋ ๋ค๋ฅด๋ค.
์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋ ธ๋๋ก ์ด๋ฃจ์ด์ ธ ์๋๋ฐ, ์ฌ๊ธฐ์ ๋ ธ๋๋ ๋ฐ์ดํฐ์ ํฌ์ธํฐ๋ฅผ ๋ด๊ณ ์๋ ๊ณต๊ฐ ๋จ์์ด๋ค.
ํฌ์ธํฐ๋ ๋ค์ ๋ ธ๋์ ์ฃผ์ ๊ฐ์ ์ ์ฅํ๋ ๊ณต๊ฐ์ด๋ค.
์ฅ์
- ๋ฏธ๋ฆฌ ๊ณต๊ฐ์ ํ ๋นํ์ง ์์๋ ๋จ
๋จ์
- ์ฐ๊ฒฐ์ ์ํ ๋ณ๋ ๊ณต๊ฐ์ด ํ์ํ๋ฏ๋ก, ์ ์ฅ๊ณต๊ฐ ํจ์จ์ด ์ข์ง ์์
- ์ฐ๊ฒฐ ์ ๋ณด๋ฅผ ์ฐพ๋ ์๊ฐ์ด ํ์ํ๋ฏ๋ก ์ ๊ทผ ์๋๊ฐ ๋๋ฆผ
- ์ค๊ฐ ๋ฐ์ดํฐ ์ญ์ ์, ์ ๋ค ๋ ธ๋์ ์ฐ๊ฒฐ์ ์ฌ๊ตฌ์ฑํด์ผ ํ๋ ๋ถ๊ฐ์ ์ธ ์์ ์ด ํ์
์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ์ง์ ๊ตฌํํด๋ณด๋ฉฐ ์ฅ,๋จ์ ์ ์ดํด๋ณด๊ณ ์๊ฐ ๋ณต์ก๋์ ๋ํด์๋ ์์๋ณด์
๊ตฌํ
IList ์ธํฐํ์ด์ค๋ฅผ ์์ฑํ์ฌ ๊ตฌํ์ ํ์ํ ๋ฉ์๋๋ฅผ ์๋์ ๊ฐ์ด ์ ์ํ๋ค.
IList ์ธํฐํ์ด์ค
public interface IList<E> {
void add(E e); //๋ฐ์ดํฐ ์ถ๊ฐ
void insert(int index, E e); //index ์์น์ ๋ฐ์ดํฐ ์ถ๊ฐ
void clear(); //๋ฐ์ดํฐ ๋ชจ๋ ์ญ์
boolean delete(E e); //ํด๋น ๋ฐ์ดํฐ ์ญ์
boolean deleteByIndex(int index); //index ์์น์ ์๋ ๋ฐ์ดํฐ ์ญ์
E get(int index); //index ์์น์ ์๋ ๋ฐ์ดํฐ ๋ฐํ
int indexOf(E e); //ํด๋น ๋ฐ์ดํฐ index ๋ฐํ
boolean isEmpty(); //๋ฆฌ์คํธ์ ๋ฐ์ดํฐ๊ฐ ์๋์ง ์๋์ง ๋ฐํ
int size();
}
ํด๋น ์ธํฐํ์ด์ค๋ฅผ implementsํ์ฌ MyLinkedList ํด๋์ค๋ฅผ ์์ฑํ์ฌ ํด๋น ํด๋์ค์ ๊ตฌํํด๋ณด์.
MyLinkedList ํด๋์ค
public class MyLinkedList<E> implements IList<E> {
private int size;
private Node head;
public MyLinkedList() {
this.size = 0;
this.head = new Node(null);
}
private class Node {
E data;
Node next;
Node(E data) {
this.data = data;
}
Node(E data, Node next) {
this.data = data;
this.next = next;
}
}
}
ํด๋น ์์ค๋ฅผ ๋ณด๋ฉด ๋ด์ฅ ํด๋์ค๋ก Node๊ฐ ์๋๋ฐ ์ด๊ฒ์ด ์์์ ์ค๋ช ํ ๋ ธ๋ ์ญํ ์ ํด์ค ํด๋์ค๋ค.
์์์ ์ค๋ช ํ๋ฏ์ด ๋ ธ๋๋ ๋ฐ์ดํฐ์ ๋ค์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ๊ฐ ์๋ค๊ณ ํ๋ค. ๊ทธ๋์ ์ ๋ค๋ฆญ ํ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ด๋ data ๋ณ์, ๋ค์ ๋ ธ๋์ ์ฐ๊ฒฐํ Node ํ์ ์ next ๋ณ์๋ก ๊ตฌ์ฑํ๋ค.
๊ทธ๋ฆฌ๊ณ MyLinkedList ํด๋์ค์ 2๊ฐ์ ํ๋๊ฐ ์๋๋ฐ ํ๋๋ ํด๋น ๊ฐ์ฒด์ ๋ด๊ธด ๋ฐ์ดํฐ์ ๊ฐฏ์๋ฅผ ๋ฐํํ size, ์์ ๋ ธ๋๋ฅผ ๋ด์ head๊ฐ ์๋ค.
๊ทธ ๋ค์, ์ด์ ์ธํฐํ์ด์ค์์ ์ ์ํ ์ถ์ ๋ฉ์๋๋ค์ ๊ตฌํํด๋ณด์.
add(E e) ๋ฉ์๋
์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ์ฒ์ ๊ฐ์ ์ถ๊ฐํ ๋, ๋ ธ๋๋ฅผ ์์ฑํด์ head์ ํฌ์ธํฐ์ ์์ฑํ ๋ ธ๋๋ฅผ ์ฐ๊ฒฐํด์ค์ผ ํ๋ค.
๊ทธ ๋ค์ ๊ฐ์ ์ถ๊ฐ ํ๋ค๋ฉด ์ ์ ์ถ๊ฐํ ๋ ธ๋์ ์๋ก ์์ฑํ ๋ ธ๋๋ฅผ ์ฐ๊ฒฐํด์ค์ผ ํ๋ค.
๊ทธ๋์ add ๋ฉ์๋๋ฅผ ์๋์ ๊ฐ์ด ๊ตฌํํ๋ค.
@Override
public void add(E e) {
Node curr = this.head;
while (curr.next != null) {
curr = curr.next;
}
Node node = new Node(e);
curr.next = node;
size++;
}
curr์ head๋ฅผ ์ฒ์์ ๋์ ํด์ฃผ๊ณ , while์ ํตํด ๋ค์ ๋ ธ๋๊ฐ null์ผ ๋๊น์ง ๊ณ์ ๋ ธ๋๋ค์ ์ํํด์ค๋ค. ๊ทธ๋์ curr์๋ ๋งจ ๋ง์ง๋ง ๋ ธ๋๊ฐ ๋์ ๋ ๊ฒ์ด๋ค.
๊ทธ๋ค์ ์ถ๊ฐํ ๋ ธ๋์ธ node ๋ณ์๋ฅผ ํ ๋นํ๋ค.
๊ทธ๋ฆฌ๊ณ ๋งจ ๋ง์ง๋ง ๋ ธ๋์ ํฌ์ธํฐ ์ญํ ์ธ next์ node๋ฅผ ๋ฃ์ด์ค์ผ๋ก์จ ์์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ๋ ธ๋ ๊ฐ์ ์ฐ๊ฒฐ์ด ์ด๋ฃจ์ด์ง๋ค.
(size++์ ๋ ธ๋ ์ถ๊ฐ๋์์ผ๋ก ์ฆ๊ฐ)
insert(int index, E e) ๋ฉ์๋
์ค๊ฐ์ ๋ ธ๋๋ฅผ ์ถ๊ฐํ๋ค๋ฉด, ์ ๋ค ๋ ธ๋๋ฅผ ์ฌ์ฐ๊ฒฐ ํด์ค์ผ ํ๋ค. ์์ ๊ทธ๋ฆผ์ ๋ณด๋ฉด ์ ์ ์๋ฏ์ด, ๊ธฐ์กด์ Prev์ Curr๊ฐ ์๋ก ์ฐ๊ฒฐ๋์ด ์๋ค๊ฐ ์ฌ์ด์ insert๋ฅผ ํ๋ค๋ฉด Prev์ ๋ค์ ๋ ธ๋๋ ์๋ก ์ถ๊ฐ๋ ๋ ธ๋๊ฐ, ๊ทธ๋ฆฌ๊ณ ์๋ก ์ถ๊ฐ๋ ๋ ธ๋์ ๋ค์ ๋ ธ๋๊ฐ Curr๋ก ๋ณ๊ฒฝ๋์ด์ผ ํ๋ค๋ ๊ฒ์ด๋ค.
๊ทธ๋์ ์๋์ ๊ฐ์ด ๊ตฌํํ๋ค.
@Override
public void insert(int index, E e) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException();
Node prev = this.head;
Node curr = prev.next;
int i = 0;
while (i++ < index) {
prev = prev.next;
curr = curr.next;
}
Node node = new Node(e, curr);
prev.next = node;
size++;
}
clear() ๋ฉ์๋
@Override
public void clear() {
this.size = 0;
this.head.next = null;
}
clear ๋ฉ์๋๋ ๋ ธ๋์ ์ฐ๊ฒฐ์ ๋์ด์ฃผ๋ฉด ๋๋ค. ๊ทธ๋์ ๋งจ ์ฒ์ ๋ ธ๋์ธ head์ ๋ค์ ๋ ธ๋๋ฅผ null๋ก ๋ฐ๊ฟ ์ฐ๊ฒฐ์ ๋์ด์คฌ๋ค.
delete(E e) ๋ฉ์๋
delete๋ ์ค๊ฐ ๋ ธ๋๊ฐ ์ญ์ ๋ ์ ์์ผ๋ฏ๋ก insert ๋ฉ์๋์ ๊ฐ์ด prev, curr ๋ ธ๋ ๋๊ฐ๊ฐ ํ์ํ๋ค.
๊ทธ๋์ curr ๋ ธ๋์ ๋ฐ์ดํฐ๊ฐ ๋งค๊ฐ๋ณ์์ ๊ฐ์ผ๋ฉด prev์ ๋ค์ ๋ ธ๋๋ฅผ curr์ ๋ค์ ๋ ธ๋๋ก ์ฐ๊ฒฐํ๊ณ , curr์ ๋ค์ ๋ ธ๋๋ฅผ null๋ก ์ฐ๊ฒฐํ์ฌ ๋์ด์ค๋ค.
@Override
public boolean delete(E e) {
Node prev = this.head;
Node curr = prev.next;
while (curr != null) {
if (curr.data.equals(e)) {
prev.next = curr.next;
curr.next = null;
size--;
return true;
}
prev = prev.next;
curr = curr.next;
}
return false;
}
deleteByIndex(int index) ๋ฉ์๋
@Override
public boolean deleteByIndex(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException();
Node prev = this.head;
Node curr = prev.next;
int i = 0;
while (i++ < index) {
prev = prev.next;
curr = curr.next;
}
prev.next = curr.next;
curr.next = null;
size--;
return true;
}
delete ๋ฉ์๋์ ๊ฐ๋ ์ ๊ฐ์ผ๋ฏ๋ก ์ฝ๋๋ง ์ฒจ๋ถํด๋ ๋ ๊ฒ ๊ฐ๋ค.
๊ธฐํ ๋ฉ์๋
๋๋จธ์ง get์ด๋ indexOf ๋ฑ ๊ธฐํ ๋ฉ์๋๋ค์ ๋ ธ๋ ๊ฐ์ ์ฐ๊ฒฐ์ ์ฌ๊ตฌ์ฑํ๋ ๊ฒ ํ์์์ด์ ์ถ๊ฐ, ์ญ์ ๋ฅผ ์ดํดํ๋ค๋ฉด ์ฝ๋๋ง ๋ด๋ ์ดํดํ ์ ์์ ๊ฒ์ด๋ค.
@Override
public E get(int index) {
Node curr = this.head;
int i = 0;
while (i++ < index) {
curr = curr.next;
}
return curr.data;
}
@Override
public int indexOf(E e) {
Node curr = this.head;
int i = 0;
while (curr != null) {
if (curr.data.equals(e)) {
return i;
}
curr = curr.next;
i++;
}
return -1;
}
@Override
public boolean isEmpty() {
return this.size == 0;
}
@Override
public int size() {
return size;
}
๊ตฌํ์ ํด๋ณธ ๊ฒฐ๊ณผ, ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋ฐ์ดํฐ ์ถ๊ฐ, ์ญ์ ์ ๋์ ๋ ธ๋๊ฐ ๋งจ ์์ด๋ผ๋ฉด O(1)์ ์๊ฐ๋ณต์ก๋๋ฅผ ๊ทธ๊ฒ ์๋๋ผ๋ฉด O(n)์ ์๊ฐ๋ณต์ก๋๋ฅผ ๊ฐ๊ฒ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฒ์ ์ญ์ ์ํ๋ฅผ ํด์ผํ๋ฏ๋ก O(n)์ ์๊ฐ๋ณต์ก๋๋ฅผ ๊ฐ๊ฒ ๋๋ค.
์๊ฐ๋ณต์ก๋
- ์ถ๊ฐ, ์ญ์ : O(1), O(n)
- ๊ฒ์ : O(n)
'๐ ์๋ฃ๊ตฌ์กฐ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[์๋ฃ๊ตฌ์กฐ] 05. ํด์ฌ ํ ์ด๋ธ(Hash Table) (0) | 2023.06.19 |
---|---|
[์๋ฃ๊ตฌ์กฐ] 03. ์คํ(Stack) (0) | 2023.06.07 |
[์๋ฃ๊ตฌ์กฐ] 02. ํ(Queue) (0) | 2023.06.01 |
[์๋ฃ๊ตฌ์กฐ] 01. ๋ฐฐ์ด (0) | 2023.06.01 |