스택과 큐(Stack & Queue)

스택(Stack) : LIFO(Last In First Out)구조. 마지막에 저장된 것을 제일 먼저 꺼내게 된다.

밑이 막힌 상자안에 물건을 쌓는 구조. 위로만 넣고 빼는 것이 가능하기 때문에 마지막에 저장(push)한 것이 가장 먼저 추출(pop) 된다.

나중에 저장된 것이 가장 먼저 추출

 

(Queue) : FIFO(First In First Out) 구조. 제일 먼저 저장(offer)한 것을 제일 먼저 추출(poll)하게 된다.

먼저 저장된 것이 가장 먼저 추출

 

스택과 큐(Stack & Queue)의 메소드

- Stack (Stack은 클래스다. 평범하게 객체 생성 가능)

* search 메소드 사용시, Stack의 맨 위가 index 1이고, 쭉 아래로 오름차순임

 

 

- Queue (Queue는 인터페이스다. Queue를 구현한 클래스를 이용해 객체를 생성해야함)

* add, remove는 비어있으면 예외가 발생하지만 poll, peeknull을 반환함

 

 

Queue 인터페이스를 구현한 클래스 찾기

Java API에 들어가서 Queue 인터페이스를 찾는다 -> Queue 인터페이스를 구현한 클래스를 찾는다 -> 다형성을 이용해서 Queue객체를 생성한다.

ex) Queue q = new LinkedList();

 

 

ex)

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class Ex11_2 {

	public static void main(String[] args) {
		Stack st = new Stack();
		Queue q = new LinkedList(); // Queue인터페이스의 구현체인 LinkedList를 사용
		
		st.push("0");
		st.push("1");
		st.push("2");
		
		q.offer("0");
		q.offer("1");
		q.offer("2");
		
		System.out.println("= Stack =");
		while(!st.empty()) { // 비었는지 확인
			System.out.println(st.pop()); // 스택에서 요소 하나를 꺼내서 출력
		}
		
		System.out.println("= Queue =");
		while(!q.isEmpty()) { // 비었는지 확인
			System.out.println(q.poll()); // 큐에서 요소 하나를 꺼내서 출력
		}

	}

}

 

 

스택과 큐(Stack & Queue)의 활용

 

스택의 활용 예 수식계산, 수식괄호검사, 워드프로세서의 undo/redo, 웹브라우저의 뒤로/앞으로

 

큐의 활용 예 최근사용문서, 인쇄작업 대기목록, 버퍼(buffer)

 

ex)

 

import java.util.EmptyStackException;
import java.util.Stack;

public class Ex11_3 {

	public static void main(String[] args) {
		if (args.length!=1) {
			System.out.println("Usage:java Ex11_3 \"EXPRESSION\"");
			System.out.println("Example:java Ex11_3 \"((2+3)*1)+3\"");
			System.exit(0);
		}
		
		Stack st = new Stack();
		String expression = args[0];
		
		System.out.println("expression: " + expression);
		
		try {
			for (int i=0; i<expression.length(); i++) {
				char ch = expression.charAt(i);
				
				if (ch == '(') {
					st.push(ch + "");
				} else if (ch==')') {
					st.pop();
				}
			}
			
			if (st.isEmpty()) {
				System.out.println("괄호가 일치합니다.");
			} else {
				System.out.println("괄호가 일치하지 않습니다.");
			}
		} catch (EmptyStackException e) {
			System.out.println("괄호가 일치하지 않습니다.");
		} // try-catch의 끝

	}

}
 

ex)

import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Queue;
import java.util.Scanner;

public class Ex11_4 {
	static Queue q = new LinkedList();
	static final int MAX_SIZE = 5; // Queue에 최대 5개까지만 저장되도록 한다.
	
