리스트 프로그래밍(List Programming) – 3. 리스트 클래스 연산

Copyright (c) 2015-, All Rights Reserved by Kwanghoon Choi
(아래 자바 프로그래밍 강의 교재의 내용을 자유롭게 이용하되 다른 웹 사이트 등을 통한 배포를 금합니다.)

3. 리스트 클래스 연산을 Java로 작성

앞에서 리스트 객체를 만드는 방법을 살펴보았고, 여기서는 리스트 연산을 제공하는 메소드를 정의하고 이 리스트 객체에 적용해 보려고 한다. 리스트 연산을 제공하는 메소드가 있다고 가정하면 다음과 같이 리스트 프로그래밍을 할 수 있을 것이다.

// ListTest 클래스 
public class ListTest {
        public static void main(String[] args) {
                List list = new Pair(1, new Pair(2, new Pair(3, new NullList()));
		
                int num = list.second().first();
		
                System.out.println(num);
		
                System.out.println(length(list));
		
                print(list);

                System.out.println(list.toString());

                print(reverse(list));

                print(reverse(reverse(list)));

                print(concat(list,list));
}

실행 결과는 다음과 같다.

2
3
[1,2,3]
(1, (2, (3, ())))
[3,2,1]
[1,2,3]
[1,2,3,1,2,3]

print, length, sum, concat, reverse 메소드는 다음과 같이 정의한다.

// print
        public static void print(List l) {
                System.out.print("[");
	
                while (true) {
                        if ( l.isNull() ) {
                                System.out.println("]");
                                break;
                        }
                        else {
                                System.out.print(
                                        l.first() 
                                        + (l.second().isNull() ? "" : ","));
                                l = l.second();
                        }
                }
        }
	
	
// length
        public static int length(List l) {
                int count;
		
                count = 0;
                while ( l.isPair() ) {
                        count = count + 1;
                        l = l.second();
                }
			
                return count;
        }
	
// sum
        public static int sum(List l) {
                int sum;
		
                sum = 0;
                while ( l.isPair() ) {
                        sum = sum + l.first();
                        l = l.second();
                }
		
                return sum;
        }
	
// concat
        public static List concat(List l1, List l2) {
                if ( l1.isNull() )
                        return l2;
                else 
                        return new Pair (l1.first(), concat(l1.second(), l2));
        }
	
// reverse
        public static List reverse(List l) {
                if ( l.isNull() )
                        return l;
                else
                        return concat (
                                reverse (l.second()),  
                                new Pair( l.first(), new NullList()));
        }

[연습문제] 리스트 프로그램에서 List 클래스와 독립적으로 정의된 static 메소드(print, length, sum, concat, reverse)를 List 클래스의 멤버 메소드로 작성하시오.

- static 속성은 더이상 사용하지 않고,
- print, length, sum, reverse 메소드는 인자를 없애고, concat 메소드는 인자를 하나만 두고 없앤다. 예를 들어, 변수 l이 List 클래스 타입이라고 가정하고, l.print()라고 하여 l이 가리키는 리스트를 출력한다. l.length()는 l의 길이, l.sum()은 l에 있는 정수 원소들의 합, l.reverse()는 l의 모든 원소를 포함하는 새로운 리스트 객체를 만들되 원소의 순서가 뒤에서부터 차례로 나열한 리스트, l.concat(l1)은 다른 리스트 l1과 합한 더 큰 새로운 리스트 객체를 만든다.

- List 클래스는 NullList와 Pair 클래스를 상속으로 연관시키기 위해 정의한 것으로, 이 List 클래스의  메소드들은 특별한 의미 없이 작성된 것이다. 예를 들어, List 클래스의 isNull 메소드에서 false를 반환하거나 true를 반환하거나 전혀 의미가 없다. 이러한 List 클래스를 추상 클래스로 만들기에 적합하다.

abstract class List {
        public abstract boolean isNull();
        public abstract boolean isPair();
        public abstract int first();
        public abstract List second();
        public abstract String toString();
}

 

- List 클래스의 concat 메소드와 print 메소드

// ListTest 클래스 
public class List {
        ...
        public List concat(List l) {
           if (this.isNull()) {
              return l;
           }
           else {
              return new Pair(this.first(),
                                this.second().concat(l));
           }
        }
        ...
        public void print() {
           System.out.print("[");
           List l = this;
           while ( l.isPair() ) {
              System.out.print(l.first());
              System.out.print(l.second().isNull() ? "" : ",");
              l = l.second();
           }
           System.out.println("]");
        }
        ...
}

[연습문제] 리스트 객체에 대한 연산 take와 drop을 정의하시오. take(3, l)은 리스트 l에서 앞에 있는 3개의 원소로 구성된 서브 리스트를 반환하고, drop(3, l)은 리스트 l에서 앞의 3개 원소를 제외한 나머지 원소로 구성된 서브 리스트를 반환한다. take 메소드를 적용한 리스트 l의 원소가 3개 미만이면 그 원소들만을 포함한 리스트를 만들고, drop 메소드를 적용한 리스트 l의 원소가 3개 미만이면 []을 리턴한다.

Leave a Reply

Your email address will not be published. Required fields are marked *