고급JAVA 2강 - Stack & Queue / 정렬

Whatever·2021년 10월 29일
0

고급 JAVA

목록 보기
2/32
  • Stack ==> 후입선출(LIFO - Last In First Out)의 자료구조
  • Queue ==> 선입선출(FIFO - First In First Out)의 자료구조

Stack과 Queue는 LinkedList를 이용해서 사용할 수 있다.
(Stack은 Stack이라는 클래스가 별도로 존재한다.)

Stack의 명령
1. 자료 입력 : push(입력데이터)
2. 자료 출력 :
pop() ==> 자료를 꺼내온 후 꺼내온 자료를 Stack에서 삭제한다. //실제 꺼내올 때 사용
peek() ==> 삭제없이 자료를 꺼내온다. //어떤 데이터가 있는지 검사(확인)할 때 사용

	Stack<String> stack = new Stack<>();
	LinkedList<String> stack2 = new LinkedList<>();
	stack.push("홍길동");
	stack.push("일지매");
	stack.push("변학도");
	stack.push("강감찬");
	
	System.out.println("stack => " + stack);
	String data = stack.pop();
	System.out.println("꺼내온 값 : " + data); //변수에 저장해서 꺼내옴
	System.out.println("꺼내온 값 : " + stack.pop()); //바로 꺼내옴
	System.out.println("stack => " + stack);
	
	stack.push("성춘향");
	System.out.println("stack => " + stack);
	System.out.println();

	System.out.println("꺼내온 값 : " + stack.pop());
	System.out.println("stack => " + stack);
	System.out.println();
	
	System.out.println("삭제 없이 꺼내온 값 : " + stack.peek());
	System.out.println("stack => " + stack);
	System.out.println();
	System.out.println("------------------------------------------");
    

Queue의 명령
1. 자료 입력 : offer(입력데이터)
2. 자료 출력 :
poll() ==> 자료를 꺼내오고 그 자료를 Queue에서 삭제한다.
peek() ==> 삭제없이 자료를 꺼내온다.

LinkedList는 Queue 인터페이스를 구현한 List클래스이다.
Queue queue = new LinkedList<>();//Queue는 인터페이스 - 객체생성 안 됨. LinkedList로 생성

	queue.offer("홍길동");
	queue.offer("일지매");
	queue.offer("변학도");
	queue.offer("강감찬");
	
	System.out.println("queue ==> " + queue);
	String temp = queue.poll();
	System.out.println("꺼내온 데이터 : " + temp);
	System.out.println("꺼내온 데이터 : " + queue.poll());
	System.out.println("queue ==> " + queue);
	System.out.println();
	
	queue.offer("성춘향");
	System.out.println("queue ==> " + queue);
	System.out.println();

	System.out.println("꺼내온 데이터 : " + queue.poll());
	System.out.println("queue ==> " + queue);
	System.out.println();
	
	System.out.println("삭제없이 꺼내오기 : " + queue.peek());
	System.out.println("queue ==> " + queue);
	System.out.println();  

Stack은 꺼내올 때 pop(), 입력할 때 push()
Queue는 꺼내올 때 poll(), 입력할 때 offer()
둘 다 모두 어떤 값이 있는지 확인할 때는 peek()

Stack으로 뒤로가기, 앞으로가기 만들기

public class StackTest {

public static void main(String[] args) {
	Browser b = new Browser();
	
	b.goURL("1. 네이버");
	b.goURL("2. 야후");
	b.goURL("3. 구글");
	b.goURL("4. 다음");
	
	b.history();
	
	System.out.println("뒤로가기 후...");
	b.goBack();
	b.history();
	
	System.out.println("뒤로가기 후...");
	b.goBack();
	b.history();
	
	System.out.println("앞으로가기 후...");
	b.goForward();
	b.history();
	
	System.out.println("새로운 사이트 방문 후...");
	b.goURL("5. 네이트");
	b.history();
	
}

}

