basic data structures, make, gdb -...

29
Basic Data Structures, Make, GDB

Upload: others

Post on 07-Sep-2019

12 views

Category:

Documents


0 download

TRANSCRIPT

Basic Data Structures, Make, GDB

2/17

Contents

▣Data Structures Linked List

Tree

Hash

▣Make 사용법

▣디버거(gdb) 사용법

3/17

Reference

▣The C Programming language, Brian W. Kernighan, Dennis M. Ritchie, Prentice-Hall

▣Teach yourself C, Peter Aitken, Simon & Schuster

▣Programming with GNU Software, Mike Loukides, O’REILLY

▣Fundamentals of Data Structures in C, Ellis Horowitz, Computer Science Press

4/17

Linked List

▣같은 형태의 데이터타입을 연결한 데이터타입 Single linked list

Double linked list

▣Operations next_node();

Previous_node();

add_tail();

add_head();

remove_head();

remove_tail();

insert_at();

remove_at();

5/17

Single Linked List

▣한 방향으로만 연결이 되어잇음

▣Stack, Queue 등 다른 data structure의 기본이 됨

struct Node {

int value;

struct Node *next;

};

1 2 3

6/17

head

Single Linked List

struct Node *head = NULL;

struct Node *tail = NULL;

struct Node *alloc_node( int value ) {

struct Node *node = ( struct Node * )

malloc( sizeof( struct Node ) );

node->value = value;

node->next = NULL;

}

void add_head( int value ) {

struct Node *node = alloc_node( value )

if( head == NULL ) { // tail is NULL too.

head = tail = node;

} else {

node->next = head;

head = node;

}

}

1

tail

2

7/17

head

Single Linked List

void add_tail( int value ) {

struct Node *node = alloc_node( value )

if( tail == NULL ) { // head is NULL too.

head = tail = node;

} else {

tail->next = node;

tail = node;

}

}

1

tail

2 3

8/17

head

Single Linked List

int remove_head( int *result ) {

if( head == NULL ) { // tail is NULL too.

*result = 0;

return -1;

}

struct Node *temp = head;

head = head->next;

*result = temp->value;

free( temp );

return 0;

}

1

tail

2 3

temp

▣Access temp after free() free() 후 temp의 값(*temp)를 시도하면 안된다.

9/17

Double Linked List

▣양 방향으로 연결이 되어잇음

▣prev, next를 통해 자유롭게list 안을 traverse할수 잇음.

struct Node {

int value;

struct Node *prev;

struct Node *next;

};

1 2 3

10/17

head

Double Linked List

struct Node *alloc_node( int value ) {

struct Node *node = ( struct Node * )

malloc( sizeof( struct Node ) );

node->value = value;

node->prev = NULL;

node->next = NULL;

}

void add_head( int value ) {

struct Node *node = alloc_node( value )

if( tail == NULL ) { // head is NULL too.

head = tail = node;

} else {

node->next = head;

head->prev = node;

head = node;

}

}

1

tail

2

Implement add_tail

11/17

head

Double Linked List

int remove_tail( int *result ) {

if( tail == NULL ) { // head is NULL too.

*result = 0;

return -1;

} else {

struct Node *temp = tail;

tail = tail->prev;

tail->next = NULL;

*result = temp->value;

free( temp );

}

return 0;

}

1

tail

2 3

temp

12/17

Tree

▣Tree: Acyclic Graph Root로부터 아래 방향으로 내

려가며 엔트리들을 접근할 수잇다.

▣일반적으로 hierarchical 구조나 search 등을 할때 많이사용된다.

struct BinaryNode {

int value;

struct Node *left;

struct Node *right;

};

struct BinaryNodeWithParent {

int value;

struct Node *parent;

struct Node *left;

struct Node *right

};

struct NodeWithManyChildren {

int value;

struct Node *children[10];

};

struct Node *root = NULL;

13/17

root

Tree

1 2

3 4 5

6

node_root->left = node1;

node_root->right = node2;

node1->left = node3;

node2->left = node4;

node2->right = node5;

node5->left = node 6;

node_root->right->right->left == node6

14/17

root

Tree

1 2

3 4 5

6

▣Root의 left child : node 1

▣Root의 right child : node 2

▣Node 4의 parent : node 2

▣Node 4의 sibling : node 5

▣Node 3과 Node 4는sibling? No

▣Leaf nodes : node 3, 4, 6

▣Degree of root : 2

▣Height : 4

15/17

Tree Traverse and Search

