노드를 연결시킨 자료구조...
일단 그림을 보고 이해해보자
그림을 참고하면, data/text 하나가 노드이다. 그리고 연결된 것 처럼 다음 노드를 가리키고 있다. 저 화살표는 포인터를 의미한다고 한다.
특히, 제일 앞에 있는 노드는 헤드(head), 제일 끝 노드는 테일(tail)이라고 한다.
head와 tail의 data를 쓰지 않는다면, 추가, 삭제할 노드가 중간 노드인가 만 고려하면 된다.
// java
int[] newList = new int[size * 2];
for (int i = 0; i < size; i++)
newList[i] = list[i];
list = newList;
// js
let newList = new Array(size * 2);
for (let i = 0; i < size; i++)
newList[i] = list[i];
list = newList;
# python
newList = [0] * (size * 2)
for i in range(size):
newList[i] = list[i]
list = newList
해당 코드들은 메모리를 할당한 후 for 루프로 기존의 있던 값은 복사하는 것이다.
하지만 연결리스트는 다음 노드만 추가하면 끝.
- 데이터가 자주 추가되거나 가변적으로 자주 변하는 것이라면 연결리스트를 쓰는 것이 좋다.
- 데이터의 가변적이지 않은 변경이나 탐색을 위한 것이라면 배열을 쓰는 것이 좋다.
addFirst(list, data)
링크드리스트의 새로운 노드를 추가합니다. 가장 앞에 있는 노드(head의 다음)에 새로운 노드를 추가하는 연산입니다.addLast(list, data)
addFirst와 반대로 가장 뒤에 노드를 추가합니다.removeNode(list, data)
링크드리스트가 갖고 있는 노드 중에 data값을 갖고 있는 노드를 삭제합니다.searchNode(list,data)
링크드리스트에서 data의 값과 일치하는 노드를 검색합니다.printList()
링크드리스트를 전부 탐색합니다. 리스트의 데이터를 전부 보여줍니다.
가장 첫번째에 노드를 추가합니다. 가장 첫번째라고 해서 head 앞에 추가해서는 안됩니다. head의 다음 노드에 추가해야합니다.
head의 다음 노드를 새로운 노드로 가리키게 만들고, 그 새로운 노드는 이전에 head가 가리키고 있던 노드를 가리키면 됩니다.
//java
public void addFirst(List list, int data) {
Node newNode = new Node();
newNode.data = data;
newNode.next = list.head.next;
list.head.next = newNode;
list.size++;
}
//js
function addFirst(list, data) {
let newNode = {
data: data,
next: list.head.next
};
list.head.next = newNode;
list.size++;
}
가장 마지막(tail 앞)에 노드를 추가하는 연산입니다. 일단 tail앞까지 가야하지만, 그 전의 노드를 기억해야합니다. 그러니까 살짝 까다로울 수 있지요.
//java
public void addLast(List list, int data) {
Node last = list.head;
while (last.next != list.tail)
last = last.next;
Node newNode = new Node();
newNode.data = data;
newNode.next = list.tail;
last.next = newNode;
list.size++;
}
//js
function addLast(list, data) {
let last = list.head;
while (last.next !== list.tail)
last = last.next;
let newNode = {
data: data,
next: list.tail
};
last.next = newNode;
list.size++;
}
리스트의 노드를 하나씩 돌면서 data가 일치하면 그 노드를 삭제하는 겁니다.
주의할 점은 그 노드 다음 노드를 이전의 노드가 가리키는 작업이 우선적으로 이루어져야한다는 겁니다.
//java
public void removeNode(List list, int data) {
Node node = list.head;
while (node.next != list.tail) {
if (node.next.data == data) {
Node delNode = node.next;
node.next = delNode.next;
delNode.next = null;
list.size--;
return;
}
node = node.next;
}
System.out.println("데이터를 찾지 못했습니다.");
}
//js
function removeNode(list, data) {
let node = list.head;
while (node.next !== list.tail) {
if (node.next.data === data) {
let delNode = node.next;
node.next = delNode.next;
delNode.next = null;
list.size--;
return;
}
node = node.next;
}
console.log("데이터를 찾지 못했습니다.");
}
삭제 연산보다 쉽습니다. list를 돌면서 data와 값이 일치하면 그 노드를 반환하면 되니까요.
//java
public void removeNode(List list, int data) {
Node node = list.head;
while (node.next != list.tail) {
if (node.next.data == data) {
Node delNode = node.next;
node.next = delNode.next;
delNode.next = null;
list.size--;
return;
}
node = node.next;
}
System.out.println("데이터를 찾지 못했습니다.");
}
//js
function removeNode(list, data) {
let node = list.head;
while (node.next !== list.tail) {
if (node.next.data === data) {
let delNode = node.next;
node.next = delNode.next;
delNode.next = null;
list.size--;
return;
}
node = node.next;
}
console.log("데이터를 찾지 못했습니다.");
}
이 함수 역시 정말 쉽습니다. search 연산과 별 다를 것이 없죠. 그냥 list돌면서 하나하나 출력해주기만 하면 됩니다.
//java
public void printList(List list) {
Node node = list.head.next;
while (node != list.tail) {
System.out.println(node.data);
node = node.next;
}
}
//js
function printList(list) {
let node = list.head.next;
while (node !== list.tail) {
console.log(node.data);
node = node.next;
}
}
여기있는 코드를 모두 이해할 필요는 없다고 생각한다. 하지만 해당 자료구조가 어떤 원리로 동작하는지를 알게된다면, 80%는 성공한 것이라고 생각한다.
연결리스트와 배열에 대한 정의와 차이점에 대한 질문에 대해서 답변을 할 수 있다면 GOOD!!!
연결 리스트 (Linked List):
연결 리스트는 데이터 요소를 노드라는 개별적인 단위로 저장합니다.
각 노드는 데이터와 다음 노드를 가리키는 포인터 (또는 링크)로 이루어져 있습니다.
배열 (Array):
배열은 동일한 데이터 타입의 요소를 연속적으로 저장하는 선형 자료구조입니다.
인덱스를 사용하여 각 요소에 접근합니다.
주요 차이점: