CS/Data Structure

[DS] Array List, Linked List

pipes0512 2022. 7. 6. 21:56

ArrayList

가장 기본적인 자료구조이며, 논리적 저장 순서와 물리적 저장 순서가 동일한 자료구조

따라서 index로 해당 element에 빠르게 접근이 가능

장점

  • 찾고자하는 대상의 index를 알고있으면 O(1)의 매우 빠른 속도로 접근이 가능

단점

  • List의 Capacity를 늘릴경우 더 큰 Capacity의 새로운 List에 기존 element들을 모두 복사해야 함
  • java에서는 가변길이의 ArrayList가 이미 구현이 되어있지만, ArrayList를 직접 구현을 할 경우 가변 길이는 상황에 맞는 적절한 방법을 사용하여야함
  • ex) Default capacity와 number of entries가 같아 질 경우 Default capacity의 2배의 길이로 capacity를 늘림
  • 삭제 또는 삽입의 과정에서 삭제 또는 삽입의 대상이 되는 index보다 뒤에 있는 index의 element들을 앞으로 또는 뒤로 한 칸씩 shift하는 과정이 필요함 (비효율)
  • best-case : 맨 마지막 index에 삽입하거나 삭제하는 case : O(1)
  • worst-case : 맨 처음 index에 삽입하거나 삭제하는 case :O(n)
  • 따라서 ArrayList의 삭제 혹은 삽입의 time-complexity는 O(n)으로 오래걸림

 

 

 

LinkedList

각각의 Node들이 Link를 통해 자신 다음에 어떤 Node인지 기억하고있는 방식의 자료구조

장점

  • 데이터 입력시 주소가 순차적이지 않아 element를 메모리의 어느곳에나 둘 수 있음 (크기가 동적)
  • 삽입, 삭제 시 link가 가리키는 주소만 바꿔주면 되기 때문에 element 삽입, 삭제가 용이

단점

  • 원하는 요소를 찾기위해서는 link를 하나하나 타면서 모든 Node를 확인해야하기 때문에 접근속도가 느림 : O(n)
  • 결국 삽입, 삭제를 할 때에도 원하는 위치에 가기 위해서는 Node를 하나하나 확인해야하기 때문에 결국 복잡도는 O(n)

 

이렇게 보면 LinkedList는 장점이 별로 없는 것 같지만 다른 자료구조의 근간이 되는 개념이기 때문에 매우 중요함

 

LinkedList의 종류

1.  Singly Linked List (단순 연결 리스트)

     단방향 링크

     이전 노드에 접근하기 위해서는 첫 번째 노드부터 다시 순회해야함

2. Circular Linked List (원형 연결 리스트)

     단방향 링크

     마지막 노드와 첫 번째 노드가 연결된 원형 구조

     이전 노드에 접근하기 위해서 계속 한방향으로 순회하면 됨

3. Doubly Linked List (이중 연결 리스트)

     양방향 링크

     각 노드가 앞 뒤로 연결됨

     이전 노드에 직접 접근 가능

 

ArrayList를 사용한 Bag 구현 예시

public class ArrayBag <T> implements BagInterface <T> {
	
	private  T [] bag;
	private static final int DEFAULT_CAPACITY = 25;
	private int numberOfEntries;
	
	public ArrayBag () {
		this (DEFAULT_CAPACITY);
	} // default constructor
	
	public ArrayBag (int capacity) {
		numberOfEntries = 0;
		T [] tempBag = (T []) new Object [capacity];
		bag = tempBag;
		
	} // constructor with given initial capacity
	
	
	public boolean add(T newEntry) {
		boolean result = true;
		if (isFull()) {
			result = false;
		}
		else {
			bag[numberOfEntries] = newEntry;
			numberOfEntries++;
		}
		return result;
	}
	
	public boolean isFull() {
		return numberOfEntries == bag.length;
	}
	
	public T[] toArray() {
		T[] result = (T[])new Object[numberOfEntries];
		for (int index = 0; index < numberOfEntries; index++) {
			result[index] = bag[index];
		} 
		return result;	
	} //bag자체의 레퍼런스를 그대로 return 하면 다른사람이 주소에 직접 접근을 하는 문제가 생길 수 있다. 
	  //따라서 copy를 만들어 return 하는것이 좋다.
	
	public boolean isEmpty() {
		return numberOfEntries == 0;
	}
	
	public int getCurrentSize() {
		return numberOfEntries;
	}
	