▣Tree Traverse Depth-First

• Recursive call로 구현 가능

• VLR : root, 1, 3, 2, 4, 5, 6

• LVR : 3, 1, root, 4, 2, 6, 5

• LRV : 3, 1, 4, 6, 5, 2, root Breadth-First

• Buffer(queue)가 필요

▣Search Depth-First Search (DFS)

Breadth-First Search (BFS)

root

1 2

3 4 5

6

16/17

root

Depth-First Traverse

1 2

3 4 5

6

void find_leaves_dfs( struct Node *node ) {

if( node->left == NULL &&

node->right == NULL ) {

printf( “This is leaf : %d”, node->value );

}

if( node->left != NULL ) {

find_leaves( node->left );

}

if( node->right != NULL ) {

find_leaves( node->right );

}

}

visit

left

right

17/17

Binary Tree

▣Definition Node의 값보다 작은 값을 가지는 node는 왼쪽에, 큰 값을 가지

는 node는 오른쪽에 잇는 tree

▣장점 쉽게 구현이 가능하다.

O(Log2(n))에 원하는 값을 찾을수 잇다.

▣단점 한쪽으로 쏠릴(skewed)수 잇고 이 경우 값을 찾는데 오래 걸릴

수 잇다.

18/17

Hash

▣ Hash function 값을 이용하여 키를 생성하는 함수

• Hash( 값 ) = key• Hash( x ) = x % 7;• Hash( “test” ) = (116 + 101 + 115 + 116) % 13 = 6

최대한 서로 다른 값을 가지도록 만드는 것이 중요 주로 bit operation이나 arithmetic 연산으로 구성

▣ Tree + Hash, Array + Hash 등의 조합을 이용

▣ Hash table (static hash) Table의 index를 hash로 결정

• index of “test” = hash( “test” ) = 6• index of “cs230” = hash( “cs230” ) = 12

Table의 각 index에는 hash bucket이 잇고, 그 bucket안에 실제 값들이 들어잇음.

19/17

▣Hash conflicts 같은 hash 값을 가지는 서로 다른 값이 존재할수 잇음

• hash( “jinsoo” ) == hash( “thread” ) 해결책 : Bucket을 크게 한다, Conflict block끼리 linked list로

잆는다(chaining), 비어잇는 옆 bucket에 넣는다(linear insert), …

“cs230” “test”

4 5 6 7 8 9 10 11 12

“jinsoo” “cs230” “test”

4 5 6 7 8 9 10 11 12

“jinsoo”“thread”

Chaining Linear insertion

“thread”

20/17

Hash Implementation

struct hash_bucket {

int count; // Word count

char *string; // Value

struct hash_bucket *next; // Conflict chain

};

struct hash_bucket *hash_table[13] = { NULL };

struct hash_bucket *insert_into_hash ( char *key ) {

int hashvalue = hash( key );

struct hash_bucket *entry = ( struct hash_bucket *)malloc( sizeof( struct hash_bucket ) );

entry->string = strdup( key ); // Initialize entry

struct hash_bucket *bucket = hash_table[ hashvalue ];

if( bucket == NULL ) {

hash_table[ hashvalue ] = entry;

} else {

entry->next = bucket;

bucket = entry;

}

return entry;

}

21/17

struct hash_bucket *find_hash ( char *key ) {

int hashvalue = hash( key );

struct hash_bucket *bucket = hash_table[ hashvalue ];

while( bucket != NULL ) { // Chain을 포함하여 값을 확인한다.

if( strcmp( bucket->string, key ) == 0 ) {

return bucket;

}

bucket = bucket->next;

}

return NULL;

}

22/17

Make (1/2)

▣ 다중파일 컴파일

1) main 함수를 포함하지 않는 .c 파일을 컴파일하여 .o 파일 생성

• Ex) gcc –c add.c sub.c

2) main 함수를 포함하는 .c 파일과 1)에서 생성한 .o 파일을 함께 컴파일

• ex) gcc –o calculator calc.c add.o sub.o

▣ Make 란?

다수의 파일로 이루어진 프로젝트의 컴파일을 쉽게 하기 위한 도구

작업디렉토리의 Makefile 에 정의된 작업을 수행

사용법 : make

23/17

Make (2/2)

▣ Makefile 예제# 매크로 선언 : 매크로이름 = 내용

OBJS = addmult.o subdiv.o

#target name: dependency

#depencency는 아래 명령을 수행하기 전 미리 수행되어야 하는 내용

all: EX_A EX_B

rm -fr *.o

