Skip to content

Commit

Permalink
Merge pull request #11 from Seogeurim/DataStructure/Seogeurim
Browse files Browse the repository at this point in the history
Data structure/seogeurim
  • Loading branch information
KimKwon authored Jan 31, 2021
2 parents d6f9535 + 6c33819 commit 1f36e0b
Show file tree
Hide file tree
Showing 5 changed files with 339 additions and 1 deletion.
25 changes: 24 additions & 1 deletion contents/data-structure/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,14 @@ String[] name = {"Stacy", "Tracy", "Dorothy"};

### Linked List 구현

- [Singly Linked List](./code/LinkedList/SinglyLinkedList.java)
- [Doubly Linked List](./code/LinkedList/DoublyLinkedList.java)
- 위 코드 실행 : [LinkedListExample.java](./code/LinkedList/LinkedListExample.java)

### Linked List 시간 복잡도

- 데이터 조회 : O(n)
- **맨 앞/뒤에** 데이터 삽입/삭제하기 : O(1)
- **맨 앞/뒤에** 데이터 삽입/삭제하기 : O(1) (SinglyLinkedList의 경우 맨 뒤의 데이터 삭제 연산은 O(n))
- **중간의 원하는 위치에** 데이터 삽입/삭제하기 : O(n) _(원하는 원소까지 데이터를 조회하는 과정이 있으므로 O(n) + O(1))_

