ABC 10장

Similar documents
11장 포인터

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

chap 5: Trees

7장

Chapter 4. LISTS

이번장에서학습할내용 동적메모리란? malloc() 와 calloc() 연결리스트 파일을이용하면보다많은데이터를유용하고지속적으로사용및관리할수있습니다. 2

03_queue

A Hierarchical Approach to Interactive Motion Editing for Human-like Figures

ABC 11장

05_tree

Chapter 4. LISTS

제 1 장 기본 개념

06장.리스트

Chapter 4. LISTS

슬라이드 1

chap01_time_complexity.key

<4D F736F F F696E74202D20C1A63132B0AD20B5BFC0FB20B8DEB8F0B8AEC7D2B4E7>

슬라이드 1

08장.트리

Microsoft PowerPoint - ch10 - 이진트리, AVL 트리, 트리 응용 pm0600

Contents v 학습목표 자료구조큐에대한개념을스택과비교하여이해한다. 큐의특징과연산방법에대해알아본다. 순차표현방법을이용한큐와연결표현방법을이용한큐를구현해본다. 큐의응용방법을알아본다. v 내용 큐 큐의구현 큐의응용 2/74

<4D F736F F F696E74202D20C1A63137C0E520B5BFC0FBB8DEB8F0B8AEBFCD20BFACB0E1B8AEBDBAC6AE>


Chap 6: Graphs

Lab 3. 실습문제 (Single linked list)_해답.hwp

Lab 4. 실습문제 (Circular singly linked list)_해답.hwp

슬라이드 1

슬라이드 1

03장.스택.key

Microsoft PowerPoint - 07-chap05-Stack.ppt

11장 포인터

untitled

슬라이드 1

<322EBCF8C8AF28BFACBDC0B9AEC1A6292E687770>

PowerPoint 프레젠테이션

원형연결리스트에대한설명중틀린것은 모든노드들이연결되어있다 마지막에삽입하기가간단한다 헤더노드를가질수있다 최종노드포인터가 NULL이다 리스트의 번째요소를가장빠르게찾을수있는구현방법은무엇인가 배열 단순연결리스트 원형연결리스트 이중연결리스트 단순연결리스트의노드포인터 가마지막노드를

A Dynamic Grid Services Deployment Mechanism for On-Demand Resource Provisioning

o 스택 (stack) ~ 쌓아놓은더미 1. 스택의개요 - 2 -

PowerPoint Template

Microsoft PowerPoint - ch07 - 포인터 pm0415

Microsoft PowerPoint - 자료구조2008Chap06

슬라이드 1

Chapter 08. 트리(Tree)

OCW_C언어 기초

Microsoft PowerPoint - 08-chap06-Queue.ppt

5.스택(강의자료).key

Microsoft PowerPoint - chap11-포인터의활용.pptx

Microsoft PowerPoint - 08-Queue.ppt

PowerPoint 프레젠테이션

Algorithms

슬라이드 1

C 언어 강의노트

슬라이드 1

chap x: G입력

ABC 9장

PowerPoint 프레젠테이션

<4D F736F F F696E74202D20C1A637C0E52DB0EDB1DEBFACB0E1B8AEBDBAC6AE2E >

03장.스택

