๐Ÿ’ป Knowledge/์ž๋ฃŒ๊ตฌ์กฐ

๐Ÿง‘๐Ÿป‍๐Ÿ’ป Singly LinkedList ์ง์ ‘ ๊ตฌํ˜„ (JAVA)

ming412 2023. 9. 21. 12:29

1. Singly LinkedList ์ž๋ฃŒ๊ตฌ์กฐ

https://ming412.tistory.com/157

 

Array vs LinkedList ํŠน์ง• & ์„ฑ๋Šฅ ๋น„๊ต

Array (๋ฐฐ์—ด) ํŠน์ง• - ๊ฐ™์€ ํƒ€์ž…์˜ ์—ฌ๋Ÿฌ ๋ณ€์ˆ˜๋ฅผ ํ•˜๋‚˜์˜ ๋ฌถ์Œ์œผ๋กœ ๋‹ค๋ฃจ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ - ๋ฌผ๋ฆฌ์ ์œผ๋กœ ์—ฐ์†์ ์ธ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์— ์ €์žฅ๋˜๋ฉฐ ํฌ๊ธฐ๊ฐ€ ๊ณ ์ •๋˜์–ด ์žˆ๋‹ค. ์‹œ๊ฐ„ ๋ณต์žก๋„ ์ ‘๊ทผ(Access) - ๋ฐฐ์—ด์€ ๋ฌด์ž‘์œ„ ์ ‘

ming412.tistory.com

 

2. Singly LinkedList ์ง์ ‘ ๊ตฌํ˜„ํ•˜๊ธฐ

1) ADT (Abstract Data Type) ์ •์˜

- ๋ฐ์ดํ„ฐ (Data)

    - Node

        - data: ๋ฐ์ดํ„ฐ

        - next: ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ์ฐธ์กฐ

    - MySinglyLinkedList

        - head: ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์˜ ์ฒ˜์Œ ์š”์†Œ๋ฅผ ์ฐธ์กฐ

        - size: ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์˜ ๊ธธ์ด

 

- ์ž‘์—… (Operation)

    - search(idx): ํŠน์ • ์œ„์น˜์˜ ๋…ธ๋“œ ๋ฐ˜ํ™˜

    - addFirst(e): ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ ๋งจ ์•ž์— ๋…ธ๋“œ ์ถ”๊ฐ€

    - addLast(e): ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ ๋งจ ๋งˆ์ง€๋ง‰์— ๋…ธ๋“œ ์ถ”๊ฐ€

    - add(idx, e): ํŠน์ • ์œ„์น˜์— ๋…ธ๋“œ ์ถ”๊ฐ€

    - get(idx): ํŠน์ • ์œ„์น˜์˜ ๋…ธ๋“œ์˜ ๊ฐ’ ๋ฐ˜ํ™˜

    - remove(idx): ํŠน์ • ์œ„์น˜์˜ ์š”์†Œ ์‚ญ์ œ

 

2) Node ํด๋ž˜์Šค ์ •์˜

data ๋ณ€์ˆ˜๋กœ ๊ฐ’์„ ์ €์žฅํ•˜๊ณ , next๋กœ ๋‹ค์Œ ๋…ธ๋“œ์˜ ์ฃผ์†Œ๋ฅผ ์ฐธ์กฐํ•œ๋‹ค.

public class Node<E> {
	public E data; // ๋ฐ์ดํ„ฐ
	public Node<E> next; // ๋‹ค์Œ ๋…ธ๋“œ์˜ ์ฃผ์†Œ

	public Node(E data) {
		this.data = data;
		this.next = null;
	}
}

 

3) MySinglyLinkedList ํด๋ž˜์Šค ์ •์˜

์ง์ ‘ ๊ตฌํ˜„ํ•œ ๋‹จ์ผ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ๋Š” head ํฌ์ธํ„ฐ๋กœ ์ฒซ ๋ฒˆ์งธ ๋…ธ๋“œ์˜ ์ฃผ์†Œ๋ฅผ ์ฐธ์กฐํ•˜๊ณ , size ๋ณ€์ˆ˜๋กœ ๋ฆฌ์ŠคํŠธ์˜ ์ „์ฒด ๊ธธ์ด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