	public static void save(String input) {
		// queue에 저장한다.
		if(!"".equals(input)) // if(input!=null && !input.equals("")
          q.offer(input);

		// queue의 최대크기를 넘으면 제일 처음 입력된 것을 삭제한다.
		if(q.size() > MAX_SIZE)  // size()는 Collection인터페이스에 정의
			q.remove(); // q.poll()도 쓸 수 있음.
	}
	public static void main(String[] args) {
		System.out.println("help를 입력하면 도움말을 볼 수 있습니다.");
		
		while(true) {
			System.out.println(">>");
			try {
				// 화면으로부터 라인단위로 입력받는다.
				Scanner sc = new Scanner(System.in);
				String input = sc.nextLine().trim(); // trim은 앞뒤에 있는 공백 삭제
				
				if ("".equals(input)) continue;
				
				if(input.equalsIgnoreCase("q")) {
					System.exit(0);
				} else if (input.equalsIgnoreCase("help")) {
					System.out.println(" help - 도움말을 보여줍니다.");
					System.out.println(" q 또는 Q - 프로그램을 종료합니다.");
					System.out.println(" history - 최근에 입력한 명령어를 "+MAX_SIZE+"개 보여줍니다.");
				} else if (input.equalsIgnoreCase("history")) {
					
					save(input); // 입력받은 명령어를 저장하고,
					
					// LinkedList의 내용을 보여준다.
					LinkedList list = (LinkedList)q;
					
					final int SIZE = list.size();
					for(int i=0; i<SIZE; i++)
						System.out.println((i+1)+"."+list.get(i));
				} else {
					save(input);
					System.out.println(input);
				} // if(input.equalsIgnoreCase("q")) {
			} catch(Exception e) {
				System.out.println("입력오류입니다.");
			}
		} // while(true) 끝
		

	} // main()

}

 

 

 

Iterator, ListIterator, Enumeration

- 컬렉션에 저장된 데이터를 접근하는데 사용되는 인터페이스 (읽어오기)

핵심 메소드)

hasNext() : 읽어올 요소가 남아있는지 확인한다. 있으면 true, 없으면 false를 반환한다.

next() : 다음 요소를 읽어온다. next()를 호출하기 전에 hasNext()를 호출해서 읽어올 요소가 있는지 확인하는 것이 안전하다.

 

- EnumerationIterator의 구버전

Enumeration의 핵심메소드)

hasMoreElements() (IteratorhasNext()와 같음)

nextElement() (Iteratornext()와 같음)

- ListIteratorIterator의 접근성을 향상시킨 것(단방향 -> 양방향)

 

- Iterator

컬렉션에 저장된 요소들을 읽어오는 방법을 표준화 한 것

 

- Iterator 사용방법

List list = new ArrayList(); // 다른 컬렉션으로 변경할 때는 이 부분만 고치면 된다.
Iterator it = list.iterator();

while(it.hasNext()) {
	System.out.println(it.next());
}

 

 

ex)

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Ex11_5 {

	public static void main(String[] args) {
		// Collection의 메소드만 사용하고 있다면, 객체가 바뀌어도 뒤에 있는 코드들을 수정하지 않을 수 있어서 좋음.
		Collection c = new ArrayList();
		
		// ArrayList list = new ArrayList(); 참조변수를 ArrayList로 고정해놓으면 객체가 바뀌는 경우
		// 코드들을 무조건 수정해줘야 해서 번거로울 수 있음. 
		c.add("1");
		c.add("2");
		c.add("3");
		c.add("4");
		c.add("5");
		
		Iterator it = c.iterator();	// iterator는 Collection을 구현한 클래스에서 모두 사용 가능
		
		while(it.hasNext()) {
			Object obj = it.next();
			System.out.println(obj);
		}
		
//		for (int i=0; i<list.size(); i++) {	
//			System.out.println(list.get(i));
//		}
	}

}

 

MapIterator

- Map에는 iterator()가 없다.

Map map = new HashMap();

Iterator it = map.entrySet().iterator();

 

Arrays 배열을 다루기 편리한 메소드(static) 제공

1. 배열의 출력 toString()

static String toString(boolean[] a)

static String toString(byte[] a)

static String toString(char[] a)

static String toString(short[] a)

static String toString(int[] a)

static String toString(long[] a)

static String toString(float[] a)

static String toString(double[] a)

static String toString(Object[] a)

 

2. 배열의 복사 copyOf(), copyOfRange()

int[] arr = {0,1,2,3,4};
int[] arr2 = Arrays.copyOf(arr, arr.length); // arr2 = [0,1,2,3,4]
int[] arr3 = Arrays.copyOf(arr, 3);	// arr3 = [0,1,2]
int[] arr4 = Arrays.copyOf(arr, 7); 	// arr4 = [0,1,2,3,4,0,0]
int[] arr5 = Arrays.copyOfRange(arr, 2, 4); // arr5 = [2,3]
int[] arr6 = Arrays.copyOfRange(arr, 0, 7); // arr6 = [0,1,2,3,4,0,0]

 

3. 배열 채우기 fill(), setAll()

int[] arr = new int[5];
Arrays.fill(arr, 9);	// arr=[9,9,9,9,9]
Arrays.setAll(arr, (i) -> (int)(Math.random()*5)+1); // arr=[1,5,2,1,1]

 

4. 배열의 정렬과 검색 sort(), binarySearch() (이진탐색)