//웹브라우저의 앞으로가기, 뒤로가기 기능 구현(스택 이용)
class Browser{
    //앞으로가기 데이터가 저장될 주소
    private Stack<String> back;    //이전 방문 내역이 저장된 스택
    private Stack<String> forward; //다음 방문 내역이 저장될 스택
    private String currentURL; 	   //현재 페이지

//생성자
public Browser() {
	back = new Stack<>();
	forward = new Stack<>();
	currentURL = "";
}

//사이트를 방문하는 메서드 ==> 매개변수에는 방문할 URL이 저장된다.
public void goURL(String url) {
	System.out.println(url + " 사이트에 접속합니다.");
	
	//현재 페이지가 있으면...
	if(currentURL != null && !"".equals(currentURL)) {
		back.push(currentURL); //현재 페이지를 back 스택에 추가한다.
	}
	currentURL = url; //현재 페이지를 변경한다.
	forward.clear();  //forward 스택 데이터 전체 삭제
}

//뒤로 가기
public void goBack() {
	//isEmpty() ==> Stack이 비어있으면 true, 그렇지 않으면 false 
	if(!back.isEmpty()){//비어있지 않으면 동작
		forward.push(currentURL); //현재 페이지를 forward 스택에 추가한다.
		currentURL = back.pop();  //back에서 1개의 요소를 꺼내와 현재 페이지로 한다.
	}
	
}

//앞으로 가기
public void goForward() {
	if(!forward.isEmpty()) {
		back.push(currentURL); //현재 페이지를 back 스택에 추가한다.
		currentURL = forward.pop(); //forward에서 1개의 요소를 꺼내와 현재 페이지로 한다.
	}
}

//방문 기록 확인하기
public void history() {
	System.out.println("---------------------------------");
	System.out.println("  방	  문	  기	  록   ");
	System.out.println("---------------------------------");
	System.out.println(" back      ==> " + back);
	System.out.println(" 현재       ==> " + currentURL);
	System.out.println(" forward   ==> " + forward);
	System.out.println("---------------------------------");

}

}

정렬

정렬과 관련된 interface는 Comparable, Comparator 이렇게 두 가지가 있다.

  • Comparable은 Collection에 추가되는 데이터 자체에 정렬 기준을 넣고 싶을 때 구현하는 인터페이스이다. (내부 정렬기준 구현하기)
  • Comparator는 외부에 별도로 정렬 기준을 구현하고 싶을 때 사용하는 인터페이스이다. (외부 정렬기준 구현하기)
  • Comparable에서는 compareTo()메서드를 재정의하고, Comparator에서는 compare()메서드를 재정의해야 한다.
  • String 클래스, Wrapper 클래스, Date 클래스, File 클래스에는 내부 정렬기준이 구현되어 있다.
    (내부 정렬기준은 오름차순으로 처리되도록 구현되어 있다.)
      public static void main(String[] args) {
      ArrayList<String> list = new ArrayList<>();

	list.add("일지매");
	list.add("홍길동");
	list.add("성춘향");
	list.add("변학도");
	list.add("이순신");
	
	System.out.println("정렬전 : " + list);
	
	//정렬은 Collections.sort()메서드를 이용하여 정렬한다.
	//Collections.sort()메서드는 기본적으로 내부 정렬 기준으로 정렬한다.
	//내부 정렬 기준 
	// ==> Collection에 추가되는 데이터 자체에 구성된 정렬 기준 (지금은 String의 내부 정렬기준)
	// ==> 기본적인 자료형의 내부 정렬 기준은 오름차순으로 정렬되도록 만들어져 있다.
	Collections.sort(list);
	System.out.println("정렬후 : " + list); //가나다순으로 정렬됨
	
	Collections.shuffle(list); //자료 섞기
	System.out.println("자료 섞기 후 : " + list);
				  
	//외부 정렬 기준을 사용해서 정렬하기
	Collections.sort(list, new Desc()); //정렬기준 객체를 생성해서 넣어주기
	System.out.println("내림차순 정렬 후 : " + list);
	
}

}

