3. 트리 3.1 트리의개요 3.2 이진트리 3.3 트리의운행
3.1 트리의개요 트리 : 그래프의일종 데이터 : 노드 순환적정의 T = {R, T 1,T 2, T n } R : 루트 T i : 서브-트리 ( 트리 )
3.1 트리의개요 1. 노드 2. 근노드 3. 서브트리 4. 차수 5. 단노드 6. 간노드 (nonterminal node) 7. 부-노드, 자-노드 8. Family tree : 조상, 자손 9. 레벨 10. 높이 11. 숲
3.1 트리의개요 3.1.4 트리의종류 Ordered tree Oriented tree Binary tree Skewed tree
3.2 이진트리 여러가지응용에가장넓이사용 엄밀한이진트리크누스이진트리
3.2 이진트리 3.2.2 이진트리와관련된정리 정리 1 : 이진트리의레렐 i 에있는노드의 최대개수는 2 i-1 이다. 정리 2 : 깊이가 k 인이진트리에있는 노드의전체개수는최대 2 k -1 이다.
3.2 이진트리 정리 4 : n개의노드를가진전이진트리, 즉깊이가 log n + 1 인트리가 1차원배열에저장되면다음과같은관계가성립된다. (1) parent[i] 는 i!=1일때 i/2의위치에있게된다. (2) Leftchild[i] 는 2i<=n일때 2i의위치에있게된다. (3) rightchild[i] 는 2i+1<=n 일때 2i+1의위치에있게된다.
3.3 트리의운행 트리의운행 (Traversal) 각노드를중복되지않게한번씩방문하여트리를검색하는방법 트리의운행방법 Level order Traveral Preorder Traversal Inorder Traversal Postorder Traversal
3.3 트리의운행 7.3.2 이진트리의운행 L : 왼쪽으로의이동 R : 오른쪽으로의이동 D : 자료의출력 Preorder Traversal----DLR Inorder Traversal----LDR Postorder Traversal----LRD
3.3 트리의운행 전위운행 public static void preorder(binarytreenode t) { if(t!=null) { visit(t); preorder(t.leftchild); preorder(t.rightchild); } } 출력 : / - * A ** B C Log D E A * B - ** / log C E D
7.3 트리의운행 중위운행 public static void inorder(binarytreenode t) { if(t!=null) { inorder(t.leftchild); visit(t); inorder(t.rightchild); } } 출력 : A * B ** C - log D / E A * B - ** / log C E D
3.3 트리의운행 후위운행 public static void postorder(binarytreenode t) { if(t!=null) { postorder(t.leftchild); postorder(t.rightchild); visit(t); } } 출력 : A B ** * D log - E / - * log A ** B C / E D
3.3 트리의운행 7.3.3 운행의응용 트리의복사 public BinaryTreeNode copytree(binarytreenode bintree) { } } if( bintree=!null){ BinaryTreeNode temptree=new BinaryTreeNode(); temptree.leftchild=copytree(bintree.leftchild); temptree.rightchild=copytree(bintree.rightchild); return temptree; return null;
3.3.3 운행의응용 두트리의비교 public int equal(binarytreenode first, BinaryTreeNode second) { } 3.3 트리의운행 return((fist==null && second==null) (first!=null&&second!=null&& first.element==second.element)&& equal(firt.leftchild, second.leftchild)&& equal(first.rightchild, second.rightchild));
트리의응용 7.3.5 이진트리의이질성격 public class BinaryTreeNode1 { } BinaryTreeNode1 leftchild; BinaryTreeNode1 rightchild; char operator; float value;
7.3 트리의운행 이진드리를이용한수식의계산 public float evaltree(binarytreenode1 tree) { if(tree!=null) { evaltree(tree.leftchild); evaltree(tree.rightchild); switch(tree.operator){ case + : tree.value=tree.leftchild.value+tree.rightchild.value break; case - : tree.value=tree.leftchild.value-tree.rightchild.value break; case * : tree.value=tree.leftchild.value*tree.rightchild.value break; case / : tree.value=tree.leftchild.value/tree.rightchild.value } } }
5. 이진탐색트리 이진탐색트리 (binary search tree) 이진트리에탐색을위한조건을추가하여정의한자료구조 이진탐색트리의정의 ⑴ 모든원소는서로다른유일한키를갖는다. ⑵ 왼쪽서브트리에있는원소의키들은그루트의키보다작다. ⑶ 오른쪽서브트리에있는원소의키들은그루트의키보다크다. ⑷ 왼쪽서브트리와오른쪽서브트리도이진탐색트리다.
5. 이진탐색트리 이진탐색트리의탐색연산 루트에서시작한다. 탐색할킷값 x를루트노드의킷값과비교한다. ( 킷값 x = 루트노드의킷값 ) 인경우 : 원하는원소를찾았으므로탐색연산성공 ( 킷값 x < 루트노드의킷값 ) 인경우 : 루트노드의왼쪽서브트리에대해서탐색연산수행 ( 킷값 x > 루트노드의킷값 ) 인경우 : 루트노드의오른쪽서브트리에대해서탐색연산수행 서브트리에대해서순환적으로탐색연산을반복한다.
5. 이진탐색트리 탐색연산알고리즘
5. 이진탐색트리 탐색연산예 ) 원소 11 탐색하기 1 찾는킷값 11 을루트노드의킷값 8 과비교 ( 찾는킷값 11 > 노드의킷값 8) 이므로오른쪽서브트리를탐색 2 ( 찾는킷값 11 > 노드의킷값 10) 이므로, 다시오른쪽서브트리를탐색 3 ( 찾는킷값 11 < 노드의킷값 14) 이므로, 왼쪽서브트리를탐색 4 ( 찾는킷값 11 = 노드의킷값 11) 이므로, 탐색성공! ( 연산종료 )
5. 이진탐색트리 이진탐색트리의삽입연산 1) 먼저탐색연산을수행 삽입할원소와같은원소가트리에있으면삽입할수없으므로, 같은원소가트리에있는지탐색하여확인한다. 탐색에서탐색실패가결정되는위치가삽입위치가된다. 2) 탐색실패한위치에원소를삽입한다.
5. 이진탐색트리 이진탐색트리에서의 삽입할자리탐색 삽입할노드만들기 탐색한자리에노드연결
5. 이진탐색트리 이진탐색트리에서의삽입연산예 ) 원소 4 삽입하기 1 찾는킷값 4 를루트노드의킷값 8 과비교하여, ( 찾는킷값 4 < 노드의킷값 8) 이므로, 왼쪽서브트리를탐색한다. 2 ( 찾는킷값 4 > 노드의킷값 3) 이므로, 오른쪽서브트리를탐색한다. 3 ( 찾는킷값 4 < 노드의킷값 5) 이므로, 왼쪽서브트리를탐색해야하는데왼쪽자식노드가없으므로탐색실패! 이때, 탐색실패가결정된위치즉, 왼쪽자식노드의위치가삽입위치가된다. 4 탐색작업으로찾은자리즉, 노드 5 의왼쪽자식노드자리에노드 4 를삽입한다.
5. 이진탐색트리 단순연결리스트로표현한이진트리에서의원소 4 삽입하기 q q 탐색실패! q
5. 이진탐색트리 이진탐색트리의삭제연산 1) 먼저탐색연산을수행 삭제할노드의위치를알아야하므로트리를탐색한다. 2) 탐색하여찾은노드를삭제한다. 노드의삭제후에도이진탐색트리를유지해야하므로삭제노드의경우에대한후속처리 ( 이진탐색트리의재구성작업 ) 가필요하다. 삭제할노드의경우 삭제할노드가단말노드인경우 : 차수가 0인경우 삭제할노드가하나의자식노드를가진경우 : 차수가 1인경우 삭제할노드가두개의자식노드를가진경우 : 차수가 2인경우
5. 이진탐색트리 단말노드의삭제연산 노드 4 를삭제하는경우
5. 이진탐색트리 노드 4 를삭제하는경우에대한단순연결리스트표현 노드를삭제하고, 삭제한노드의부모노드의링크필드에 null 설정
5. 이진탐색트리 자식노드가하나인노드, 즉차수가 1 인노드의삭제연산 노드를삭제하면, 자식노드는트리에서연결이끊어져서고아가된다. 후속처리 : 이진탐색트리의재구성 삭제한부모노드의자리를자식노드에게물려준다. 예 ) 노드 10 을삭제하는경우 탐색시작 8 1 10 > 8 3 10 2 5 2 10 = 10 자식노드이동 14 1 단계 : 삭제할노드탐색 2 단계 : 탐색한노드삭제 3 단계 : 후속처리 4 11 16
5. 이진탐색트리 예 ) 노드 10을삭제하는경우
5. 이진탐색트리 노드 10을삭제하는경우에대한단순연결리스트표현
5. 이진탐색트리 자식노드가둘인노드, 즉차수가 2 인노드의삭제연산 노드를삭제하면, 자식노드들은트리에서연결이끊어져서고아가된다. 후속처리 : 이진탐색트리의재구성 삭제한노드의자리를자손노드들중에서선택한후계자에게물려준다. 후계자선택방법방법 1) 왼쪽서브트리에서가장큰자손노드선택 왼쪽서브트리의오른쪽링크를따라계속이동하여오른쪽링크필드가 NULL 인노 드즉, 가장오른쪽에있는노드가후계자가된다. 방법 2) 오른쪽서브트리에서가장작은자손노드선택 오른쪽서브트리에서왼쪽링크를따라계속이동하여왼쪽링크필드가 NULL 인노 드즉, 가장왼쪽에있는노드가후계자가된다.
5. 이진탐색트리 삭제한노드의자리를물려받을수있는후계자노드
5. 이진탐색트리 예 ) 노드 8을삭제하는경우
5. 이진탐색트리 노드 5 를후계자로선택한경우 1 후계자노드 5 를원래자리에서삭제하여, 삭제노드 8 의자리를물려준다. 2 후계자노드 5 의원래자리는자식노드 4 에게물려주어이진탐색트리를재구성한다. ( 자식노드가하나인노드삭제연산의후속처리수행!) 노드 10 을후계자로선택한경우 1 후계자노드 10 을원래자리에서삭제하여, 삭제노드 8 의자리를물려준다. 2 후계자노드 10 의원래자리는자식노드 14 에게물려주어이진탐색트리를재구성한다. ( 자식노드가하나인노드삭제연산의후속처리수행!)
5. 이진탐색트리 노드 5를후계자로선택한경우 1 단계 : 노드삭제 노드삭제 8 2 단계 : 삭제한노드의자리를후계자에게물려주기 3 단계 : 후계자노드의원래자리를자식노드에게물려주기 3 10 2 4 5 14 11 16
5. 이진탐색트리 노드 8을후계자로선택한경우 노드삭제 8 1 단계 : 노드삭제 2 단계 : 삭제한노드의자리를후계자에게물려주기 3 단계 : 후계자노드의원래자리를자식노드에게물려주기 3 10 2 5 14 4 11 16
5. 이진탐색트리 이진탐색트리에서의삭제연산알고리즘
5. 이진탐색트리 이진탐색트리에서의삭제연산알고리즘
5. 이진탐색트리 : [ 예제 8-3] 이진탐색트리프로그램 연결자료구조를이용한이진탐색의 C 프로그램 이진탐색트리를단순연결리스트로구현하고, 탐색연산을수행하는프로그램 실행결과 >
5. 이진탐색트리 : [ 예제 8-3] 이진탐색트리프 로그램 001 #include<stdio.h> 002 #include<stdlib.h> 003 004 typedef struct treenode { 005 char key; // 데이터필드 006 struct treenode* left; // 왼쪽서브트리링크필드 007 struct treenode* right; // 오른쪽서브트리링크필드 008 } treenode; 009 010 typedef char element; // char을이진탐색트리 element의자료형으로정의 011 012 treenode* insertnode(treenode *p, char x) 013 { // 포인터 p가가리키는노드와비교하여노드 x를삽입하는연산 014 treenode *newnode; 015 if (p == NULL){ 016 newnode = (treenode*)malloc(sizeof(treenode)); 017 newnode->key = x; 018 newnode->left = NULL; 019 newnode->right = NULL; 020 return newnode; 021 } 022 else if (x < p->key) p->left = insertnode(p->left, x); 023 else if (x > p->key) p->right = insertnode(p->right, x); 024 else printf("\n 이미같은키가있습니다! \n"); 025 026 return p; 027 }
5. 이진탐색트리 : [ 예제 8-3] 이진탐색트리프로그램 029 void deletenode(treenode *root, element key) 030 { // root 노드부터탐색하여 key 값과같은노드를찾아삭제하는연산 031 treenode *parent, *p, *succ, *succ_parent; 032 treenode *child; 033 034 parent=null; 035 p=root; 036 while((p!= NULL) && (p->key!= key)){ // 삭제할노드의위치탐색 037 parent=p; 038 if(key < p->key) p=p->left; 039 else p=p->right; 040 } 041 if(p == NULL){ // 삭제할노드가없는경우 042 printf("\n 찾는키가이진트리에없습니다!!"); 043 return; 044 } 045 046 // 삭제할노드가단말노드인경우 047 if((p->left == NULL) && (p->right == NULL)){ 048 if(parent!= NULL){ 049 if(parent->left == p) parent->left=null; 050 else parent->right=null; 051 } 052 else root=null; 053 } 054
5. 이진탐색트리 : [ 예제 8-3] 이진탐색트리프 로그램 055 // 삭제할노드가한개의자식노드를가진경우 056 else if((p->left == NULL) (p->right == NULL)){ 057 if(p->left!= NULL) child=p->left; 058 else child=p->right; 059 060 if(parent!= NULL){ 061 if(parent->left == p) parent->left=child; 062 else parent->right=child; 063 } 064 else root=child; 065 } 066 067 // 삭제할노드가두개의자식노드를가진경우 068 else{ 069 succ_parent=p; 070 succ=p->left; 071 while(succ->right!= NULL){ 072 succ_parent=succ; 073 succ=succ->right; 074 } 075 if(succ_parent->left == succ) succ_parent->left=succ->left; 076 else succ_parent->right=succ->left; 077 p->key=succ->key; 078 p=succ; 079 } 080 free(p); 081 } 082
5. 이진탐색트리 : [ 예제 8-3] 이진탐색트리프로그램 083 treenode* searchbst(treenode* root, char x) 084 { // 이진탐색트리에서키값이 x인노드의위치를탐색하는연산 085 treenode* p; 086 p = root; 087 while (p!= NULL){ 088 if (x < p->key) p = p->left; 089 else if (x == p->key) return p; 090 else p = p->right; 091 } 092 printf("\n 찾는키가없습니다!"); 093 return p; 094 } 095 096 void displayinorder(treenode* root) 097 { // 이진탐색트리를중위순회하면서출력하는연산 098 if(root){ 099 displayinorder(root->left); 100 printf("%c_", root->key); 101 displayinorder(root->right); 102 } 103 } 104 105 void menu() 106 { 107 printf("\n*---------------------------*"); 108 printf("\n\t1 : 트리출력 "); 109 printf("\n\t2 : 문자삽입 );
5. 이진탐색트리 : [ 예제 8-3] 이진탐색트리프 로그램 110 printf("\n\t3 : 문자삭제 "); 111 printf("\n\t4 : 문자검색 "); 112 printf("\n\t5 : 종료 "); 113 printf("\n*---------------------------*"); 114 printf("\n메뉴입력 >> "); 115 } 116 117 int main() 118 { 119 treenode* root = NULL; 120 treenode* foundednode = NULL; 121 char choice, key; 122 123 root=insertnode(root, 'G'); // 트리만들기 124 insertnode(root, 'I'); 125 insertnode(root, 'H'); 126 insertnode(root, 'D'); 127 insertnode(root, 'B'); 128 insertnode(root, 'M'); 129 insertnode(root, 'N'); 130 insertnode(root, 'A'); 131 insertnode(root, 'J'); 132 insertnode(root, 'E'); 133 insertnode(root, 'Q'); 134 135 while(1){ 136 menu(); 137 choice = getchar(); getchar();
5. 이진탐색트리 : [ 예제 8-3] 이진탐색트리프 139 로그램 switch(choice){ 140 case 1 : printf("\t[ 이진트리출력 ] "); 141 displayinorder(root); printf("\n"); 142 break; 143 144 case 2 : printf(" 삽입할문자를입력하세요 : "); 145 key = getchar(); getchar(); 146 insertnode(root, key); 147 break; 148 149 case 3 : printf(" 삭제할문자를입력하세요 : "); 150 key = getchar(); getchar(); 151 deletenode(root, key); 152 break; 153 154 case 4 : printf(" 찾을문자를입력하세요 : "); 155 key = getchar(); getchar(); 156 foundednode = searchbst(root, key); 157 if (foundednode!= NULL) 158 printf("\n %c 를찾았습니다! \n", foundednode->key); 159 else printf("\n 문자를찾지못했습니다. \n"); 160 break; 161 162 case 5 : return 0; 163 default : printf(" 없는메뉴입니다. 메뉴를다시선택하세요! \n"); 164 break; 165 } 166 } 167 }
6. 히프 히프 (heap) 완전이진트리에있는노드중에서킷값이가장큰노드나킷값이가장작은노드를찾기위해서만든자료구조 최대히프 (max heap) 킷값이가장큰노드를찾기위한완전이진트리 { 부모노드의킷값 자식노드의킷값 } 루트노드 : 킷값이가장큰노드 최소히프 (min heap) 킷값이가장작은노드를찾기위한완전이진트리 { 부모노드의킷값 자식노드의킷값 } 루트노드 : 킷값이가장작은노드
6. 히프 히프의예
6. 히프 히프가아닌이진트리의예
6. 히프 히프의추상자료형 ADT Heap 데이터 : n개의원소로구성된완전이진트리로서각노드의킷값은그의자식노드의킷값보다크거나같다. ( 부모노드의킷값 자식노드의킷값 ) 연산 : heap Heap; item Element; createheap() = create an empty heap; // 공백히프의생성연산 isempty(heap) = if (heap is empty) then return true; else return false; // 히프가공백인지를검사하는연산 insertheap(heap, item) = insert item into heap; // 히프의적당한위치에원소 (item) 를삽입하는연산 deleteheap(heap) = if (isempty(heap)) then return error; else { item 히프에서가장큰원소 ; remove { 히프에서가장큰원소 }; return item; } // 히프에서킷값이가장큰원소를삭제하고반환하는연산 End Heap()
6. 히프 히프에서의삽입연산 1 단계 : 완전이진트리를유지하면서확장한노드에삽입할원소를임시저장 노드가 n 개인완전이진트리에서다음노드의확장자리는 n+1 번의노드가된다. n+1 번자리에노드를확장하고, 그자리에삽입할원소를임시저장한다. 2 단계 : 만들어진완전이진트리내에서삽입원소의제자 리를찾는다. 현재위치에서부모노드와비교하여크기관계를확인한다. { 현재부모노드의킷값 삽입원소의킷값 } 의관계가성립하지않으면, 현재부모노드의원소와삽입원소의자리를서로바꾼다.
6. 히프 히프에서의삽입연산예 1) 17 을삽입하는경우 노드를확장하여임시로저장한위치에서의부모노드와크기를비교하여히프의크기관계가성립하므로, 현재위치를삽입원소의자리로확정
6. 히프 히프에서의삽입연산예2) 23을삽입하는경우
6. 히프 히프에서의삽입연산알고리즘
6. 히프 1 현재히프의크기를하나증가시켜서노드위치를확장하고, 확장한노드번호가현재의삽입위치 i 가된다. 2 삽입할원소 item 과부모노드 heap[ i/2 ] 를비교하여 item 이부모노드보다작거나같으면현재의삽입위치 i 를삽입원소의위치로확정한다. 3 만약삽입할원소 item 이부모노드보다크면, 부모노드와자식노드의자리를바꾸어최대히프의관계를만들어야하므로부모노드 heap[ i/2 ] 를현재의삽입위치 heap[i] 에저장하고, 4 i/2 를삽입위치 i 로하여, 2~4 를반복하면서 item 을삽입할위치를찾는다. 5 찾은위치에삽입할노드 item 을저장하면, 최대히프의재구성작업이완성되므로삽입연산을종료한다.
6. 히프 히프에서의삭제연산 히프에서는루트노드의원소만을삭제할수있다. 1 단계 : 루트노드의원소를삭제하여반환한다. 2 단계 : 원소의개수가 n-1 개로줄었으므로, 노드의수가 n-1 인완전이진트리로조정한다. 노드가 n 개인완전이진트리에서노드수 n-1 개의완전이진트리가되기위해서마지막노드, 즉 n 번노드를삭제한다. 삭제된 n 번노드에있던원소는비어있는루트노드에임시저장한다. 3 단계 : 완전이진트리내에서루트에임시저장된원소의 제자리를 찾는다.
6. 히프 히프에서의삭제연산예
6. 히프 히프에서의삭제연산알고리즘
6. 히프 히프에서의삭제연산알고리즘 1 루트노드 heap[1] 을변수 item 에저장하고, 2 마지막노드의원소 heap[n] 을변수 temp 에임시저장한후에, 3 마지막노드를삭제하고히프배열의원소개수를하나감소한다. 4 마지막노드의원소였던 temp 의임시저장위치 i 는루트노드의자리인 1 번이된다. 5 현재저장위치에서왼쪽자식노드 heap[j] 와오른쪽자식노드 heap[j+1] 이있을때, 둘중에서킷값이큰자식노드의킷값과 temp 를비교하여, temp 가크거나같으면현재위치가 temp 의자리로확정된다. 6 만약 temp 가자식노드보다작으면, 자식노드와자리를바꾸고다시 5~ 6 을반복하면서 temp 의자리를찾는다. 7 찾은위치에 temp 를저장하여최대히프의재구성작업을완성하고 8 루트노드를저장한 item 을반환하는것으로삭제연산을종료한다.
6. 히프 순차자료구조를이용한히프의구현 부모노드와자식노드를찾기쉬운 1 차원배열의순차자료구조이용 1 차원배열을이용한히프의표현예
6. 히프 : [ 예제 8-4] 순차자료구조를이용한히프프로그램 순차자료구조를이용한히프 C 프로그램 공백히프에원소 10, 45, 19, 11, 96 을차례로삽입하면서최대히프를구성하고, 삭제연산을수행하여삭제된원소를출력하는프로그램 최대히프의루트노드는히프에서가장큰노드가되므로, 원소개수만큼삭제연산을수행하면서출력하면큰값부터작은값의내림차순으로출력되는것을확인할수있다. 실행결과 >
6. 히프 : [ 예제 8-4] 순차자료구조를이용한히프프로그램 01 #include <stdio.h> 02 #include <stdlib.h> 03 #define MAX_ELEMENT 100 04 typedef struct { // 히프에대한 1 차원배열과히프원소의갯수를구조체로묶어서선언 05 int heap[max_element]; 06 int heap_size; 07 } heaptype; 08 09 heaptype* createheap() // 공백히프를생성하는연산 10 { 11 heaptype *h = (heaptype *)malloc(sizeof(heaptype)); 12 h->heap_size=0; 13 return h; 14 } 15 16 void insertheap(heaptype *h, int item) // 히프에 item 을삽입하는연산 17 { 18 int i; 19 h->heap_size = h->heap_size +1; 20 i = h->heap_size; 21 while((i!=1) && (item > h->heap[i/2])){ 22 h->heap[i] = h->heap[i/2]; 23 i/=2; 24 } 25 h->heap[i] = item; 26 }
6. 히프 : [ 예제 8-4] 순차자료구조를이용한히프프로그 램 28 int deleteheap(heaptype *h) // 히프의루트를삭제하여반환하는연산 29 { 30 int parent, child; 31 int item, temp; 32 item = h->heap[1]; 33 temp = h->heap[h->heap_size]; 34 h->heap_size = h->heap_size -1; 35 parent = 1; 36 child = 2; 37 while(child <= h->heap_size) { 38 if((child < h->heap_size) && (h->heap[child]) < h->heap[child+1]) 39 child++; 40 if (temp >= h->heap[child]) break; 41 else { 42 h->heap[parent] = h->heap[child]; 43 parent = child; 44 child = child*2; 45 } 46 } 47 h->heap[parent] = temp; 48 return item; 49 } 50 51 printheap(heaptype *h) // 1차원배열히프의내용을출력하는연산 52 { 53 int i; 54 printf("heap : ");
6. 히프 : [ 예제 8-4] 순차자료구조를이용한히프프로그램 55 for(i=1; i<= h->heap_size; i++) 56 printf("[%d] ", h->heap[i]); 57 } 58 59 void main() 60 { 61 int i, n, item; 62 heaptype *heap = createheap(); 63 insertheap(heap, 10); 64 insertheap(heap, 45); 65 insertheap(heap, 19); 66 insertheap(heap, 11); 67 insertheap(heap, 96); 68 69 printheap(heap); 70 71 n= heap->heap_size; 72 for(i=1; i<=n; i++){ 73 item = deleteheap(heap); 74 printf("\n delete : [%d] ", item); 75 } 76 77 getchar(); 78 }
IT CookBook, C 로배우는쉬운자료구조 ( 개정판 )