public class MySinglyLinkedList<E> {
	private Node<E> head;
	private int size;

	public MySinglyLinkedList() {
		this.head = null;
		this.size = 0;
	}
}

 

4) search ๊ตฌํ˜„

search๋Š” add์™€ remove์—์„œ ์‚ฌ์šฉ๋  ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ์ด๋‹ค.

add์™€ remove๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”, ๋จผ์ € ์ถ”๊ฐ€/์‚ญ์ œํ•  ์š”์†Œ๋ฅผ ํƒ์ƒ‰ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— search ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜๋ณต์ ์œผ๋กœ ์žฌ์‚ฌ์šฉ๋  ๊ฒƒ์ด๋‹ค.

public Node<E> search(int idx) {
    Node<E> cur = head;
    for (int i=0; i<idx; i++) {
        cur = cur.next;
    }
    return cur;
}

 

5) add ๊ตฌํ˜„

addFirst - ๋ฆฌ์ŠคํŠธ์˜ ๋งจ ์ฒ˜์Œ์— ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

์ด๋•Œ head๊ฐ€ null์ด ์•„๋‹Œ ๊ฒฝ์šฐ๋Š” ๋ฆฌ์ŠคํŠธ์— ๋‹ค๋ฅธ ์›์†Œ๊ฐ€ ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์ƒํƒœ์ด๋‹ค.

์ด๋•Œ๋Š” head๋ฅผ ๊ฐฑ์‹ ํ•˜๊ธฐ ์ „์—, ์ƒˆ๋กœ์šด ๋…ธ๋“œ์˜ next์— ๊ธฐ์กด head๋ฅผ ๋Œ€์ž…ํ•˜์—ฌ ๋‘˜์„ ๋ฏธ๋ฆฌ ์—ฐ๊ฒฐํ•ด ๋†“์•„์•ผ ํ•œ๋‹ค. 

public void addFirst(E e) {
    Node<E> newNode = new Node<>(e);
    if (head != null) {
        // ์ƒˆ๋กœ์šด ๋…ธ๋“œ์™€ ๊ธฐ์กด ์ฒซ ๋ฒˆ์งธ ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐ
        newNode.next = head;
    }
    // head๋ฅผ ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋กœ ๊ฐฑ์‹ 
    head = newNode;
    size++;
}

 

addLast - ๋ฆฌ์ŠคํŠธ์˜ ๋งจ ๋์— ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

๋ฆฌ์ŠคํŠธ๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด, ์•ž์„œ ๋งŒ๋“ค์—ˆ๋˜ search ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ์˜ ๋งจ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๋ฅผ ์ฐพ๋Š”๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ทธ ๋…ธ๋“œ์™€ ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐํ•œ๋‹ค.

 

๋งŒ์•ฝ ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋ฉด head๋ฅผ ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋กœ ๊ฐฑ์‹ ํ•œ๋‹ค.

public void addLast(E e) {
    Node<E> newNode = new Node<>(e);
    if (head != null) {
        // ๋งจ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๋ฅผ ์ฐพ๊ธฐ
        Node<E> lastNode = search(size - 1);
        // ๋งจ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ์™€ ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐ
        lastNode.next = newNode;
    } else {
        head = newNode;
    }
    size++;
}

 

add - ๋ฆฌ์ŠคํŠธ์˜ ํŠน์ • ์œ„์น˜์— ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

์šฐ์„ , ์ถ”๊ฐ€ ์œ„์น˜(idx)๋ฅผ ๊ฒ€์ฆํ•œ๋‹ค.

idx๊ฐ€ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ ์‚ฌ์ด์ฆˆ๋ณด๋‹ค ํด ๋•Œ์—๋Š” ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  idx๊ฐ€ 0์ด๊ฑฐ๋‚˜ size์ผ ๋•Œ๋Š” ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘” addFirst์™€ addLast๋ฅผ ํ™œ์šฉํ•œ๋‹ค.

 

