연결 리스트
자료 구조 목차
- Data-Structure
- Linear
- Static
- Array
- Dynamic
- Linked List
- Stack
- Queue
- Static
- Non Linear
- Tree
- Graph
- Linear
저번에 배열에 대해서 알아보았는데 이제는 선형 자료 구조 중 동적인 연결 리스트에 대해서 알아보자
배열과 동일하게 연결 리스트도 선형 자료 구조이다. 다만 배열과 다른 점은 연결 리스트의 각 데이터는 연속된 주소에 저장되는 것이 아니다.
각 엘레멘드가 포인터를 사용하여 연결되어 있는 것이다.
연결 리스트 사용 이유
동일한 타입의 데이터는 배열을 통해서도 저장할 수 있지만 배열은 아래와 같이 몇가지의 제한사항이 있다.
- 배열의 크기는 고정임으로 배열 생성시 제한을 어디에 둘지 알아야한다. 또한 제한을 둔 곳까지 사용하지 않더라도 메모리에는 할당이 되어있다.
- 배열에 요소를 삽입하는데 많은 비용이 들 수 있다.
예를 들면id[] = [1000, 1010, 1050, 2000, 2040]
이 있고 오름차순을 지키며 새로운 ID로 1005를 삽입하고자 한다면 1000을 제외한 나머지를 옮겨야한다.
삭제 또한 마찬가지이다.
배열과 비교했을때 장점
- 동적 사이즈
- 쉬운 삽입 및 삭제
단점
- 랜덤 엑세스가 불가함. 첫 번째 노드부터 접근할 수 있음. 그르므로 바이너리 서치에는 연결 리스트를 사용하는 것이 효율적이지 않음
- 각 요소에 추가적으로 포인터를 위한 추가 메모리 공간이 필요함.
- 캐시 친화적이지 않음. 배열의 요소들은 연속적인 위치임으로 ‘참조 지역성의 원리(Locality of reference)’이지만 연결 리스트는 그렇지 않음
Linked List 생성
import java.util.Arrays;
import java.util.LinkedList;
public class LinkedListSample1 {
public static void main(String[] args) {
LinkedList<Integer> integerLinkedList1 = new LinkedList<Integer>(); // 타입 지정
LinkedList<Integer> integerLinkedList2 = new LinkedList<>(); // 타입 생략 가능
LinkedList<Integer> integerLinkedList3 = new LinkedList<>(integerLinkedList1); // 다른 Collection값으로 초기화
LinkedList<Integer> integerLinkedList4 = new LinkedList<>(Arrays.asList(1, 2, 3, 4, 5)); // Arrays.asList()로 초기화
}
}
위와 같이 여러가지 방법으로 Linked List를 생성할 수 있다.
Linked List 엘레멘트 추가/변경
import java.util.LinkedList;
public class LinkedListSample2 {
public static void main(String[] args) {
LinkedList<String> colors = new LinkedList<>();
// add() method를 이용하여 추가
colors.add("Black");
colors.add("White");
colors.add(0, "Green"); // index : 0에 Green을 추가
colors.add("Red");
// set() method
colors.set(1, "Blue"); // index : 1에 위치한 값을 Blue로 변경
System.out.println(colors);
}
}
인덱스 없이 요소만 적었을 시에 인덱스 끝에 삽입된다. add() 메서드에서 인덱스를 사용했을 시 해당 인덱스에 추가된 값이 있다면 해당 값은 다음 인덱스로 밀려나도 추가로 적은 값이 해당 인덱스에 들어간다.
Linked List 엘레멘트 삭제
import java.util.Arrays;
import java.util.LinkedList;
public class LinkedListSample3 {
public static void main(String[] args) {
LinkedList<String> colors = new LinkedList<>(Arrays.asList("Black", "White", "Green", "Red"));
String removedColor = colors.remove(0); // 해당 인덱스 값을 제거하고 제거도니 값 리턴
System.out.println("Removed color is " + removedColor);
colors.remove("White"); // 값이 White와 동일한 것을 삭제
System.out.println(colors);
colors.clear(); // LinkedList 전체 삭제
System.out.println(colors);
}
}
LinkedList 전체 값 확인
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
public class LinkedListSample4 {
public static void main(String[] args) {
LinkedList<String> colors = new LinkedList<>(Arrays.asList("Black", "White", "Green", "Red"));
// for-each loop
for (String color : colors) {
System.out.print(color + "\t");
}
System.out.println();
// for loop
for (int i=0; i<colors.size(); ++i) {
System.out.print(colors.get(i) + "\t");
System.out.println();
}
System.out.println();
// using iterator
Iterator<String> iterator = colors.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + "\t");
}
System.out.println();
// using listiterator
ListIterator<String> listIterator = colors.listIterator(colors.size());
while (listIterator.hasPrevious()) {
System.out.print(listIterator.previous() + "\t");
}
System.out.println();
}
}
Linked List는 여기까지만 적고 스택으로 넘어가도록 하겠다.
추후에 이 밖에도 Circular Linked List 또는 Double Linked List에 대해서도 정리하겠다.