큐(Queue)


1. 큐(Queue)

  • 큐는 자료 구조에 들어있는 요소 중에서 가장 먼저 삽입한 요소를 꺼냄.
    • enqueue는 요소를 큐에 삽입
    • dequeue는 요소를 큐에서 가장 먼저 삽입한 요소를 꺼냄
  • 먼저 삽입된 요소부터 순서대로 꺼내는 규칙을 FIFO(first-in first-out)라고 함

 

2. 큐(Queue) 구현

2.1 큐(Queue) Interface

public interface Queue<T> {
	
    // 큐(Queue)에 Node 삽입
	void enqueue(T value);
	
    // 큐(Queue)의 사이즈를 반환
	int size();
	
    // 큐(Queue)가 비어있는지 true/false 반환
	boolean isEmpty();
	
    // 큐(Queue)의 첫번째 Node의 값을 반환하고 Node를 삭제
	T dequeue();
	
    // 큐(Queue)의 첫번재 Node의 값을 반환
	T peek();
	
    // 입력받은 값이 큐(Queue)에 존재하는지 true/false를 반환
	boolean contains(T string);
}

 

2.2 큐(Queue)의 메소드 구현

2.2.1 큐의 Node 정의

// Queue의 Node를 정의
    private static class Node<T>{
		private T data;
		
		private Node<T> next;
		
		public Node(T data) {
			this.data = data;
			this.next = null;
		}
	}

2.2.2 enqueque() 메소드 구현

// 큐에 Node를 삽입하는 메소드
    @Override
	public void enqueue(T value) {
		
		Node<T> newNode = new Node<T>(value);
		
		if(isEmpty()) {
			front = newNode;
			rear = newNode;
		}else {
			rear.next = newNode;
			rear = newNode;
		}
		
		size++;
	}

2.2.3 size() 메소드 구현

// 큐의 size를 반환하는 메소드
    @Override
	public int size() {
		return size;
	}

2.2.4 isEmpty() 메소드 구현

// queue가 비어있으면 true를 반환, 비어있지 않으면 false를 반환하는 메소드	
    @Override
	public boolean isEmpty() {
		return (this.size == 0);
	}

2.2.5 dequeue() 메소드 구현

// 큐의 첫번째 Node의 값을 반환하고 Node를 삭제하는 메소드
    @Override
	public T dequeue() {
		if(isEmpty()) {
			throw new RuntimeException("스택이 비어있습니다.");
		}else {
			Node<T> deNode = front;
			
			front = front.next;
			size--;
			
			return deNode.data;
		}

	}

2.2.5 peek() 메소드 구현

// 큐의 첫번째 Node의 값을 반환하는 메소드
    @Override
	public T peek() {
		if(isEmpty()) {
			throw new RuntimeException("스택이 비어있습니다.");
		}
		
		return front.data;
	}

2.2.6 contains() 메소드 구현

// 입력받은 값이 큐에 존재하면 true, 존재하지 않으면 false를 반환하는 메소드
	@Override
	public boolean contains(T string) {
		Node<T> current = front;
		
		while(current != null) {
			if(current.data.equals(string)) {
				return true;
			}
			current = current.next;
		}
		
		return false;
	}

2.2.7 toString() 메소드 구

// 큐에 존재하는 모든 Node의 값을 출력하는 메소드
    @Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		Node<T> current = front;
		
		sb.append("[");
		
		while(current != null) {
			sb.append(current.data + ", ");
			current = current.next;
		}
		
		if(sb.lastIndexOf(",") != -1) {
			sb.replace(sb.lastIndexOf(","), sb.length(), "]");
		}else {
			sb.append("]");
		}
		
		return sb.toString();
	}

 

3. 큐(Queue) 테스트

3.1 size() & isEmpty()  테스트

// 큐 생성 후, size()메소드와 isEmpty()메소드 테스트
Queue<String> queue = new ArrayListQueue<>(5);
		
System.out.println(queue);				
System.out.println(queue.size());
System.out.println(queue.isEmpty());

3.2 enqueue()  테스트

// enqueue() 테스트
queue.enqueue("딸기");
queue.enqueue("포도");
queue.enqueue("망고");
queue.enqueue("수박");
queue.enqueue("사과");
		
System.out.println(queue);
System.out.println(queue.size());	// Node가 5개 삽입되었기 때문에 5를 반환
System.out.println(queue.isEmpty());	// Node가 삽입되었기 때문에 false를 반환

 

3.3 dequeue()  테스트

// dequeue() 테스트
System.out.println(queue.dequeue());
System.out.println(queue.dequeue());
	