#EX_A라는 target을 수행하기 위해서는 OBJS에 정의된 addmult.o 와 subdiv.o 가 미리 컴파일 되어 있어야 함

#dependency 리스트에 .o 파일이 지정되어 있으면 같은 이름의 .c 파일을 –c 옵션으로 자동 컴파일 함

EX_A : a_test.c $(OBJS)

$(CC) $^ -o $@

# $(매크로이름)으로 매크로 치환가능, $@ : 타켓 이름, $^는 dependency list를 나타냄

EX_B : b_test.c $(OBJS)

$(CC) $^ -o $@

clean:

rm -fr EX_A

rm -fr EX_B

rm -fr *.o

24/17

GDB (1/5)

▣gdb 시작하기 gcc –g 옵션으로 컴파일 한다

gdb 프로그램명 [core-dump] 로 디버거 시작

• -d source_directory : 소스파일이 잇는 디렉토리 지정

• -x file : 디버거 시작 후 바로 실행할 명령어를 지정한 파일

• -batch : -x로 지정된 파일을 수행하고 디버거 종료

프롬프트에서 명령어 입력

• help 명령어 : 해당 명령어에 대한 도움말 보기

• quit : 디버거 종료

25/17

GDB (2/5)

▣ 파일 수행하기 : run [arguments] [pipe or redirections]

arguments는 shell 에서 입력하는 것과 동일

arguments가 지정되지 않으면 바로 젂에 사용한 argument 사용

에러 없이 종료 시 : Program exited with code n 을 출력

비정상적인 종료(ex. segmentation fault)시 gdb로 제어권이 넘어옴

본격적인 디버깅 시작~

프로그램 수행 도중 Ctrl+C 를 이용하여 중단 가능

26/17

GDB (3/5)

▣ list [line1,line2] | [routine-name] :

no args : 정지시점 위의 source code 10줄을 본다

• 반복해서 list를 치면 이어지는 10줄씩 계속 보여준다

• “list –” 를 이용하여 위방향으로 10줄씩 볼 수 잇다.

line1, line2 : 두 줄 사이의 source code 를 보여준다

routine-name : 특정함수의 code를 보여준다

▣ backtrace, where

정지시점에서 활성화되어 잇는 모든 프로시저의 리스트를 보여줌

up/down으로 프레임갂 이동할 수 잇다.(gdb)backtrace

#0 0x22c8 in march_to_infinity() at badref.c:16

#1 0x2324 in setup() at badref.c:25

#2 0x2340 in main() at badref.c:30

(gdb)

27/17

GDB (4/5)

▣ whatis [변수명] : 변수의 type 을 알 수 잇다.

▣ print 연산 연산 := literal 상수| [변수명] | [함수호출 문법] | {연산} operator {연산}

변수 값 혹은 함수의 리턴 값을 알 수 잇다.

$n : 히스토리, 이후 참고가능

▣ set variable 변수명 = 값

(gdb) whatis p

type = int *

(gdb) print p

$1 = (int *)0xf8000000

(gdb) print *p

$2 = Cannot access memory at address 0xf8000000

(gdb) print $1-1

$3 = (int *)0xf7fffffc

(gdb) print *$3

$5 = 0

28/17

GDB (5/5)

▣ 정지점 설정 (break명령)

프로그램 실행 중 디버깅을 위해 정지시키고 gdb명령을 실행 할 수 잇다. 다수의 정지점을 설정할 수 잇다.

• break line-number

• break function-name

• break line-or-function if condition

▣ 관찰점 설정

watch condition• 예) watch testsize>10000 //testsize 변수 값이 10000 보다 크면 정지

• condition이 없으면 변수값이 바뀔때 정지

▣ 실행 재개

continue : 다음 정지점까지 실행

step : 한 줄씩 실행

next : 한 줄씩 실행 중 함수를 만나면 함수 젂체를 실행

29/17

연습문제

1. 300을 입력 받기 젂까지의 입력으로 binary tree를 구성하고, 300을 입력 받은 이후에는 입력한 숫자가binary tree안에 존재하는지 확인하는 프로그램을 작성하여라. 입력 값은 integer이다.

2. 17개의 bucket을 가지는 hash를 이용하여 입력한 단어의 출현 횟수를 세는 프로그램을 작성하여라. 입력값은 string이다.

Conflict는 linear insertion을 이용하여라.

Bucket이 모두 찼을 경우 hash table의 내용을 출력하고 종료하여라.

strlen(), strdup(), strcmp()