import static banana.Logic.print; // class Logic { public static void print() {} } // public class Test236 { public static void main( String[] args ) { System.out.println("HelloWorld"); print(); } }
import static
static 하게 선언된 함수를 호출한다.
import static banana.Logic.print; // class Logic { // 적절한 종료시점이 없어 무한반복한다. public static void print() { System.out.println("HelloWorld"); try { Thread.sleep( 800 ); } catch( Exception e ){} print(); } /* 재귀 호출을 그만하는 시점이 있어야 한다. print( 5 ); System.out.println("HelloWorld " + 5 ); print( 4 ); System.out.println("HelloWorld " + 4 ); print( 3 ); System.out.println("HelloWorld " + 3 ); print( 2 ); System.out.println("HelloWorld " + 2 ); print( 1 ); System.out.println("HelloWorld " + 1 ); print( 0 ); System.out.println("HelloWorld " + 0 ); -- 더 이상 재귀호출 안함. 여기서 종료 */ public static void print( int i ) { System.out.println("HelloWorld " + i ); if( i > 0 ) { print( i-1 ); } } } // public class Test237 { public static void main( String[] args ) { print( 5 ); } }
재귀 호출 ( recursive call )
: 함수 안에서 자기 자신을 다시 호출, 적절한 종료 시점이 없으면 무한 반복한다.
import static banana.Logic.*; // class Logic { public static int apple( int i ) { if( i != 0 ) return i * apple( i-1 ); else return 1; } } // public class Test238 { public static void main( String[] args ) { int r = apple( 5 ); System.out.println( r ); } }
apple(5) = 5 * apple(4) = 5 * 4 * apple(3) = 5 * 4 * 3 * apple(2) = 5 * 4 * 3 * 2 * apple(1) = 5 * 4 * 3 * 2 * 1 * apple(0) = 5 * 4 * 3 * 2 * 1 * 1
class Node { int data = 0; Node next = null; // 매개변수와 로컬변수가 이름이 같으면 this 를 사용하여 구별 Node( int data, Node n ) { this.data = data; next = n; } }
class Node { int data = 0; Node left = null; Node right = null; // public Node( int data ) { this.data = data; } } // public class Test240 { public static void main( String[] args ) { Node root = new Node( 5 ); // 이렇게 코드를 쓰면 a 와 root.left 는 같은 대상. 즉 new Node( 3 ) 을 가리키게 된다. Node a = root.left = new Node( 3 ); Node b = root.right = new Node( 8 ); // System.out.println( a == root.left ); System.out.println( b == root.right ); // a.left = new Node( 1 ); a.right = new Node( 4 ); } }
이진트리
: 포인터 2개를 가지고 아래로 이어붙이는 형태의 자료구조
import static banana.Logic.*; // class Node { int data = 0; Node left = null; Node right = null; // public Node( int data ) { this.data = data; } } // public class Test241 { public static void main( String[] args ) { Node root = new Node( 5 ); // Node a = root.left = new Node( 3 ); Node b = root.right = new Node( 8 ); // a.left = new Node( 1 ); a.right = new Node( 4 ); // print( root ); } } // class Logic { public static void print ( Node n ) { if( n != null ) { System.out.println( n.data ); print( n.left ); print( n.right ); } } }
print( n = [5] ) System.out.println( 5 ) print( n = [3] ) System.out.println( 3 ) print( n = [1] ) System.out.println( 1 ) print( null ) print( null ) print( n = [4] ); System.out.println( 4 ) print( null ) print( null ) print( n = [8] ) System.out.println( 8 ) print( null ) print( null )
print( n.left );
print( n.right );
이므로 트리의 왼쪽 끝까지 탐색 후 오른쪽을 탐색하는 코드
import static banana.Logic.*; // class Node { int data = 0; Node left = null; Node right = null; // public Node( int data ) { this.data = data; } } // public class Test242 { public static void main( String[] args ) { Node root = new Node( 5 ); // Node a = root.left = new Node( 3 ); Node b = root.right = new Node( 8 ); // a.left = new Node( 1 ); a.right = new Node( 4 ); // print( root ); } } // class Logic { public static void print ( Node n ) { if( n != null ) { print( n.left ); System.out.println( n.data ); print( n.right ); } } }
print( n = [5] ); print( n = [3] ); print( n = [1] ); print( null ); System.out.println( 1 ); print( null ); System.out.println( 3 ); print( n = [4] ); print( null ); System.out.println( 4 ); print( null ); System.out.println( 5 ); print( n = [8] ); print( null ); System.out.println( 8 ); print( null );
트리의 제일 오른쪽으로 이동한뒤
제일 왼쪽에 위치한 서브트리의 왼쪽노드 - 루트노드 - 오른쪽노드
해당 서브트리를 가진 루트노드 -> 오른쪽 서브트리에 왼쪽 노드가 존재한다면 그쪽으로 이동 ... 이런식으로 이동한다.
이진트리
에서 노드를 배치하는 원칙
public class Test243 { public static void main( String[] args ) { Node root = null; root = new Node( 5 ); Node a = root.left = new Node( 3 ); Node b = root.right = new Node( 8 ); Node c = a.left = new Node( 1 ); a.right = new Node( 4 ); // 위의 원칙에 의해 추가된 노드들 c.right = new Node( 2 ); b.left = new Node( 7 ); b.right = new Node( 9 ); // 최소값을 리턴하는 min 구현 // 단 데이터가 하나도 없으면 -1 int r = min( root ); System.out.println( r ); // 재귀호출 이용하지 않는 경우 int r2 = min2( root ); System.out.println( r2 ); } } // class Logic { // 재귀호출 없이 최소값 찾기 public static int min2( Node t ) { if( t == null ) return -1; while( t.left != null ) { t = t.left; } return t.data; } // public static int min( Node t ) { if( t == null ) { return -1; } else if( t.left != null ){ return min( t.left ); } else { return t.data; } } }
위의 원칙에 의해 최소값은 가장 왼쪽에 위치하므로 t.left != null
일때까지 이동한다.
public class Test245 { public static void main( String[] args ) { Node root = null; root = new Node( 5 ); Node a = root.left = new Node( 3 ); Node b = root.right = new Node( 8 ); Node c = a.left = new Node( 1 ); a.right = new Node( 4 ); // Node found = apple( root, 1 ); if( found != null ) { System.out.println( found.data ); } } } // class Logic { public static Node apple ( Node n, int d ) { Node found = null; if( n != null ) { // 찾던값과 data 가 맞으면 대입 if( n.data == d ) found = n; // 찾는 값보다 노드의 data 값이 크면 왼쪽으로 이동한다. if( found == null && n.data > d ) found = apple( n.left , d ); // 찾는 값보다 노드의 data 값이 작으면 오른쪽으로 이동한다. if( found == null && n.data < d ) found = apple( n.right , d ); } return found; } }
배치 원칙 : 왼쪽 노드 < 루트 노드 < 오른쪽 노드
public class Test248 { public static void main( String[] args ) { /* 아래의 모양대로 노드를 배치하던 걸 함수호출로 구현 root = new Node( 5 ); Node a = root.left = new Node( 3 ); Node b = root.right = new Node( 8 ); Node c = a.left = new Node( 1 ); a.right = new Node( 4 ); */ Node root = null; root = add( root, 5 ); root = add( root, 3 ); root = add( root, 8 ); root = add( root, 1 ); root = add( root, 4 ); } } // class Logic { public static Node add( Node n, int d ) { if( n == null ) { n = new Node( d ); } else { if( n.data > d ) n.left = add( n.left , d ); else if( n.data < d ) n.right = add( n.right , d ); else throw new RuntimeException("Data Duplicated"); } return n; } }