System.out.println(queue);
System.out.println(queue.size());	// Node 2개를 삭제했기 때문에 3을 반환
System.out.println(queue.isEmpty());

 

3.4 peek()  테스트

// peek() 테스트
System.out.println(queue.peek());
System.out.println(queue);
System.out.println(queue.size());	//peek()는 Node의 값만 반환하고 삭제하지 않기 때문에 3을 반환
System.out.println(queue.isEmpty());

3.5 contains()  테스트

// contains() 테스트
System.out.println(queue);
System.out.println(queue.contains("망고"));	// true를 반환
System.out.println(queue.contains("딸기"));	// false를 반환

스택(Stack)


1. 스택(Stack)

  • 스택은 자료 구조에 들어있는 요소 중에서 마지막에 삽입한 요소를 꺼
    • push는 요소를 스택에 삽입
    • pop은 요소를 스택에서 마지막에 삽입한 요소를 꺼냄
  • 먼저 들어간 것이 마지막에 나오는 규칙을 LIFO(list-in first-out)라고 함

 

2. 스택(Stack) 구현

2.1 스택(Stack) Interface

package com.beyond.palindromes.structure;

public interface Stack<T> {
	
    // 스택에 노드 추가
	void push(T value);
	
    // 스택의 size 반환
	int size();
	
    // 스택이 비어있는지에 대해 true/false 반환
	boolean isEmpty();

	// 스택의 마지막 노드 값 출력 후 제거
	T pop();

	// 스택에 입력받은 값이 존재하는지 true/false 반환
	boolean contains(String string);

	// 스택의 마지막 노드 값 반환
	T peek();

}

 

2.2 스택(Stack)의 메소드 구현

2.2.1 스택의 Node

	// 스택의 Node
    private static class Node<T>{
		private T data;
		private Node<T> next;
		
		public Node(T data) {
			this.data = data;
			this.next = null;
		}
	}

2.2.2 push() 메소드

	// 스택에 node를 추가하는 메소드
    @Override
	public void push(T value) {
		Node<T> newNode = new Node<>(value);
		
		newNode.next = top;
		top = newNode;
		
		size++;
	}

2.2.3 size() 메소드

	// 스택의 size를 반환하는 메소드
    @Override
	public int size() {
		return this.size;
	}

2.2.4 isEmpty() 메소드

	// 스택이 비어있다면 true, 비어있지 않다면 false를 반환하는 메소드
    @Override
	public boolean isEmpty() {
		return top==null;
	}

2.2.5 pop() 메소드

	// 스택의 마지막 Node의 값을 반환하고 Node를 삭제하는 메소드
    @Override
	public T pop() {
		if(isEmpty()) {
			throw new RuntimeException("스택이 비어있습니다.");
		}
		
		T value = top.data;
		
		top = top.next;
		
		size --;
		
		return value;
	}

2.2.6. contains 메소드

	//입력받은 값이 스택에 존재한다면 true, 존재하지 않는다면 false를 반환하는 메소드
    @Override
	public boolean contains(String string) {
		Node<T> current = top;
		
		while(current != null) {
			if(current.data.equals(string)) {
				return true;
			}
			
			current = current.next;
		}
	
		return false;
	}

2.2.7. peek() 메소드

	// 스택의 마지막 노드의 값을 반환하는 메소드
    @Override
	public T peek() {
		if(isEmpty()) {
			throw new RuntimeException("스택이 비어있습니다.");
		}
		return top.data;
	}

2.2.8. toString() 메소드

	// 스택에 존재하는 모든 Node의 값을 출력하는 메소드
	@Override
	public String toString() {
		Node<T> current = top;
		StringBuilder sb = new StringBuilder();
		
		sb.append("[");
		
		while(current != null) {
			sb.append(current.data + ", ");
			
			current = current.next;
		}
		
		if (sb.lastIndexOf(",") != -1) {
			sb.replace(sb.lastIndexOf(","), sb.length(), "]");			
		} else {
			sb.append("]");		
		}

		return sb.toString();
	}

 

3. 스택(Stack) 테스트

3.1 size() & isEmpty()  테스트

// 스택 생성 후, size()메소드와 isEmpty()메소드 테스트
Stack<String> stack = new LinkedListStack<>();
		
System.out.println(stack);			// toString()을 재정의 하여 스택의 모든 Node의 값을 출력
System.out.println(stack.size());
System.out.println(stack.isEmpty());

3.2 peek()  테스트

// push() 테스트
stack.push("딸기");
stack.push("포도");
stack.push("바나나");
		
