Array
배열에 오버플로우가 발생하면 배열 크기를 2배로 확장
배열의 3/4이 비어 있다면 배열의 크기를 1/2로 축소
Singly Linked List
node 객체는 항목을 저장할 item과 Node 레퍼런스를 저장하는 next를 가진다.
public class Node <E> {
private E item;
private Node<E> next;
public Node(E newItem, Node<E> node){ // 생성자
item = newItem;
next = node;
}
// get set 메소드
public E getItem() {return item;}
public Node<E> getNext(){return next;}
public void setItem(E newItem) { item = newItem; }
public void setNext(Node<E> nextNode) { next = nextNode; }
}
public class SList <E> {
protected Node head; // 연결 리스트의 첫 노드를 가리킴
private int size;
public SList() { // 생성자
head = null;
size = 0;
}
}
원하는 노드가 나올 때까지 첫 노드부터 원하는 노드까지 순차적으로 탐색해야한다.
첫 노드의 item이 target 값과 같지 않다면 그 다음 노드를 p로 하여 p의 item이 target과 비교한다. 노드의 item이 target과 같을 때까지 반복한다. 모든 노드를 탐색하였는데 target 값이 없다면 -1을 리턴한다.
// 탐색
public int search(E target) {
Node p = head; // 첫 노드
for (int k = 0; k < size; k++){
if(target == p.getItem()){
return k; // 몇 번째 노드에 target 값이 있는 지를 반환
}
p = p.getNext(); // target 값과 같지 않다면 그 다음 노드를 p로
}
return -1; // 탐색 실패의 경우
}
1) 맨 앞에 새로운 노드에 삽입하는 경우
public void insertFront(E newItem) {
head= new Node(newItem, head);
size++;
}
2) p가 가리키는 노드의 다음에 삽입하는 경우
삽입하려는 노드의 next가 p의 next 노드를 가리키고, p의 next 를 새로 삽입하려는 노드를 가리키도록 수정한다.
newNode의 next -> 기존 p의 next
p의 next -> newNode
public void insertAfter(E newItem, Node p) {
p.setNext(new Node(newItem, p.getNext()));
size++;
}
1) 맨 앞의 노드 삭제하는 경우
맨 처음 노드를 가리키는 head를 맨 앞의 노드의 다음 노드로 설정한다.
public void deleteFront(){
if(isEmtpy()) throw new NoSuchElementException();
head = head.getNext();
size--;
}
2) p가 가리키는 노드의 다음 노드를 삭제하는 경우
p의 다음 노드의 next를 p의 next로 설정하고 삭제하려는 노드의 next를 null로 설정한다.
public void deleteAfter(Node p){
if(p == null ) throw new NoSuchElementException();
Node t = p.getNext();
p.setNext(t.getNext());
t.setNext(null);
size--;
}
Doubly Linked List
public class DNode <E>{
private E item;
private DNode previous; // 이전 노드
private DNode next; // 다음 노드
public DNode(E newItem, DNode p, DNode q){
item = newItem;
previous = p;
next = q;
}
//get, set 메소드
}
public class DList <E>{
protected DNode head, tail;
protected int size;
public DList() { // 생성자
head = new DNode(null, null, null);
tail = new DNode(null,head,null); //tail의 이전 노드를 head로 만든다
head.setNext(tail); //head의 다음 노드를 tail로 만든다
size = 0;
}
}
1) 특정 노드 앞에 삽입
public void insertBefore(DNode p, E newItem){
DNode t = p.getPrevious();
DNode newNode =new DNode(newItem, t, p);
t.setNext(newNode);
p.setPrevious(newNode);
size++;
}
2) 특정 노드 뒤에 삽입
// 특정 노드 뒤에 삽입
public void insertAfter(DNode p, E newItem){
DNode t = p.getNext();
DNode newNode =new DNode(newItem,p ,t );
t.setPrevious(newNode);
p.setNext(newNode);
size++;
}
public void delete(DNode x){
DNode f = x.getNext();
DNode r = x.getPrevious()
r.setNext(f);
f.setPrevious(r);
size --;
}
Circular Linked List
public class CList <E>{ // 생성자
private Node last; // 리스트의 마지막 노드를 가리킴
private int size;
public CList() {
last = null;
size=0;
}
}
last가 가리키는 노드의 다음에 새로운 노드를 삽입한다.
newNode - 새 항목을 저장할 새로운 노드 생성
리스트의 요소가 없다면 last는 null이고 last를 새 노드로 지정한다.
요소가 있다면 [ last -> 기존 last.next 노드 ]를 [ last -> 새로운 노드 -> 기존 last.next 노드 ]로 변경한다.
public void insert(E newItem){ // last가 가리키는 노드의 다음에 새노드 삽입
Node newNode = new Node(newItem, null); // 새 항목을 저장할 새로운 노드 생성
if(last == null){
newNode.setNext(newNode);
last = newNode;
}
else{
newNode.setNext(last.getNext()); //newNode의 다음 노드가 last가 가리키는 노드의 다음 노드가 되도록
last.setNext(newNode);
}
size++;
}
public Node delete(){ //last가 가리키는 노드의 다음을 제거
Node x = last.getNext(); //x는 리스트의 첫 노드
if(x==last){ // 리스트에 노드가 한 개만 있는 경우
last=null;
}
else{
last.setNext(x.getNext()); // last가 가리키는 노드의 다음노드가 x의 다음 노드임
x.setNext(null);
}
size--;
return x;
}
최악의 경우 수행시간 비교
양성봉 저,『자바와 함께하는 자료구조의 이해』, 생능출판사(2017)
자료구조 게시글은 모두 위 책을 참고하였습니다