---
Expand Down Expand Up @@ -314,6 +318,25 @@ class Trie {

## 질의응답

<details>
<summary>Array와 Linked List를 그 차이점을 이용해 설명해봅시다.</summary>

- 데이터 접근 속도
- Array는 인덱스를 통한 Random Access를 지원하므로 시간 복잡도 O(1)로 빠르게 찾을 수 있다.
- LinkedList는 순차 접근 방식을 사용하므로 시간 복잡도 O(N)이 걸린다.
- 데이터의 삽입/삭제 속도
- Array는 데이터를 중간이나 맨 앞에 삽입/삭제하는 경우 shift가 필요하므로 데이터가 많을수록 비효율적이다.
- LinkedList는 중간 삽입/삭제는 똑같이 O(N)의 시간 복잡도를 갖지만, 맨 앞 또는 뒤에 삽입할 경우 O(1)의 시간복잡도를 갖는다.
- 다만 LinkedList는 데이터 삽입/삭제마다 메모리 할당/해제가 일어나므로 시간복잡도는 빠를지라도 시스템 콜(System Call)에 있어서 Array보다 더 시간이 걸린다.
- 메모리 할당
- Array는 정적 메모리 할당이 이루어진다. (Compile time)
- LinkedList는 동적 메모리 할당이 이루어진다. (Runtime)
- Array의 경우 데이터 삽입 시 모든 공간이 다 차버렸다면 새로운 메모리 공간이 필요하지만 LinkedList는 동적으로 할당받을 수 있다.

데이터 삽입/삭제가 빈번하다면 LinkedList를 사용하는 것이 좋고, 데이터 접근 속도가 중요하다면 Array를 사용하는 것이 좋다.

</details>

<details>
<summary>스택으로 큐를 구현할 수 있을까요?</summary>
네, 2개의 스택을 이용하여 구현할 수 있습니다. Enqueue 연산은 첫번째 스택에 원소를 추가하면 됩니다. Dequeue 연산은 두번째 스택을 이용합니다. 우선 두번째 스택이 비어있다면 첫번째 스택이 빌 때까지 첫번째 스택의 원소를 pop하고 두번째 스택에 push하는 것을 반복합니다. 그리고 두번째 스택이 비어있지 않다면 두번째 스택의 원소를 pop하면 됩니다.
Expand Down
128 changes: 128 additions & 0 deletions contents/data-structure/code/LinkedList/DoublyLinkedList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package LinkedList;

public class DoublyLinkedList<E> implements ILinkedList<E> {
private Node<E> header;
private Node<E> trailer;
private int size;

public DoublyLinkedList() {
header = new Node<>(null, null, null);
trailer = new Node<>(null, header, null);
header.setNext(trailer);
size = 0;
}

@Override
public int size() {
return size;
}

@Override
public boolean isEmpty() {
return size == 0;
}

@Override
public E first() {
if (isEmpty()) return null;
return header.getNext().getElement();
}

@Override
public E last() {
if (isEmpty()) return null;
return trailer.getPrev().getElement();
}

@Override
public void addFirst(E e) {
addBetween(e, header, header.getNext());
}

@Override
public void addLast(E e) {
addBetween(e, trailer.getPrev(), trailer);
}

@Override
public E removeFirst() {
if (isEmpty()) return null;
return remove(header.getNext());
}

@Override
public E removeLast() {
if (isEmpty()) return null;
return remove(trailer.getPrev());
}

@Override
public String toString() {
if (isEmpty()) return "[]";

StringBuilder sb = new StringBuilder("[");
DoublyLinkedList.Node<E> current = header.getNext();
while (current.getNext() != trailer) {
sb.append(current.getElement()).append(", ");
current = current.getNext();
}
sb.append(current.getElement()).append("]");
return sb.toString();
}

private void addBetween(E e, Node<E> predecessor, Node<E> successor) {
Node<E> newest = new Node<>(e, predecessor, successor);
predecessor.setNext(newest);
successor.setPrev(newest);
size ++;
}

private E remove(Node<E> node) {
Node<E> predecessor = node.getPrev();
Node<E> successor = node.getNext();
predecessor.setNext(successor);
successor.setPrev(predecessor);
size --;
return node.getElement();
}

private static class Node<E> {
private E element;
private Node<E> prev;
private Node<E> next;

public Node() {
this(null, null, null);
}

public Node(E element, Node<E> prev, Node<E> next) {
this.element = element;
this.prev = prev;
this.next = next;
}

public E getElement() {
return element;
}

public void setElement(E element) {
this.element = element;
}

public Node<E> getPrev() {
return prev;
}

public void setPrev(Node<E> prev) {
this.prev = prev;
}

public Node<E> getNext() {
return next;
}

public void setNext(Node<E> next) {
this.next = next;
}
}
}
16 changes: 16 additions & 0 deletions contents/data-structure/code/LinkedList/ILinkedList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package LinkedList;

public interface ILinkedList<E> {

public int size();
public boolean isEmpty();

public E first();
public E last();

public void addFirst(E e);
public void addLast(E e);

public E removeFirst();
public E removeLast();
}
46 changes: 46 additions & 0 deletions contents/data-structure/code/LinkedList/LinkedListExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package LinkedList;

public class LinkedListExample {
public static void main(String[] args) {
System.out.println("==================Singly Linked List==================");
ILinkedList<Integer> sll = new SinglyLinkedList<>();
sll.addFirst(3);
sll.addLast(10);
sll.addFirst(2);
sll.addLast(12);
System.out.println(sll);
System.out.println("size : " + sll.size());
System.out.println("first : " + sll.first());
System.out.println("last : " + sll.last());
System.out.println("removeFirst : " + sll.removeFirst());
System.out.println(sll);
System.out.println("removeLast : " + sll.removeLast());
System.out.println(sll);
System.out.println("removeFirst : " + sll.removeFirst());
System.out.println(sll);
System.out.println("removeLast : " + sll.removeLast());
System.out.println(sll);
System.out.println("size : " + sll.size());

System.out.println("==================Doubly Linked List==================");
ILinkedList<Integer> dll = new DoublyLinkedList<>();
dll.addFirst(3);
dll.addLast(10);
dll.addFirst(2);
dll.addLast(12);
System.out.println(dll);
System.out.println("size : " + dll.size());
System.out.println("first : " + dll.first());
System.out.println("last : " + dll.last());
System.out.println("removeFirst : " + dll.removeFirst());
System.out.println(dll);
System.out.println("removeLast : " + dll.removeLast());
System.out.println(dll);
System.out.println("removeFirst : " + dll.removeFirst());
System.out.println(dll);
System.out.println("removeLast : " + dll.removeLast());
System.out.println(dll);
System.out.println("size : " + dll.size());
}
}

125 changes: 125 additions & 0 deletions contents/data-structure/code/LinkedList/SinglyLinkedList.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package LinkedList;

public class SinglyLinkedList<E> implements ILinkedList<E> {
private Node<E> head;
private Node<E> tail;
private int size;

public SinglyLinkedList() {
head = tail = null;
size = 0;
}

@Override
public int size() {
return size;
}

@Override
public boolean isEmpty() {
return size == 0;
}

@Override
public E first() {
if (isEmpty()) return null;
return head.getElement();
}

@Override
public E last() {
if (isEmpty()) return null;
return tail.getElement();
}

@Override
public void addFirst(E e) {
head = new Node<>(e, head);
if (isEmpty()) tail = head;
size ++;
}

@Override
public void addLast(E e) {
Node<E> newest = new Node<>(e, null);
if (isEmpty()) head = newest;
else tail.setNext(newest);
tail = newest;
size ++;
}

@Override
public E removeFirst() {
if (isEmpty()) return null;
E target = head.getElement();
head = head.getNext();
size --;
if (isEmpty()) tail = null;
return target;
}

@Override
public E removeLast() {
if (isEmpty()) return null;
E target;
if (head == tail) {
target = head.getElement();
head = tail = null;
} else {
Node<E> current = head;
while (current.getNext() != tail) {
current = current.getNext();
}
target = tail.getElement();
tail = current;
tail.setNext(null);
}
size --;
return target;
}

@Override
public String toString() {
if (isEmpty()) return "[]";

StringBuilder sb = new StringBuilder("[");
Node<E> current = head;
while (current.getNext() != null) {
sb.append(current.getElement()).append(", ");
current = current.getNext();
}
sb.append(current.getElement()).append("]");
return sb.toString();
}

private static class Node<E> {
private E element;
private Node<E> next;

public Node() {
this(null, null);
}

public Node(E element, Node<E> next) {
this.element = element;
this.next = next;
}

public E getElement() {
return element;
}

public void setElement(E element) {
this.element = element;
}

public Node<E> getNext() {
return next;
}

public void setNext(Node<E> next) {
this.next = next;
}
}
}

0 comments on commit 1f36e0b

Please sign in to comment.