System.out.println(stack);
System.out.println(stack.size());		// 스택에 3개의 Node를 삽입하였으므로 3을 반환
System.out.println(stack.isEmpty());		// 스택에 Node를 삽입하였으므로 false
System.out.println();

3.3 pop()  테스트

// pop() 테스트
System.out.println(stack.pop());	// stack은 LIFO이므로 "바나나"를 반환하고 노드를 삭제
		
System.out.println(stack);
System.out.println(stack.size());
System.out.println(stack.isEmpty());

3.4 contains()  테스트

// contains()메소드 테스트
System.out.println(stack);
System.out.println(stack.contains("딸기"));
System.out.println(stack.contains("바나나"));

3.5 peek() 테스트

// peek() 메소드 테스트
System.out.println(stack.peek());

System.out.println(stack.size());		// peek()는 값만 반환하고 삭제하지 않으므로 size는 그대로
System.out.println(stack.isEmpty());
System.out.println();

1. 배열(Array)

  • 배열은 같은 타입의 원소들을 효율적으로 관리할 수 있는 자료 구조
  • 배열은 하나의 변수 이름으로 동일한 타입의 데이터를 그룹화하여 관리 가능
  • 배열의 요소를 일렬로 나열하고 각 요소에 인덱스를 사용하여 원하는 데이터에 접근 가능

 

2. 연결 리스트(Linked List)

  • 배열의 약점인 삽입과 삭제 작업에 강한 자료 구조로 연결 리스트가 있음
  • 연결 리스트는 각 요소를 포인터라고 부르는 화살표에 의해 한 줄로 나열한 것

  • 연결 리스트의 종류
    • 단방향 연결 리스트는 각 노드를 연결하는 포인터가 어느 한쪽 방향이 되도록 한 것
    • 양방향 연결 리스트는 각 노드를 연결하는 포인터가 양방향이 되도록 한 것

 

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

 

3.1 단순 연결리스 구현

  • List Interface
// List 인터페이스

public interface List<T> {
	
	// 첫번째에 노드 삽입
	void addFirst(T data);
	
	// 마지막에 노드 삽입
	void addLast(T data);
	
	// 노드 삽입
	void add(int index, T data);
	
	// 리스트 사이즈
	int size();
	
	// 입력받은 인덱스 노드의 값 반환
	T get(int index);
	
	// 입력받은 값의 node가 있는지 true, false 반환
	boolean contains(T data);
	
	// 첫번째 노드 삭제
	void removeFirst();
	
	// 마지막 노드 삭제
	void removeLast();
	
	// 입력받은 인덱스 노드 삭제
	void remove(int index);
	