int[] arr = [3,2,0,1,4];
int idx = Arrays.binarySearch(arr, 2); // idx=-5 <- 잘못된 결과, 정렬이 되어있어야 함.


Arrays.sort(arr); // 배열 arr을 정렬한다.
System.out.println(Arrays.toString(arr));		// [0,1,2,3,4]
int idx = Arrays.binarySearch(arr, 2);		// idx=2 <- 올바른 결과.

 

5. 다차원 배열의 출력 deepToString()

int[] arr = {0,1,2,3,4};
int[][] arr2D = {{11,12}, {21,22}};

System.out.println(Arrays.toString(arr));	// [0, 1, 2, 3, 4]
System.out.println(Arrays.deepToString(arr2D)); // [[11,12], [21, 22]]

 

6. 다차원 배열의 비교 deepEquals()

String[][] str2D = new String[][]{{“aaa”,“bbb”},{“AAA”,“BBB”}};
String[][] str2D2 = new String[][]{{“aaa”,“bbb”},{“AAA”,“BBB”}};

System.out.println(Arrays.equals(str2D, str2D2));		// false
System.out.println(Arrays.deepEquals(str2D, str2D2));	// true

 

 

7. 배열을 List로 변환 asList(Object... a) 가변 매개변수 개수가 정해져있지 않음

List list = Arrays.asList(new Integer[]{1,2,3,4,5});		// list = [1, 2, 3, 4, 5]
List list = Arrays.asList(1,2,3,4,5);
list.add(6); // UnsupportedOperationException 예외 발생, 지원하지 않는 기능
// (이 list는 읽기전용이라 변경이 안 됨)


List list = new ArrayList(Arrays.asList(1,2,3,4,5)); // 새로운 ArrayList 생성
// (이 list는 변경이 가능)

 

8. 람다와 스트림(14)관련 parallelXXX(), spliterator(), stream()

-> 14장 가서 설명...

 

ex)

 

import java.util.Arrays;

public class Ex11_6 {

	public static void main(String[] args) {
		int[] arr = {0,1,2,3,4};
		int[][] arr2D = {{11,12,13}, {21,22,23}};
		
		System.out.println("arr="+Arrays.toString(arr));
		System.out.println("arr2D="+Arrays.deepToString(arr2D));
		
		int[] arr2 = Arrays.copyOf(arr, arr.length);
		int[] arr3 = Arrays.copyOf(arr, 3);
		int[] arr4 = Arrays.copyOf(arr, 7);
		int[] arr5 = Arrays.copyOfRange(arr, 2, 4);
		int[] arr6 = Arrays.copyOfRange(arr, 0, 7);
		
		System.out.println("arr2="+Arrays.toString(arr2));
		System.out.println("arr3="+Arrays.toString(arr3));
		System.out.println("arr4="+Arrays.toString(arr4));
		System.out.println("arr5="+Arrays.toString(arr5));
		System.out.println("arr6="+Arrays.toString(arr6));
		
		int[] arr7 = new int[5];
		Arrays.fill(arr7, 9);	// arr=[9,9,9,9,9]
		System.out.println("arr7="+Arrays.toString(arr7));
		
		Arrays.setAll(arr7, i -> (int)(Math.random()*6)+1);
		System.out.println("arr7="+Arrays.toString(arr7));
		
		for(int i : arr7) { // 향상된 for문
//		for(int x=0; x<arr7.length; x++) {
//			int i = arr7[x];
		
			char[] graph = new char[i];
			Arrays.fill(graph, '*');
			System.out.println(new String(graph)+i); // String->char[] 는 tocharArray() 이용
		}											 // char[]->String 는 new String(char[]) 이용(생성자 이용)
		
		String[][] str2D = new String[][] {{"aaa","bbb"},{"AAA","BBB"}};
		String[][] str2D2 = new String[][] {{"aaa","bbb"},{"AAA","BBB"}};
		
		System.out.println(Arrays.equals(str2D, str2D2));		// false
		System.out.println(Arrays.deepEquals(str2D, str2D2));	// true
		
		char[] chArr = {'A', 'D', 'C', 'B', 'E'};
		
		System.out.println("chArr="+Arrays.toString(chArr));
		System.out.println("index of B ="+Arrays.binarySearch(chArr, 'B'));
		System.out.println("= After sorting =");
		Arrays.sort(chArr); // binarySearch를 하기 전에는 반드시 정렬 먼저 해야 함.
		System.out.println("chArr="+Arrays.toString(chArr));
		System.out.println("index of B ="+Arrays.binarySearch(chArr, 'B'));
	}	

}

출처 - 유튜브 남궁성의 정석코딩 [자바의 정석 - 기초편] 

+ Recent posts