// 정렬 방식을 정해주는 class만들기 (외부 정렬기준 class 만들기)
class Desc implements Comparator<String>{ //인터페이스에 선언된 메서드를 구현해야 함.

/*
   compare메서드의 반환값
  - 반환값이 0 ==> 두 값이 같다.
  - 반환값이 양수 ==> 두 값의 순서를 바꾼다.
  - 반환값이 음수 ==> 두 값의 순서를 바꾸지 않는다. 
  
  예) 오름차순일 경우 
     ==> 앞의 값이 크면 양수, 같으면 0, 뒤의 값이 크면 음수가 반환되도록 구현한다.
  
*/

@Override
public int compare(String str1, String str2) { //반환값이 int - 순서를 바꿀지 그대로 둘지 정하는 것
	//내림차순으로 구현하려고 한다.

// if(str1.compareTo(str2) > 0) { //앞이 크고 뒤가 작다.
// return -1;
// }else if(str1.compareTo(str2) < 0){
// return 1;
// }else {
// return 0;
// }

	return str1.compareTo(str2) * -1; //오름차순의 부호를 반대로 : -1을 곱함.
}
                                       

public class ListSortTest02 {

public static void main(String[] args) {
	ArrayList<Member> memList = new ArrayList<>();
	
	memList.add(new Member(1, "홍길동", "010-1111-1111"));
	memList.add(new Member(5, "이순신", "010-2222-1111"));
	memList.add(new Member(9, "성춘향", "010-3333-1111"));
	memList.add(new Member(3, "강감찬", "010-4444-1111"));
	memList.add(new Member(6, "일지매", "010-5555-1111"));
	memList.add(new Member(2, "변학도", "010-6666-1111"));
	
	System.out.println("정렬전...");
	for(Member mem : memList) {
		System.out.println(mem);
	}
	System.out.println("---------------------------------------------");
	
	//회원이름을 기준으로 오름차순 - 내부정렬기준
	Collections.sort(memList); //내부 정렬 기준이 없을 때 정렬 불가(오류) 
	// - 정렬하고 싶으면 comparable이라는 인터페이스도 같이 구현해줘야 함.
	// - 내부 정렬 기준은 한 가지 기준으로밖에 정렬할 수 없음.
	
	System.out.println("정렬후...(내부정렬기준 - 회원이름을 기준으로 오름차순)");
	for(Member mem : memList) {
		System.out.println(mem);
	}
	System.out.println("---------------------------------------------");
	
	//회원번호의 내림차순을 정렬하기
	Collections.sort(memList, new SortNumDesc());
	
	System.out.println("회원번호의 내림차순 정렬후...");
	for(Member mem : memList) {
		System.out.println(mem);
	}
	System.out.println("---------------------------------------------");
}

}

//Member클래스의 회원이름을 기준으로 오름차순 정렬이 되도록
//내부 정렬 기준 추가하기 => Comparable 인터페이스를 구현한다.
class Member implements Comparable<Member>{
    private int num; //회원번호
    private String name; //이름
    private String tel; //전화번호

public Member(int num, String name, String tel) {
	this.num = num;
	this.name = name;
	this.tel = tel;
	
}

public int getNum() {
	return num;
}


public void setNum(int num) {
	this.num = num;
}

public String getName() {
	return name;
}

public void setName(String name) {
	this.name = name;
}

public String getTel() {
	return tel;
}

public void setTel(String tel) {
	this.tel = tel;
}


@Override
public String toString() {
	return "Member [num=" + num + ", name=" + name + ", tel=" + tel + "]";
}

//내부 정렬 기준을 설정하는 메서드 구현하기
//(회원이름의 오름차순 기준 설정)
@Override
public int compareTo(Member mem) { //매개변수가 하나 - this(현재 Member클래스)와 mem(다른 Member클래스)과 비교 
	
	return this.getName().compareTo(mem.getName()); //this가 현재 값, mem.getName이 매개변수에서 온 값.
	//이름 - String 타입이면 compareTo()라는 메서드를 쓸 수 있다.
}

}

// Member 클래스의 회원번호(num)를 기준으로 내림차순되는
// 외부정렬기준 class를 작성하시오.

class SortNumDesc implements Comparator{

@Override
public int compare(Member mem1, Member mem2) { //숫자형이기 때문에 비교연산자로 바로 비교할 수 있음

// if(mem1.getNum() > mem2.getNum()) { //앞이 크고 뒤가 작으면 => 바꾸지 않는다(음수)
// return -1;
// }else if(mem1.getNum() < mem2.getNum()){ //앞이 작고 뒤가 크면 => 바꾼다(양수)
// return 1;
// }else {
// return 0;
// }

	//Wrapper클래스를 이용하는 방법1
	// return new Integer(mem1.getNum()).compareTo(mem2.getNum()) * -1; //if문 쓰지 않아도 가능
	//기본적으로 오름차순이기 때문에 반대로 하려면 부호를 반대로 하면 됨.
	
	//Wrapper클래스를 이용하는 방법1
	return Integer.compare(mem1.getNum(), mem2.getNum()) * -1; //위와 같은 의미, 같은 결과.
	//compare가 static메서드. 오름차순 기준으로 반환값을 만들어줌.
	

}

}

문제) 학번(int), 이름(String), 국어점수, 영어점수, 수학점수, 총점, 등수를 멤버로 갖는 Student클래스를 만든다.
- 이름만 String, 나머지는 다 int
이 클래스의 생성자에서는 학번, 이름, 국어점수, 영어점수, 수학점수만 매개변수로 받아서 초기화 처리를 한다.
이 Student 객체는 List에 저장하여 관리한다. - memList처럼
List에 저장된 데이터(Student)는 학번의 오름차순으로 정렬할 수 있는 내부 정렬 기준을 구현한다.
그리고, 총점의 역순으로 정렬하는데 총점이 같으면 이름의 오름차순으로 정렬이 될 수 있는 외부 정렬 기준 클래스를 작성한다.
위 정렬 기준에 맞춰 정렬되는 프로그램을 작성하시오.
(단, 등수는 List에 전체 데이터가 추가된 후에 저장되도록 한다.)