idx๊ฐ€ 0๋˜๋Š” size๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด,

search ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ๋ฐ”๋กœ ์•ž ๋…ธ๋“œ(prev)๋ฅผ ์ฐพ๊ณ , ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ์™€ prev์˜ ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ๋จผ์ € ์—ฐ๊ฒฐํ•ด์•ผ ํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  prev์˜ ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•  ๋…ธ๋“œ๋กœ ๊ฐฑ์‹ ํ•œ๋‹ค.

public void add(int idx, E e) {
    Node<E> newNode = new Node<>(e);
    if (idx > size || idx < 0) {
        throw new IndexOutOfBoundsException();
    }
    else if (idx == 0) {
        addFirst(e);
    }
    else if (idx == size) {
        addLast(e);
    } else {
        // ๋ฐ”๋กœ ์•ž ๋…ธ๋“œ๋ฅผ ์ฐพ๊ธฐ
        Node<E> prevNode = search(idx - 1);
        // ์ƒˆ๋กœ์šด ๋…ธ๋“œ์™€ prev์˜ next ์—ฐ๊ฒฐ
        newNode.next = prevNode.next;
        // prev์˜ next ๊ฐฑ์‹ 
        prevNode.next = newNode;
    }
}

 

6) remove ๊ตฌํ˜„

ํŠน์ • ์œ„์น˜์˜ ๋…ธ๋“œ๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค๋Š” ๊ฒƒ์€, ๊ทธ ๋…ธ๋“œ์˜ ์—ฐ๊ฒฐ์„ ๋Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด ์ œ๊ฑฐํ•  ๋…ธ๋“œ์˜ ์•ž ๋…ธ๋“œ์™€ ์ œ๊ฑฐํ•  ๋…ธ๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

์ œ๊ฑฐํ•  ๋…ธ๋“œ์˜ ์•ž ๋…ธ๋“œ์™€ ์ œ๊ฑฐํ•  ๋…ธ๋“œ์˜ ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ์„œ๋กœ ์—ฐ๊ฒฐํ•ด์ฃผ๋ฉด ์ œ๊ฑฐํ•  ๋…ธ๋“œ๋Š” ์—ฐ๊ฒฐ์ด ๋Š์–ด์ง€๊ฒŒ ๋œ๋‹ค.

public void remove(int idx) {
    if (idx >= size || idx < 0) {
        throw new IndexOutOfBoundsException();
    } else {
        // ๋ฐ”๋กœ ์•ž ๋…ธ๋“œ๋ฅผ ์ฐพ๊ธฐ
        Node<E> prevNode = search(idx - 1);
        // ์ œ๊ฑฐํ•  ๋…ธ๋“œ๋ฅผ ์ฐพ๊ธฐ
        Node<E> targetNode = search(idx);
        // ๋ฐ”๋กœ ์•ž ๋…ธ๋“œ์™€ ์ œ๊ฑฐํ•  ๋…ธ๋“œ์˜ ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐ
        prevNode.next = targetNode.next;
    }
}

 

7) get ๊ตฌํ˜„

get ํ•จ์ˆ˜๋Š” ํŠน์ • ์œ„์น˜์˜ ๋…ธ๋“œ๋ฅผ ์ฐพ์•„ ๊ทธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋œ๋‹ค.

๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘” search ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜๋ฉด ๋˜๊ณ , idx์˜ ๋ฒ”์œ„๊นŒ์ง€ ๊ฒ€์ฆํ•˜์ž.

public E get(int idx) {
    if (idx >= size || idx < 0) {
        throw new IndexOutOfBoundsException();
    }
    return search(idx).data;
}

 

8) toString ์˜ค๋ฒ„๋ผ์ด๋”ฉ

์•„๋ž˜์ฒ˜๋Ÿผ toString์„ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜๋ฉด ๋””๋ฒ„๊น…ํ•˜๊ธฐ ์ข‹๋‹ค.