[ 마이크로프로세서 1] 2 주차 3 차시. 포인터와구조체 2 주차 3 차시포인터와구조체 학습목표 1. C 언어에서가장어려운포인터와구조체를설명할수있다. 2. Call By Value 와 Call By Reference 를구분할수있다. 학습내용 1 : 함수 (Functi

Data structure: Assignment 1 Seung-Hoon Na October 1, Assignment 1 Binary search 주어진 정렬된 입력 파일이 있다고 가정하자. 단, 파일내의 숫자는 공백으로 구 분, file내에 숫자들은

Microsoft PowerPoint - chap13-입출력라이브러리.pptx

리스트 (list), 선형리스트 (linear list): 순서를가진항목들의모임 집합 : 항목간의순서의개념이없음 L = n ( item0, item1,..., item -1) l 리스트의예 l 요일 : ( 일요일, 월요일,, 토요일 ) l 한글자음의모임 : ( ㄱ, ㄴ

1장. 리스트

Microsoft PowerPoint - chap10-함수의활용.pptx

02장.배열과 클래스

Microsoft PowerPoint - chap09.ppt

Algorithms

목차 포인터의개요 배열과포인터 포인터의구조 실무응용예제 C 2

슬라이드 1

untitled

C++ Programming

1 장 C 언어복습 표준입출력배열포인터배열과포인터함수 const와포인터구조체컴파일러사용방법 C++ 프로그래밍입문

K&R2 Reference Manual 번역본

학습목차 2.1 다차원배열이란 차원배열의주소와값의참조

컴파일러

chap 5: Trees

e-비즈니스 전략 수립

Microsoft PowerPoint - 제5장-스택의응용.pptx

중간고사 (자료 구조)

슬라이드 1

슬라이드 1

Microsoft PowerPoint - 제4장-스택과큐.pptx

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

슬라이드 1

BMP 파일 처리


<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C D616E2E637070>

Microsoft PowerPoint - chap04-연산자.pptx

4장

chap8.PDF

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CC0E7B0EDB0FCB8AE5C53746F636B5F4D616E D656E74732E637070>

Microsoft PowerPoint - chap03-변수와데이터형.pptx

비트와바이트 비트와바이트 비트 (Bit) : 2진수값하나 (0 또는 1) 를저장할수있는최소메모리공간 1비트 2비트 3비트... n비트 2^1 = 2개 2^2 = 4개 2^3 = 8개... 2^n 개 1 바이트는 8 비트 2 2

chap x: G입력

Lab 5. 실습문제 (Double linked list)-1_해답.hwp

adfasdfasfdasfasfadf

< E20C6DFBFFEBEEE20C0DBBCBAC0BB20C0A7C7D12043BEF0BEEE20492E707074>

0. 표지에이름과학번을적으시오. (6) 1. 변수 x, y 가 integer type 이라가정하고다음빈칸에 x 와 y 의계산결과값을적으시오. (5) x = (3 + 7) * 6; x = 60 x = (12 + 6) / 2 * 3; x = 27 x = 3 * (8 / 4

제 11 장포인터 유준범 (JUNBEOM YOO) Ver 본강의자료는생능출판사의 PPT 강의자료 를기반으로제작되었습니다.

Microsoft PowerPoint - chap-11.pptx

Transcription:

10 장구조체와리스트처리 0

자기참조구조체 자기참조구조체는자기자신의형을참조하는포인터멤버를가짐 이러한자료구조를동적자료구조라고함 배열이나단순변수는일반적으로블록을진입할때메모리할당을받지만, 동적자료구조는기억장소관리루틴을사용하여명시적으로메모리할당을요구함 10-1

자기참조구조체 10-2

자기참조구조체 예제 struct list { int struct list a; data; *next; dat a next 10-3

자기참조구조체 동작예제 struct list a, b, c; a.data = 1; b.data = 2; c.data = 3; a.next = b.next = c.next = NULL; a b c 1 NULL 2 NULL 3 NULL 10-4

동작예제 ( 계속 ) a.next = &b; b.next = &c; 자기참조구조체 a b c 1 2 3 NULL - a.next -> data : 값 2 - a.next -> next -> data : 값 3 10-5

선형연결리스트 선형연결리스트는자료구조체들이순차적으로매달려있는빨래줄과같음 헤드포인터는이리스트상의첫번째원소를포인트하고, 각원소는다음원소를포인트함 그리고마지막원소는 NULL 값을가짐 10-6

앞으로사용할헤더파일 선형연결리스트 /* In file list.h */ #include <stdio.h> #include <stdlib.h> typedef char DATA; /* will use char in examples */ struct linked_list { ; DATA d; struct linked_list *next; typedef struct linked_list typedef ELEMENT ELEMENT; *LINK; 10-7

선형연결리스트예제 세개의문자 n, e, w 를저장하는선형연결리스트생성 head n e w NULL 10-8

선형연결리스트예제 1. n 을위한노드생성및저장 head = malloc(sizeof(element)); head -> d = 'n'; head -> next = NULL; head n NULL 10-9

선형연결리스트예제 2. e 을위한노드를생성하고 n 노드에연결 head -> next = malloc(sizeof(element)); head -> next -> d = 'e'; head -> next -> next = NULL; head n e NULL 10-10

선형연결리스트예제 3. w 을위한노드를생성하고 e 노드에연결 head -> next -> next = malloc(sizeof(element)); head -> next -> next -> d = 'w'; head -> next -> next -> next = NULL; head n e w NULL 10-11

리스트연산 기본적인선형리스트연산 1. 리스트생성 2. 원소개수세기 3. 원소탐색 4. 두리스트결합 5. 원소삽입 6. 원소삭제 10-12

리스트연산 리스트생성 주어진문자열을리스트로변환하는함수 ( 재귀버전 ) #include <stdlib.h> #include "list.h" LINK string_to_list(char s[]) { LINK head; if (s[0] == '\0') /* base case */ return NULL; else { head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; 10-13

리스트연산 리스트생성 호출예 list = string_to_list( new ); // LINK list list string_to_list( new ) 10-14

리스트연산 리스트생성 string_to_list( new )... head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; head n string_to_list( ew ) 10-15

리스트연산 리스트생성 string_to_list( ew )... head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; head e string_to_list( w ) 10-16

리스트연산 리스트생성 string_to_list( w )... head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; head w string_to_list( ) 10-17

리스트연산 리스트생성 string_to_list( )... if (s[0] == '\0') /* base case */ return NULL; 10-18

리스트연산 리스트생성 string_to_list( w )... head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; head w string_to_list( ) 10-19

리스트연산 리스트생성 string_to_list( w )... head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; head w string_to_list( ) NULL 10-20

리스트연산 리스트생성 string_to_list( w )... head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; head w NULL 10-21

리스트연산 리스트생성 string_to_list( ew )... head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; head e string_to_list( w ) 10-22

리스트연산 리스트생성 string_to_list( ew )... head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; head e string_to_list( w ) w NULL 10-23

리스트연산 리스트생성 string_to_list( ew )... head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; head e w NULL 10-24

리스트연산 리스트생성 string_to_list( new )... head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; head n string_to_list( ew ) 10-25

리스트연산 리스트생성 string_to_list( new )... head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; head n string_to_list( ew ) e w NULL 10-26

리스트연산 리스트생성 string_to_list( new )... head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; head n e w NULL 10-27

리스트연산 리스트생성 호출 list = string_to_list( new ); // LINK list list string_to_list( new ) 10-28

리스트연산 리스트생성 호출 list = string_to_list( new ); // LINK list list string_to_list( new ) n e w NULL 10-29

리스트연산 리스트생성 호출 list = string_to_list( new ); // LINK list list n e w NULL 10-30

리스트연산 리스트생성 주어진문자열을리스트로변환하는함수 ( 반복버전 ) LINK s_to_l(char s[ ]){ LINK head = NULL, tail; int i; if (s[0]!= '\0') { // first element head = malloc(sizeof(element)); head -> d = s[0]; tail = head; for (i = 1; s[i]!= '\0'; ++i) { // add to tail tail -> next = malloc(sizeof(element)); tail = tail -> next; tail -> d = s[i]; tail -> next = NULL; return head; // end of list 10-31

리스트연산 s_to_l("ab") 호출에의한리스트생성단계 head t ai l A? head t ai l A?? head A B? t ai l head A B NULL t ai l 10-32

리스트연산 원소세기 리스트의원소수를세는함수 ( 재귀버전 ) int count(link head){ if (head == NULL) return 0; else return (1 + count(head -> next)); 10-33

리스트연산 원소세기 리스트의원소수를세는함수 ( 반복버전 ) int count_it(link head){ int cnt = 0; for ( ; head!= NULL; head = head -> next) ++cnt; return cnt; 10-34

리스트연산 리스트연결 두리스트를연결하는함수 ( 재귀버전 ) void concatenate(link a, LINK b){ assert(a!= NULL); if (a -> next == NULL) a -> next = b; else concatenate(a -> next, b); 10-35

리스트처리함수 자기참조리스트를처리하기위한재귀함수의일반적인형태 void generic_recursion(link head){ if (head == NULL) else do the base case do the general case and recur with generic_recursion(head -> next) 10-36

리스트연산 삽입 리스트에서현재위치에새로운원소를삽입할경우, 고정된시간내에삽입을할수있음 반대로큰배열에새로운값을삽입할경우, 배열값의순서를유지해야하기때문에삽입에걸리는시간은평균적으로배열길이에비례함 10-37

리스트연산 삽입 리스트에서 p1 과 p2 가포인트하고있는인접한두원 소사이에 q 가포인트하고있는원소삽입 p1 p2... A C... q B NULL p1 p2... A C... q B 10-38

리스트연산 삽입 삽입함수 void insert(link p1, LINK p2, LINK q){ assert(p1 -> next == p2); p1 -> next = q; /* insert */ q -> next = p2; 10-39

리스트연산 삭제 리스트에서 p 가포인트하고있는다음원소삭제 삭제되는원소를 free() 를사용하여반납해야함 p... A B C... p... A B C... 10-40

삭제함수 리스트연산 삭제 void delete_list(link head) { if (head!= NULL) { delete_list(head -> next); free(head); // release storage 10-41

수식표기법 중위표기법예 ) 3 + 7 전위표기법예 ) +, 3, 7 후위표기법 ( 폴리시표기법 ) 예 ) 3, 7, + 10-42

폴리시표기법 중위수식을후위수식으로만드는방법 1. 중위수식을연산자의우선순위에따라완전한괄호표현으로변환예 ) 1 + 3 * 4 (1 + (3 * 4)) 2. 각연산자를그연산자를포함하는괄호중제일가까운닫는괄호뒤로보냄예 ) (1 + (3 * 4) ) (1 (3, 4) * ) + 3. 괄호제거예 ) 1, 3, 4, *, + 10-43

알고리즘 폴리시수식계산 - 수식의각항목을왼쪽에서오른쪽으로검사하며다음과같은일을반복한다. 1. 현재검사되는항목이숫자이면다음항목을검사한다. 2. 현재검사되는항목이연산자이면앞의두항목 ( 숫자 ) 을이연산자의피연산자로하여계산한후새로운항목으로삽입한다. 3. 이러한일은하나의숫자가남을때까지반복하고, 마지막남은수가이수식의값이다. 10-44

13, 4, -, 2, 3, *, + 폴리시수식계산예제 13, 4, -, 2, 3, *, + 1 2 3 9 (=13 4), 2, 3, * + 4 5 6 9, 6 (= 2 * 3), + 15 (= 9 + 6) 7 10-45

스택 선형연결리스트로구현한스택 st ack cnt el em dat a stack cnt elem NULL t op top data dat a data...... dat a NULL data 10-46

스택구현 stack.h #include <stdio.h> #include <stdlib.h> #define EMPTY 0 #define FULL 10000 typedef char data; typedef enum {false, true boolean; struct elem { // element on the stack data d; struct elem *next; ; 10-47

스택구현 stack.h typedef struct elem elem; struct stack { int cnt; // a count of the elements elem *top; // ptr to the top element ; typedef struct stack stack; void initialize(stack *stk); void push(data d, stack *stk); data pop(stack *stk); data top(stack *stk); boolean empty(const stack *stk); boolean full(const stack *stk); 10-48

#include "stack.h" 스택구현 - 함수 void initialize(stack *stk){ stk -> cnt = 0; stk -> top = NULL; void push(data d, stack *stk){ elem *p; p = malloc(sizeof(elem)); p -> d = d; p -> next = stk -> top; stk -> top = p; stk -> cnt++; 10-49

스택구현 - 함수 data pop(stack *stk){ data d; elem *p; d = stk -> top -> d; p = stk -> top; stk -> top = stk -> top -> next; stk -> cnt --; free(p); return d; 10-50

스택구현 - 함수 data top(stack *stk){ return (stk -> top -> d); boolean empty(const stack *stk){ return ((boolean) (stk -> cnt == EMPTY)); boolean full(const stack *stk){ return ((boolean) (stk -> cnt == FULL)); 10-51

스택 - 검사프로그램 #include "stack.h" int main(void){ char str[ ] = "My name is joanna Kelly!"; int i; stack s; initialize(&s); // initialize the stack printf(" In the string: %s\n", str); for (i = 0; str[i]!= '\0'; ++i) if (!full(&s)) push(str[i], &s); // push a char on the stack printf("from the stack: "); while (!empty(&s)) putchar(pop(&s)); // pop a char off the stack putchar('\n'); return 0; 10-52

스택 - 검사프로그램 출력 In the string : My name is Jonna Kelly! From the stack :!yllek annoj si eman ym 10-53

폴리시수식계산 2- 스택알고리즘 1. 폴리시스택이공백이면, 연산스택의 top 을답으로하고중지한다. 2. 폴리시스택이공백이아니면, 폴리시스택에서 pop 하여그것을 d 에배정한다. ( 이알고리즘에서는자료보관을위해 d, d1, d2 를사용한다.) 3. d 가피연산자라면, 연산스택에 d 를 push 한다. 4. d 가연산자라면, 연산스택을두번 pop 하여처음것을 d2 에배정하고다음것을 d1 에배정한다. d 연산자를 d1 과 d2 피연산자에적용하여계산하고, 결과를연산스택에 push 한다. 단계 1 부터다시수행한다. 10-54

2- 스택알고리즘예제 (1) 13 4 4 폴리시스택 연산스택 - 2 3 * + - 2 3 * + 13-2 3 * + 4 13 2 3 * + 9 10-55

2- 스택알고리즘예제 (2) 폴리시스택 연산스택 3 * + 2 9 * + 3 2 9 + 6 9 15 10-56

큐 큐는 front 와 rear 가있고, rear 에서는삽입이, front 에서는삭제가일어남 연산 - 초기화 - 삽입 - 삭제 - 상태확인 10-57

큐구현 리스트로의큐구현 queue cnt f r ont r ear el em el em el em dat a dat a dat a NULL 10-58

큐구현 queue.h #include <assert.h> #include <stdio.h> #include <stdlib.h> #define EMPTY 0 #define FULL 10000 typedef unsigned int data; typedef enum {false, true boolean; struct elem { data d; struct elem *next; ; typedef struct elem elem; // an element in the queue 10-59

큐구현 queue.h struct queue { int cnt; // a count of the elements elem *front; // ptr to the front element elem *rear; // ptr to the rear element ; typedef struct queue queue; void initialize(queue *q); void enqueue(data d, queue *q); data dequeue(queue *q); data front(const queue *q); boolean empty(const queue *q); boolean full(const queue *q); 10-60

트리 노드라고하는원소의유한집합 루트, 리프노드, 부트리 루트노드 a 부트리의루트 b f g 부트리 c d e h 리프노드 10-61

이진트리 한노드가최대 2 개의자식노드를갖는트리 G D I B F H J A C E 10-62

이진트리 헤더파일 tree.h #include <assert.h> #include <stdio.h> #include <stdlib.h> typedef char DATA; struct node { DATA d; struct node *left; struct node *right; ; typedef struct node NODE; typedef NODE *BTREE; #include "fct_proto.h" /* function prototypes */ 10-63

중위순회 1. 왼쪽부트리방문 2. 루트방문 3. 오른쪽부트리방문 전위순회 1. 루트방문 2. 왼쪽부트리방문 3. 오른쪽부트리방문 후위순회 1. 왼쪽부트리방문 2. 오른쪽부트리방문 3. 루트방문 이진트리순회 10-64

중위순회 void inorder(btree root){ if (root!= NULL) { inorder(root -> left); printf("%c", root -> d); inorder(root -> right); 10-65

중위순회 void inorder(btree root){ G if (root!= NULL) { inorder(root -> left); printf("%c", root -> d); D I inorder(root -> right); B F H J A C E 10-66

중위순회 void inorder(btree root){ G if (root!= NULL) { inorder(root -> left); printf("%c", root -> d); D I inorder(root -> right); B F H J A C E 출력 A B C D E F G H I J 10-67

전위순회 void preorder(btree root){ if (root!= NULL) { printf("%c ", root -> d); preorder(root -> left); preorder(root -> right); 10-68

전위순회 void preorder(btree root){ G if (root!= NULL) { printf("%c ", root -> d); preorder(root -> left); D I preorder(root -> right); B F H J A C E 10-69

전위순회 void preorder(btree root){ G if (root!= NULL) { printf("%c ", root -> d); preorder(root -> left); D I preorder(root -> right); B F H J A C E 출력 G D B A C F E I H J 10-70

후위순회 void postorder(btree root){ if (root!= NULL) { postorder(root -> left); postorder(root -> right); printf("%c ", root -> d); 10-71

후위순회 void postorder(btree root){ G if (root!= NULL) { postorder(root -> left); postorder(root -> right); D I printf("%c ", root -> d); B F H J A C E 10-72

후위순회 void postorder(btree root){ G if (root!= NULL) { postorder(root -> left); postorder(root -> right); D I printf("%c ", root -> d); B F H J A C E 출력 A C B E F D H J I G 10-73

트리생성 BTREE new_node( ){ return (malloc(sizeof(node))); BTREE init_node(data d1, BTREE p1, BTREE p2){ BTREE t; t = new_node( ); t -> d = d1; t -> left = p1; t -> right = p2; return t; 10-74

트리생성 BTREE create_tree(data a[], int i, int size) { if (i >= size) return NULL; else return (init_node(a[i], create_tree(a, 2 * i + 1, size), create_tree(a, 2 * i + 2, size))); 0 1 2 3 4 5 6 7 8 9 G D I B F H J A C E 10-75

일반적인연결리스트 어떤자료구조는배열과리스트를결합하여사용함 일반트리 - 형제노드는선형리스트로자식노드는배열의인덱스로접근 a t[0] a b f g b f g c d e h NULL c d e h NULL NULL NULL NULL 10-76

일반트리 일반트리의원소를위한형정의 #include <assert.h> #include <stdio.h> #include <stdlib.h> typedef char DATA; struct node { int child_no; DATA d; struct node *sib; ; typedef struct node NODE; typedef NODE *GTREE; #include "fct_proto.h" /* function prototypes */ 10-77

노드생성함수 일반트리 GTREE new_gnode(){ return (malloc(sizeof(node))); GTREE init_gnode(data d1, int num, GTREE sibs){ GTREE temp; temp = new_gnode(); temp -> d = d1; temp -> child_no = num; temp -> sib = sibs; return temp; 10-78

일반트리 일반트리생성 t[0] = init_gnode('a', 1, NULL); t[1] = init_gnode('b', 2, NULL); t[1] -> sib = init_gnode('f', 6, NULL); t[1] -> sib -> sib = init_gnode('g', 7, NULL); t[2] = init_gnode('c', 3, NULL); t[2] -> sib = init_gnode('d', 4, NULL); t[2] -> sib -> sib = init_gnode('e', 5, NULL); t[3] = t[4] = t[5] = NULL; t[6] = init_gnode('h', 8, NULL); t[7] = t[8] = NULL; 10-79

일반트리 전위순회함수 /* Preorder traversal of general trees. */ void preorder_g(gtree *t, int ind) { GTREE tmp; /* tmp traverses the sibling list */ tmp = t[ind]; /* t[ind] is the root node */ while (tmp!= NULL) { printf("%c %d\n", tmp -> d, tmp -> child_no); preorder_g(t, tmp -> child_no); tmp = tmp -> sib; 10-80