얼마만에 포스팅인지 하핫... 그동안 여행도 다니고 우아한 테크코스 지원한다고 자소서 쓰다보니 시간이 없었다(는 핑계..)
오늘 포스팅 할 문제만 3-4일 걸려서 풀었던거 같다! 원래는 interface와 abstract class가 메인이였으나 나중에는 코드를 이해하려고 쏟은 시간이 대부분이였다능... 암튼 시작한다!
1. ListItem
package danHeeYoung;
public abstract class ListItem {
protected ListItem rightLink;
protected ListItem leftLink;
protected Object value;
public ListItem(Object obj) {
value = obj;
}
abstract ListItem next();
abstract ListItem setNext(ListItem listItem);
abstract ListItem previous();
abstract ListItem setPrevious(ListItem listItem);
abstract int compareTo(ListItem listItem);
public Object getValue() {
return this.value;
}
public void setValue(Object obj) {
this.value = obj;
}
}
추상 클래스이다! 링크리스트이다보니 왼쪽, 오른쪽 객체가 하니씩 있고 어떤 값을 가지고 있는 value 또한 있다. 클래스를 추상으로 declare하려면 최소 하나에 메소드는 추상으로 지정해야한다! 이 클래스에는 총 5개의 추상 메소드가 있다!
2. Node
package danHeeYoung;
public class Node extends ListItem{
public Node(Object obj) {
super(obj);
}
@Override
ListItem next() {
return this.rightLink;
}
@Override
ListItem setNext(ListItem listItem) {
this.rightLink = listItem;
return this.rightLink;
}
@Override
ListItem previous() {
return this.leftLink;
}
@Override
ListItem setPrevious(ListItem listItem) {
this.leftLink = listItem;
return leftLink;
}
@Override
int compareTo(ListItem listItem) {
if(listItem!=null) {
return ((String)super.getValue()).compareTo( (String)listItem.getValue());
}
return -1;
}
}
위에 추상 클래스인 ListItem을 extend한다. 링크리스트이기에 왼쪽, 오른쪽 노드를 지정하고 옮길수 있는 추상 메소드 들을 이 클래스에서 정의한다! 또한 compareTo 메소드 같은 경우 ListItem 에 value 변수가 object로 지정이 되어있기 때문에 (String)으로 케스트 해주고 비교한다. (이럴거면 애초에 String으로 설정 했어도 되지 않나? 싶은 생각이 들지만 문제 지침에 써있었으니까 봐준다..).
* 이 compareTo 메소드 이해하는게 아직 조금 부족했는지 이 메소드 사용할때 조금 헷갈렸다.
int result = current.compareTo(newItem);
요런 코드가 있다면 current라는 변수와 newItem이라는 변수를 비교하는건데 앞에 나오는 current가 더 크다면 (current > newItem) 리턴되는 result는 > 0 이고, 뒤에 나오는 newItem이 더 크다면 (current < newItem), result < 0 이된다! 만약 값이 같다면 0이 리턴된다!
3.NodeList
package danHeeYoung;
public interface NodeList {
ListItem getRoot();
boolean addItem(ListItem listItem);
boolean removeItem(ListItem listItem);
void traverse(ListItem root);
}
첫 인터페이스이다! 4개의 static 메소드가 있다.
인터페이스에 대해서 조금더 알아보니 3개의 메소드가 존재한다고 한다. (static, default, private)
아래 링크에 굉장히 상세하게 나와있다!
[Java] 인터페이스 - 인터페이스의 요소들
인터페이스의 요소 상수 : 선언된 모든 변수는 상수로 처리됩니다. 메서드 : 인터페이스에 모든 메서드는 추상 메서드입니다. 디폴트 메서드 : 구현코드가 없는 인터페이스에서 공통적으로 구현
velog.io
참고로! java8부터는 인터페이스 안에서 default라는 메소드를 사용하면 정의뿐만이아니라 구현또한 가능하다고 한다! 그리고 이 default 메소드는 인터페이스를 구현하는 클래스에 자동적으로 상속된다!
4. MyLinkedList
package danHeeYoung;
public class MyLinkedList implements NodeList{
private ListItem root;
public MyLinkedList(ListItem listItem) {
root = listItem;
}
@Override
public ListItem getRoot() {
return this.root;
}
@Override
public boolean addItem(ListItem newItem) {
if(root==null) {
// root.setNext(newItem);
this.root = newItem;
return true;
}
ListItem current = root;
while(true) {
int result = current.compareTo(newItem); // compare the root with the given newItem
if(result<0) { // if newItem is greater than current
if(current.next()!=null) {
current = current.next();
} else {
newItem.setPrevious(current).setNext(newItem);
return true;
}
} else if(result>0) { // if current is greater than the newItem
if(current.previous()!=null) {
current.previous().setNext(newItem).setPrevious(current.previous());
newItem.setNext(current).setPrevious(newItem);
// newItem.setNext(current).setPrevious(newItem);
// newItem.setPrevious(current.previous()).setNext(newItem);
return true;
} else {
current.setPrevious(newItem).setNext(current);
this.root = newItem;
return true;
}
} else {
System.out.println("Line 43");
return false;
}
}
}
@Override
public boolean removeItem(ListItem newItem) {
ListItem current = root;
while(current!=null) {
int comparision = current.compareTo(newItem);
if(comparision==0) { // found the item to delete
if(current.equals(newItem)) { // newItem to be deleted is the root
root = current.next();
} else { // item to be deleted is not root
current.previous().setNext(current.next());
if(current.next()!=null) { // next item exists!
current.next().setPrevious(current.previous());
}
}
return true;
} else if(comparision<0) { // current is greater than item to be deleted, so move to the next item
current = current.next();
} else { // item to delete is greater
return false;
}
}
return false;
}
@Override
public void traverse(ListItem root) {
if(root==null) {
System.out.println("The list is empty");
} else {
while(root.next()!=null) {
System.out.println(root.value);
root = root.next();
}
}
}
}
가장 힘들었던 클래스이다! 일단 NodeList를 상속하니 그 안에 있던 메소드들을 이 클래스에서 정의한다. 특히 addItem 메소드가 힘들었는데 이번 첼린지를 하면서 뼈저리게 느꼈던 것중 하나가 코드가 길어지고 생각해야할게 많은 코드라면 중간중간에 꼭 // 를 사용하여 메모해야할 필요가 있다는 것이다! 링크리스트의 개념을 통해 구현하는것이다 보니 하나하나 종이에 그려가면서 코드를 짰는데 코드가 점점 길어지다 보니 전에 코드가 무슨 의미였고 왜 이렇게 구현하였는지 헷갈리고 잊어버리기도 한다. 그래서 애초에 각각에 코드에 설명을 붙이면 다시 돌아가서 체크할때 굉장히 편하다는걸 느꼈다. 특히 compareTo 메소드 쓸때... 메모 안하고 그냥 머리로만 하려고 하니까 머리 깨질뻔 했다.
5. Main
간단히 시험해 보았다.
package danHeeYoung;
public class Main {
public static void main(String[] args) {
MyLinkedList list = new MyLinkedList(null);
list.traverse(list.getRoot());
String data = "서울 대전 광주 부산 천안 충주 파주 의정부 연천 포천 울산";
String[] dataArr = data.split(" ");
for(String s: dataArr) {
list.addItem(new Node(s));
}
list.traverse(list.getRoot());
list.removeItem(new Node("의정부"));
list.removeItem(new Node("연천"));
System.out.println();
list.traverse(list.getRoot());
list.addItem(new Node("뉴욕"));
list.addItem(new Node("시에틀"));
System.out.println();
list.traverse(list.getRoot());
}
}
The list is empty
광주
대전
부산
서울
연천
울산
의정부
천안
충주
파주
광주
대전
부산
서울
울산
천안
충주
파주
광주
뉴욕
대전
부산
서울
시에틀
울산
천안
충주
파주
결과는 이렇게 나온다~!
느낀점!
이번 첼린지를 하면서 중간중간 설명을 붙이는게 왜 중요한지 알게되었다. 생각에 흐름을 놓치지 않게 도와주고 혹시라도 흐름을 놓쳐서 전 코드를 체크해야할때도 굉장이 용이하다는것을 느꼈다.
그리고 오늘과 같이 자료구조와 같은 생각을 많이 해야하고 각각에 절차를 생각해야할때는 가만히 앉아서 머리 싸매고 있는 것보다는 종이에 그려가면서 구현하는게 훨씬 도움이 됬다. 그래서 드는 생각이 조그만 화이트보드를 구매하면 좋을거같다는 생각을 했다. 화이트보드는 쓰고 지울수있으니 종이 낭비도 안하니까 말이다.
굉장히 오랫만에 한 블로그 포스팅인데 앞으로도 꾸준히 달려보자 아자아자!!
'테크스토리' 카테고리의 다른 글
2023 우테코 프리코스 week1 문제들 (0) | 2022.10.27 |
---|---|
자바 제네릭(Generic) 공부 후기 (0) | 2022.10.22 |
LinkedList 자신있으면 도전해봐~ (LinkedList Challenge 후기) (2) | 2022.10.11 |
*LinkedList* 어디까지 알고있니? (feat. Iterator & ConcurrentModificationException) (2) | 2022.10.08 |
생소하다! 자바 Autoboxing & Unboxing (1) | 2022.10.08 |
댓글