	// 입력받은 데이터에 해당하는 노드 삭제
	void remove(T data);
}
  • Node 정의 
	// 노드 클래스 정의
	private static class Node<T> {
		private T data; // 노드가 저장하는 데이터
		
		private Node<T> next; // 다음 노드를 가리키는 참조

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

  • 0 번째 Node 삽입하는 메소드
	public void addFirst(T data) {
		Node<T> newNode = new Node<>(data);
		
		if (head == null) {
			head = newNode;
		} else {
			newNode.next = head;
			head = newNode;
		}
		
		size++;
	}

  • 마지막 Node 삽하는 메소드
	// 마지막 값 삽입
	@Override
	public void addLast(T data) {
		Node<T> newNode = new Node<>(data);
		
		if (head == null) {
			head = newNode;
		} else {
			Node<T> lastNode = this.search(size - 1);
			
			lastNode.next = newNode;
		}
		
		size++;
	}

  • 입력받은 인덱스에 Node를 삽입하는 메소드
	public void add(int index, T data) {
		if(index < 0 || index > size){
			throw new IndexOutOfBoundsException();
		}
		
		if(index == 0) {
			this.addFirst(data);
			
			return;
		}
		
		if(index == size) {
			this.addLast(data);
			
			return;
		}
		
		Node<T> newNode = new Node<>(data);
		Node<T> prevNode = this.search(index - 1);
		
		newNode.next = prevNode.next;
		prevNode.next = newNode;
		
		size++;
		
	}

  • 현재 List의 Size를 반환하는 메소드
	@Override
	public int size() {
		
		return this.size;
	}

  • 입력받은 인덱스 노드의 값 반환하는 메소드
	@Override
	public T get(int index) {
		if(index < 0 || index >= size) {
			throw new IndexOutOfBoundsException();
		}
		
		return this.search(index).data;
	}

  • 입력받은 값의 node가 있는지 true, false 반하는 메소드
	@Override
	public boolean contains(T data) {
		Node<T> current = head;
		
		while(current != null) {
			if(current.data.equals(data))
				return true;
			
			current = current.next;
			
		}
		return false;
	}

  • 0번째 인덱스의 Node 삭제하는 메소드
	@Override
	public void removeFirst() {
		if(head ==null) {
			return;
		}else {
			Node<T> first = head;
			
			head = first.next;
			
			first.data = null;
			first.next = null;
			
			size--;
		}
		
	}

  • 마지막 인덱스의 Node를 삭제하는 메소드
	@Override
	public void removeLast() {
		if(head == null) {
			return;
		}else if((size - 2) <= 0){
			this.removeFirst();
			
			return;

		}else {
			Node<T> lastPrevNode = this.search(size-2);
			
			lastPrevNode.next.data = null;
			lastPrevNode.next = null;
			
			size --;
		}
	}

  • 입력받은 인덱스의 Node를 삭제하는 메소드
	public void remove(T data) {
		
		Node<T> current = head;
		
		if(current == null) {
			return;
		}
		
		if(current.data.equals(data)) {
			this.removeFirst();
			
			return;
		}
		
		for(int i = 0; i < size - 1; i++) {
			if(current.next.data.equals(data)) {
				Node<T> nextNode = current.next;
				
				current.next = nextNode.next;
				nextNode.data = null;
				nextNode.next = null;
				
				size--;
				
				break;
				
			}
			
			current = current.next;
		}
		
	}

  • 입력받은 값의 List의 인덱스를 통해 값을 반환하는 메소드
	private Node<T> search(int index) {
		Node<T> node = head;
		
		for (int i = 0; i < index; i++) {
			node = node.next;
		}		
		
		return node;
	}

  • List를 출력하는 메소드
	@Override
	public String toString() {
		Node<T> current = head;
		StringBuilder sb = new StringBuilder();
		
		sb.append("[");
		
		while(current != null) {
			sb.append(current.data + ", ");
			
			current = current.next;
		}
		
		if (sb.lastIndexOf(",") != -1) {
			sb.replace(sb.lastIndexOf(","), sb.length(), "]");			
		} else {
			sb.append("]");		
		}

		return sb.toString();
	}

 

3.2 단순 연결리스 테스트

  • SinglyLinkedList 테스트
		List<String> list = new SinglyLinkedList<>();
		
		System.out.println(list);
		System.out.println("size : " + list.size());
		System.out.println();


  • addFirst() 메소드 테스트
		list.addFirst("딸기");
		
		System.out.println(list);
		System.out.println("size : " + list.size());
		System.out.println();


  • addLast() 메소드 테스트
		list.addLast("포도");
		list.addLast("키위");
		
		System.out.println(list);
		System.out.println("size : " + list.size());
		System.out.println();

 


  • add() 메소트 테스트
		list.add(0, "수박");
		list.add(4, "바나나");
		
	
		System.out.println(list);
		System.out.println("size : " + list.size());
		System.out.println();


  • get() 메소드 테스트
		System.out.println(list.get(0));
		System.out.println(list.get(1));
		System.out.println(list.get(3));
		System.out.println(list.get(6));
		System.out.println();


  • removeFrist() 메소드 테스트
		list.removeFirst();
		
		System.out.println(list);
		System.out.println("size : " + list.size());
		System.out.println();

 


  • removeLast() 메소드 테스트
		list.removeLast();
		
		System.out.println(list);
		System.out.println("size : " + list.size());
		System.out.println();


  • remove() 메소드 테스트 (입력값 인덱스)
		list.remove(1);
		
		System.out.println(list);
		System.out.println("size : " + list.size());
		System.out.println();


  • remove() 메소드 테스트 (입력값 값)
		list.remove("키위");
		System.out.println(list);
		System.out.println("size : " + list.size());
		System.out.println();


  • contains() 메소드 테스트
		System.out.println(list);
		
		System.out.println(list.contains("딸기"));
		System.out.println(list.contains("두리안"));
		System.out.println(list.contains("바나나"));
		System.out.println(list.contains("참외"));
		System.out.println();

'자료구조' 카테고리의 다른 글

[자료구조] 그래프(Graph)  (0) 2024.06.28
[자료구조] 트리(Tree)  (0) 2024.06.28
[자료구조] 해시 테이블(Hash Table)  (0) 2024.06.28
[자료구조] 큐(Queue)  (0) 2024.06.28
[자료 구조] 스택(Stack)  (0) 2024.06.20

+ Recent posts