	public int getFrequencyOf(T anEntry) {
		int counter = 0;
		
		for (int index = 0; index < numberOfEntries; index++) {
			if (anEntry.equals(bag[index])){
				counter++;
			}
		}
		return counter;
	}
	
	public boolean contains(T anEntry) {
		boolean found = false;
		
		for (int index = 0; !found && (index < numberOfEntries); index++) {
			if (anEntry.equals(bag[index])) {
				found = true;
			}
		}
		return found;
	}
	
	public void clear() {
		numberOfEntries = 0;
	} //numberOfEntires가 0이 되어도 array자체는 메모리에 남아있다. 하지만 나중에 GC가 collect하기 때문에 상관없음 

	public T remove() {
		T result = null;
		if (numberOfEntries >0) {
			result = bag[numberOfEntries -1];
			bag[numberOfEntries -1] = null;
			numberOfEntries--; //특정 entry를 지우는 것이 아닌 마지막 index에 위치한 entry 삭제 
		}
		return result;
	}
	
	public boolean remove(T anEntry) {
		boolean result = false;
		
		for (int index = 0; index<numberOfEntries; index++) {
			if (anEntry.equals(bag[index])) {
				bag[index] = null;
				result = true;
			}
		}
		return result;
	} //remove된 entry보다 뒤에 있는 entry 들을 한 칸씩 shift해주고 numberOfEntrie--하는 구현이 추가적으로 필요함 
}

LinkedList를 사용한 Bag 구현 예시

public class LinkedBag <T> {
	
	int numberOfEntries = 0;
	Node <T> firstNode = new Node <T> (null);
	
	public boolean add(T newEntry) {
		Node <T> newNode = new Node <T> (newEntry); 
		newNode.next = firstNode; //newNode가 전에 있던 firstNode를 가리키게 함 
		
		firstNode = newNode; //newNode가 새로운 firstNode가 됨 
		numberOfEntries++;
		
		return true;
	}
	
	public T[] toArray() {
		
		T[] result = (T[])new Object[numberOfEntries];
		
		int index = 0;
		Node <T> currentNode = firstNode;
		
		while ((index < numberOfEntries)&&(currentNode != null)) {
			result[index] = currentNode.data;
			index++;
			currentNode = currentNode.next;
		}
		return result;
	}
	
	public int getFrequencyOf(T anEntry) {
		
		int frequency = 0;
		int counter = 0;
		Node <T> currentNode = firstNode;
		
		while ((counter < numberOfEntries)&&(currentNode != null)) {
			if (anEntry.equals(currentNode.data)) {
				frequency++;
			}
			counter++;
			currentNode = currentNode.next;
		}
		
		return frequency;
	}
	
	public boolean contains (T anEntry) {
		boolean found = false;
		Node <T> currentNode = firstNode;
		
		while (!found && (currentNode != null)) {
			if (anEntry.equals(currentNode.data)) {
				found = true;
			} else {
				currentNode = currentNode.next;
			}
		}
		
		return found;
	}
	
	public T remove () {
		T result = null;
		if (firstNode != null) {
			result = firstNode.data;
			firstNode = firstNode.next; // firstNode의 다음 Node를 firstNode로 만들면서 기존 firstNode는 GC가 collect해가게 함 
			numberOfEntries--;
		}
		
		return result;
	}
	
	private Node <T> getReferenceTo(T anEntry){
		boolean found = false;
		Node <T> currentNode = firstNode;
		
		while(!found && (currentNode != null)) {
			if (anEntry.equals(currentNode.data)) {
				found = true;
			} else {
				currentNode = currentNode.next;
			}
		}
		return currentNode;
	}
	
	public boolean isEmpty() {
		
		return numberOfEntries == 0;
	}
	
	public void clear() {
		while (!isEmpty()) {
			remove();
		}
	}
}

class Node <T> {
	public T data; //entry
	public Node next; // link to next node
	
	public Node (T dataPortion) {
		this (dataPortion, null);
	}
	public Node (T dataPortion, Node nextNode) {
		data = dataPortion;
		next = nextNode;
	}
}

reference

Carrano-Data Structures and Abstractions with Java 3rd Edition

https://coding-factory.tistory.com/551

'CS > Data Structure' 카테고리의 다른 글

[DS] Recursion(재귀)  (0) 2022.07.13
[DS] Stack  (0) 2022.07.08
[DS] Time Complexity (시간 복잡도)  (0) 2022.07.07
[DS] 추상 자료형(ADT, Abstract Data Type)  (0) 2022.07.05