Linked List(연결 리스트)

구현

1. 연결 리스트 

import java.util.Comparator;

//연결 리스트 클래스
public class LinkedList<E>{

	// Node클래스
	class Node<E>{
    	private E data;	// 데이터
        private Node<E> next;	// 다음 노드 참조
        
    	// Node클래스 생성자
    	Node(E data, Node<E> next){
    		this.data = data;
        	this.next = next;
    	}
        
    }
    
    
    private Node<E> head;	// 머리 포인터: 머리 노드를 가리킴
    private Node<E> crnt;	// 선택 포인터: 현재 선택한 노드를 가리킴

	//연결 리스트 생성자
	public LinkedList(){
    	//head: 빈 연결 리스트는 노드가 없고 head가 가리킬 곳도 없기 때문에 null을 넣음
        //crnt: 어떤 요소도 선택하지 않게 하기 위해 null을 넣음
    	head = crnt = null;
	}


	//검색, 삭제, 삽입 등의 메서드
}

 

2. 메서드 구현해보기(포인터 이용)

2-1. 검색 메서드

: 검색하는 노드 만날 때까지 머리 노드부터 순서대로 스캔

1) 매개변수

- E obj: 검색 시 키가 되는 데이터 넣어 둔 객체

- Comparator<? super E> c: obj와 노드 안의 데이터를 비교하기 위한 Comparator

     - Comparator<T>: 함수형 인터페이스로 int compare(T t1, T t2)메서드로 두 객체를 비교해 정수, 0, 또는 양수 반환

     - 와일드카드 ?: 제네릭에 들어올 수 있는 어떤 타입이든 지정할 때 쓰는 미지 타입

     - ? super E: 하한 경계로 E 타입 또는 E의 슈퍼타입을 의미

          ex) Comparator<Animal>은 Comparator<? super Dog>에 할당 가능

     => E 타입의 값과 비교할 수 있는 c면 뭐든 비교 허용

          ex) E가 Integer라면 Number, Object를 허용

 

2) 분석

      1. 스캔 노드 참조 변수 ptr을 head로 초기화 - 머리노드

      2. 스캔할 노드가 있는 지 확인

      3. 데이터 obj와 스캔 중인 노드의 데이터 ptr.data를 Comparator c로 비교

           3-1. compare 메서드가 0을 반환하면 종료 및 검색 성공     // 찾고자 하는 값 == 스캔 중인 노드의 값

           3-2. 선택 포인터가 ptr.data를 반환

      4. obj와 ptr.data가 일치하지 않으면 ptr에 ptr.next를 대입해 ptr이 다음 노드를 가리키도록 함

      5. 검색 실패 시 null 반환

3) 시간복잡도: O(n)

public E search(E obj, Comparator<? super E> c){
	Node<E> ptr = head;	//현재 스캔 중인 노드
    
    while(ptr != null){
    	if(c.compare(obj, ptr.data) == 0){	//검색 성공
        	crnt = ptr;
            return ptr.data;
        }
        ptr = ptr.next;	//다음 노드 선택
    }
    return null;	//검색 실패
}

 

2-2. 삽입 메서드

1) 머리에 노드 삽입하는 메서드

public void addFirst(E obj){
	Node<E> ptr = head;
    head = crnt = new Node<E>(obj, ptr);
}

 

2) 꼬리에 노드 삽입하는 메서드

      1. 리스트 스캔

      2-1) 리스트가 빈 경우: addFirst(obj);

      2-2) 리스트가 안 빈 경우: 리스트를 순회하여 ptr이 꼬리노드를 가리킬 때 반복문에서 나와 노드를 삽입한다.

public void addLast(E obj){
	if(head == null)
    	addFirst(obj);
    else{
    	Node<E> ptr = head;
        while(ptr.next != null)
        	ptr = ptr.next;
        ptr.next = crnt = new Node<E>(obj, null);
    }
}

 

 

2-3. 삭제 메서드

- 해제라고 생각하면 좋을 것 같다

1) 머리노드 삭제하는 메서드

public void removeFirst(){
	if(head != null)//리스트 안 빔
         head = crnt = head.next;
}

 

2) 꼬리노드 삭제하는 메서드

      1. 리스트 스캔

      2-1) 리스트에 노드가 1개인 경우: removeFirst();        //노드가 1개인 리스트라면 head에 null을 대입하면 빈 상태가 된다.

      2-2) 리스트에 노드가 2개 이상인 경우: pre가 꼬리 앞 노드를 ptr이 꼬리노드를 가리키면 pre의 next에 null을 대입한다.

public void removeLast(){
	if(head != null)
    	if(head.next == null)
        	removeFirst();
    else{
    	Node<E> ptr = head;
        Node<E> pre = head;	//ptr의 앞쪽 노드
        while(ptr.next != null){
        	pre = ptr;
        	ptr = ptr.next;
        }
        pre.next = null;
        crnt = pre;
    }
}

 

3) 선택한 노드 삭제하는 메서드

- 삭제할 노드 p가 머리 노드면 removeFirst()

public void remove(Node p){
	if(head != null){
    	if(head.next == null)
        	removeFirst();
        else{
            Node<E> ptr = head;

            while(ptr.next != p){
                ptr = ptr.next;
                if(ptr == null)//리스트에 p가 없음
                    return;
            }
            ptr.next = p.next
            crnt = ptr;
        }
    }
}

 

4) 모든 노드 삭제 메서드

- 머리노드 반복 삭제

public void clear(){
	while(head != null){
    	removeFirst();
    }
    crnt = null;
}

'CS > DataStructure&Algorithm' 카테고리의 다른 글

선형구조 - 큐  (1) 2025.04.30
선형구조 - 스택  (0) 2025.04.30
검색 알고리즘  (0) 2025.04.29
선형구조 - 순차 리스트  (1) 2025.04.23
자료구조  (0) 2025.04.23

+ Recent posts