@Override
public String toString() {
    Node<E> cur = head;
    while (cur != null) {
        System.out.print(cur.data + " ");
        cur = cur.next;
    }
    System.out.println();
    return "MySinglyLinkedList{" +
        "head.data=" + head.data +
        ", size=" + size +
        '}';
}

 

9) ์ „์ฒด ์ฝ”๋“œ

public class MySinglyLinkedList<E> {
	private Node<E> head;
	private int size;

	public MySinglyLinkedList() {
		this.head = null;
		this.size = 0;
	}

	public Node<E> search(int idx) {
		Node<E> cur = head;
		for (int i=0; i<idx; i++) {
			cur = cur.next;
		}
		return cur;
	}

	public void addFirst(E e) {
		Node<E> newNode = new Node<>(e);
		if (head != null) {
			// ์ƒˆ๋กœ์šด ๋…ธ๋“œ์™€ ๊ธฐ์กด ์ฒซ ๋ฒˆ์งธ ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐ
			newNode.next = head;
		}
		// head๋ฅผ ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋กœ ๊ฐฑ์‹ 
		head = newNode;
		size++;
	}

	public void addLast(E e) {
		Node<E> newNode = new Node<>(e);
		if (head != null) {
			// ๋งจ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๋ฅผ ์ฐพ๊ธฐ
			Node<E> lastNode = search(size - 1);
			// ๋งจ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ์™€ ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐ
			lastNode.next = newNode;
		} else {
			head = newNode;
		}
		size++;
	}

	public void add(int idx, E e) {
		Node<E> newNode = new Node<>(e);
		if (idx > size || idx < 0) {
			System.out.println("Index: " + idx + ", Size: " + size);
		}
		else if (idx == 0) {
			addFirst(e);
		}
		else if (idx == size) {
			addLast(e);
		} else {
			// ๋ฐ”๋กœ ์•ž ๋…ธ๋“œ๋ฅผ ์ฐพ๊ธฐ
			Node<E> prevNode = search(idx - 1);
			// ์ƒˆ๋กœ์šด ๋…ธ๋“œ์™€ prev์˜ next ์—ฐ๊ฒฐ
			newNode.next = prevNode.next;
			// prev์˜ next ๊ฐฑ์‹ 
			prevNode.next = newNode;
		}
	}

	public void remove(int idx) {
		if (idx >= size || idx < 0) {
			throw new IndexOutOfBoundsException();
		} else {
			// ๋ฐ”๋กœ ์•ž ๋…ธ๋“œ๋ฅผ ์ฐพ๊ธฐ
			Node<E> prevNode = search(idx - 1);
			// ์ œ๊ฑฐํ•  ๋…ธ๋“œ๋ฅผ ์ฐพ๊ธฐ
			Node<E> targetNode = search(idx);
			// ๋ฐ”๋กœ ์•ž ๋…ธ๋“œ์™€ ์ œ๊ฑฐํ•  ๋…ธ๋“œ์˜ ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐ
			prevNode.next = targetNode.next;
		}
	}

	public E get(int idx) {
		if (idx >= size || idx < 0) {
			throw new IndexOutOfBoundsException();
		} else {
			return search(idx).data;
		}
	}

	@Override
	public String toString() {
		Node<E> cur = head;
		while (cur != null) {
			System.out.print(cur.data + " ");
			cur = cur.next;
		}
		System.out.println();
		return "MySinglyLinkedList{" +
			"head.data=" + head.data +
			", size=" + size +
			'}';
	}
}
public class Main {
	public static void main(String[] args) {
		MySinglyLinkedList<String> linkedList = new MySinglyLinkedList<>();
		linkedList.addFirst("A");
		linkedList.addLast("B");
		linkedList.addLast("C");
		System.out.println(linkedList.toString());

		linkedList.add(0, "D");
		linkedList.add(4, "E");
		System.out.println(linkedList.toString());

		linkedList.remove(3);
		System.out.println(linkedList.toString());
	}
}

์‹คํ–‰ ๊ฒฐ๊ณผ