내가 푼 답:

public class StudentTest {

public static void main(String[] args) {

	//학생
	ArrayList<Student> students = new ArrayList<>(); 
	
	students.add(new Student(5, "홍길동", 50, 40, 60));
	students.add(new Student(9, "김씨", 80, 10, 20));
	students.add(new Student(8, "변학도", 20, 90, 60));
	students.add(new Student(10, "이순신", 60, 50, 60));
	students.add(new Student(7, "천재", 80, 50, 90));
	
	
	for(Student student : students) {
		System.out.println(student);
	}
	
	Collections.sort(students);
	
	System.out.println("학번으로 정렬 후 : ");
	for(Student student : students) {
		System.out.println(student);
	}
	
	Collections.sort(students, new DescStudent());
	System.out.println("총점으로 정렬 후(내림차순) : ");
	for(int i = 0; i < students.size(); i++) {
		System.out.println(students.get(i));
		students.get(i).setRank(i+1);
		
	}
	
	System.out.println("순위부여 : ");
	for(Student student : students) {
		System.out.println(student);
	}
	
	
}

}

class Student implements Comparable{

//멤버변수
int studentNo;
String name;
int korean;
int english;
int math;

@Override
public String toString() {
	return "Student [studentNo=" + studentNo + ", name=" + name + ", korean=" + korean + ", 
english=" + english + ", math=" + math + ", sum=" + sum + ", rank=" + rank + "]";
  }

//학번을 가져오는
public int getStudentNo() {
	return studentNo;
}

public void setStudentNo(int studentNo) {
	this.studentNo = studentNo;
}

//총점을 가져오는
public int getSum() {
	return sum;
}

public int getRank() {
	return rank;
}

public void setRank(int rank) {
	this.rank = rank;
}

public void setSum(int sum) {
	this.sum = sum;
}

int sum;
int rank;

//생성자 초기화
public Student(int studentNo, String name, int korean, int english, int math) {
	super();
	this.studentNo = studentNo;
	this.name = name;
	this.korean = korean;
	this.english = english;
	this.math = math;
	
	this.sum = korean + english + math;
}

//내부 정렬 기준 - 학번을 기준으로 오름차순
@Override
public int compareTo(Student s) {
	
	return Integer.compare(this.getStudentNo(), s.getStudentNo()); 
}

}

//총점을 기준으로 내림차순 정렬
class DescStudent implements Comparator{

@Override
public int compare(Student s1, Student s2) {

	return Integer.compare(s1.getSum(), s2.getSum()) * -1;
}

}

단축키
Ctrl + Shift + s 에서
get, set / toString / 생성자초기화 할 수 있음

0개의 댓글

Powered by GraphCDN, the GraphQL CDN