12
조 자료구조 B2 보고서 상호참조 생성기 [Project #4 : ] 조장 고충욱 : 조원 강승우 : 허규준 최완철 최수영

자료구조04

Embed Size (px)

DESCRIPTION

트리를 이용한 상호참조생성기

Citation preview

Page 1: 자료구조04

조 자료구조B2

보고서

상호참조 생성기[Project #4 : ]

조장 고충욱:

조원 강승우:

허규준

최완철

최수영

Page 2: 자료구조04

과제수행일지소속 조원

B2 조장 고충욱: 자료조사 최완철 최수영: , 프로그래밍 강승우 최규준: ,

과제수행기간 일4

계획의 작성I.

연구제목 TREE

연구배경 트리에 대해 이해하고 트리를 이용하여 상호참조 생성기를 만들 수 있다, .

참고자료

참고 서적 로 배우는 쉬운 자료구조 이지영 출판사 한빛미디어C

참고 URL

http://blog.naver.com/ctpoyou?Redirect=Log&logNo=10493277

8 트리의 정의와 트리의 종류-

http://internet512.chonbuk.ac.kr/datastructure/tree/tree8.ht

m 트리의 순회방법-

계획의 실행II.

첫째 날 년 월 일 목요일2012 5 3

오늘의 작업 조원의 업무 분담과 학습할 내용 및 과제에 대한 이해와 숙지

토의 내용

조장 고충욱:

자료조사 강승우 최완철 최수영: , ,

프로그래밍 허규준:

위와 같이 조원의 업무 분담을 하였으며 과제를 위한 자료조사와 프로그래밍에 대한 내

용을 인식하고 개별적으로 분담을 해서 조사를 하고 이해를 해 온 다음 그것을 조원들

에게 설명해주는 것으로 방향을 잡았다.

과제준비에서

느낀 점

이번과제의 내용을 보니 자료조사가 많이 필요할 것 같아서 자료조사를 중점으로 해야

겠다는 생각을 가지게 되었다.

Page 3: 자료구조04

둘째 날 년 월 일 목요일2012 5 8

오늘의 작업 학습할 내용에 대한 설명 및 이해

토의 내용

나무구조 의 정의Tree( )

개 이상의 유한한 개수의 노드의 집합1⊙

루트 노드와 개 이상의 겹치지 않는 하위 나무 구조들의 집합으로 이루어짐0⊙

path 에 의해 연결된 들의 집합: edge node

잎leaf( ) : 자식이 없는 최하위 계층node( )

forest :루트를 제외한 나머지 부분

subtree : 큰 에 속한 작은tree tree

의node degree : 하위 의 개수 어느 특정노드의 자식 수subtree ,

의node level : 부터 최하위 까지의 중첩되지 않은 의 개수root node node path node

노드들의 자식 수 중에 가장 큰 자식 수

노드1) (Node)

노드는 트리를 구성하는 기본 요소를 말한다 즉 아래의 그림에서 본다면 에서 까지. a g

의 각 요소

모두가 노드가 된다.

근2) (Root)

트리의 가장 높은 레벨에 있는 노드를 루트 노드 또는 근 노드라 한다 이 루트 노드.

는 모든 노드의

조상이 된다 아래의 그림에서 노드는 루트 노드가 된다. a .

레벨3) (level)

레벨은 각 노드가 근노드와 얼마만큼 떨어져 있는가를 알기 위해 상용한다 예를 들어.

아래의

그림에서 노드는 루트노드와 계층 떨어져 있으므로 은 이 된다e 3 level 3 .

부모 노드와 자식 노드4)

라 불린다 서로 아래 위로 붙어 있는 노드로 상위의 노드가parent node, child node .

부모 노드가 된다 하위의 노드는 자식노드가 되고 여러개의 자식노드는 하나의 부모.

노드만 가질 수 있다.

아래의 그림에서 노드와 노드는 각각부모 노드 자식이 된다e g .

형제 노드5)

라 불린다 같은 부모 노드를 갖는 자식 노드들은 형제들의 집합으로 구성sibling node .

된다.

아래의 그림에서 노드와 노드는 가 된다b c sibling nod .

이진 나무 이진 트리 의 정의Binary Tree( , )

모든 내부 들이 둘 이하의 자식 를 갖는 나무 노드가 하나도 없는 공집합 이node node , 거나

를 기준으로 왼쪽 이진나무 오른쪽 이진나무로 이루어진 집합root node ,

완전 이진나무Complete Binary tree( )⊙

가장 마지막 을 제외한 모든 들이 꽉 차있고 마지막 은 왼쪽 부터 마지level node level

까지 빈 칸이 없는node tree

Page 4: 자료구조04

포화 이진나무Full Binary Tree( )⊙

마지막 까지 완전히 꽉 차있는 이진 트리를 말함level

이진 나무 순회(Tree Traverse)

위와 같은 트리가 있다고 한다면 각각 순회방법은 다음과 같습니다.

전위 순회(preorder traverse)⊙ 뿌리 를 먼저 방문: (root)

중위 순회(inorder traverse)⊙ 왼쪽 하위 트리를 방문 후 뿌리 를 방문: (root)

후위 순회(postorder traverse)⊙ 하위 트리 모두 방문 후 뿌리 를 방문: (root)

층별 순회(level order traverse)⊙ 위 쪽 들 부터 아래방향으로 차례로 방문: node

전위 순회 : 0->1->3->7->8->4->9->10->2->5->11->6

중위 순회 : 7->3->8->1->9->4->10->0->11->5->2->6

후위 순회 : 7->8->3->9->10->4->1->11->5->6->2->0

층별 순회 : 0->1->2->3->4->5->6->7->8->9->10->11

전위 순회는 뿌리 왼쪽 자식 오른쪽 자식 순-> ->★

Page 5: 자료구조04

중위 순회는 왼쪽자식 뿌리 오른쪽 자식-> ->★

후위 순회는 왼쪽자식 오른쪽 자식 뿌리-> ->★

층별 순회는 그냥 노드의 순서대로★

과제준비에서

느낀 점

트리에 대한 개념은 어느 정도 이해 할 수 있었으나 이것을 사용하고 구현하기 위해서

는 아직 많은 것이 부족한 것 같다 더 많은 공부가 필요한 것 같다. .

셋째 날 년 월 일 목요일2012 5 10

오늘의 작업 자료조사 내용

토의 내용

트리의 순회

이진 트리의 순회는 일정한 순서로 트리의 모든 노드들을 오직 한번씩만 방문하는 것이

다 트리의 순회는 트리 구조로 된 정보의 검색이나 수식 처리등에 유용하게 사용된다. .

특정 노드에서 자신의 왼쪽 서브 트리를 모두 방문하고 자기 노드를,

방문한 후에 오른쪽 서브 트리를 방문한다 이 원리를 모든 노드에 재.

귀적으로 적용하면 모든 노드들을 한번씩 방문할 수 있다.

특정 노드에서 먼저 자기 노드를 방문하고 왼쪽 서브 트리를 모두,

Page 6: 자료구조04

방문하고 마지막으로 오른쪽 서브 트리를 모두 방문한다 이 원리를, .

모든 노드에 재귀적으로 적용하면 모든 노드를 한번씩 방문할 수 있

다.

특정 노드에서 자신의 왼쪽 서브 트리와 오른쪽 서브 트리를 차례로

방문한 후 마지막으로 자신의 노드를 방문한다 이 원리를 모든 노드, .

에 재귀적으로 적용하면 각 노드를 한번씩 방문할 수 있다.

과제준비에서

느낀 점

순회에 대해 공부하면서 어떤걸 써야지 효과적일지에 대해 생각을 많이 하게 되었다.

그리고 순회를 구현하기 위해서 어떻게 할지 더 많은 회의가 필요할 것 같다.

Page 7: 자료구조04

넷째 날 년 월 일 목요일2012 5 17

오늘의 작업 소스파악

초안

/************************************************************************

* cross_reference_generator.c

단어의 빈도수 및 단어가 위치한 줄번호를 출력하는 프로그램*

************************************************************************/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <assert.h>

typedef short bool;

#define FALSE 0

#define TRUE 1

typedef struct _WORDNODE *PWORDNODE;

typedef struct _LINENODE *PLINENODE;

typedef struct _LINENODE 단어가 출현시 그 라인번호에 대한 구조체// .

{

int line_number; 라인번호// .

PLINENODE next_node; 다음 노드//

} LINENODE;

typedef struct _WORDNODE // 의 노드 구조체Binary Search Tree .

{

char word[32]; 단어// .

int frequency; 빈도수//

PLINENODE pLine_node; 단어가 나오는 라인번호// (Linked

로 구현List )

PWORDNODE left_child; 왼쪽자식노드//

PWORDNODE right_child; 오른쪽자식노드//

} WORDNODE;

/************************************************************************

* Function Prototype Declare

************************************************************************/

노드를 삽입//

void InsertNode( PWORDNODE* pRoot, char* aKey, int aLineNumber );

/* 같은 단어가 존재시에는 해당 노드 반환 혹은

* 존재 하지 않을 시 삽입 할 위치의 의 포인터 반환parent node */

PWORDNODE Search( PWORDNODE pRoot , char* key ,bool* exist_same);

Page 8: 자료구조04

/* 사전 순서대로 단어 빈도수 그리고 총 단어수 출력, ,

* (inorder-traversal) */

void PrintTree( PWORDNODE pRoot );

int main( int argc , char* argv[] )

{

PWORDNODE pRoot = NULL ; 트리의 루트//

char string[256] = {0}; 텍스트파일 한 라인의 버퍼//

char* ptr_key; 토큰된 단어에 대한 포인터//

char* ptr_lwr_key; 소문자로 변환된 단어// lower key ,

의 포인터

int line_number = 0 ; 해당 라인 번호//

FILE* in_file; 읽어들일 파일 구조체// .

if ( argc != 2 || strlen(argv[1]) == 0) {

printf("Usage : %s filename\n" , argv[0]);

return 0;

}

in_file = fopen(argv[1],"r"); 파일을 읽기전용 모드로 연다// .

if (!in_file) {

fprintf(stderr,"Can not open a file. : %s \n",argv[1]);

exit(1);

}

이 끝에 도달 할 때까지 아래 내용을 실행while ( !feof(in_file) ) // in_file .

{

memset(string,0,sizeof(string)); 한 라인에 대한//

버퍼를 초기화.

fgets( string , sizeof(string),in_file); 파일로 부터 라인을 읽어옴//

++line_number; //

라인번호 증가.

/*************************************************************************

사용법은 참조 바람strtok , strlwr C reference manual .

************************************************************************/

문자열에서 로 단어들을 추출// separator

ptr_key = strtok( string, "

`~!@#$%^&*()_-=+[]{};:\'\"|\\/?,.<>\t\n" );

while( ptr_key != NULL )

{

ptr_lwr_key = strlwr(ptr_key);

해당 단어를 소문자로 변환//

해당단어와 라인번호를 트리에 삽입// binary search

Page 9: 자료구조04

InsertNode( &pRoot , ptr_lwr_key , line_number );

다음 단어 추출// .

ptr_key = strtok( NULL, "

`~!@#$%^&*()_-=+[]{};:\'\"|\\/?,.<>\t\n" );

}

}

if ( pRoot ) 트리에 노드가 존재 한다면// .

{

printf("-------------------------------------------------

-------------------\n");

단어 빈도수 라인printf("%-19s|%-11s|%-19s\n", " " , " "," ");

printf("-------------------------------------------------

-------------------\n");

PrintTree( pRoot ); 트리 내용 출력// .

printf("-------------------------------------------------

-------------------\n");

}

fclose(in_file); 파일을 닫음// .

return 0;

}

/************************************************************************

사전 순서대로 단어 빈도수 그리고 총 단어수 출력* , , (inorder-traversal)

************************************************************************/

void PrintTree( PWORDNODE pRoot )

{

PLINENODE tmpLineNode; 해당 단어의 라인번호를 출력하기 위//

한 임시 포인터

if ( pRoot ) 루트가 널이 아니라면//

{

tmpLineNode = pRoot->pLine_node ; 는 라인노드// tmpLineNode

를 가르킴

PrintTree( pRoot->left_child ); 왼쪽 자식노드 출//

력.

중간 즉 루트 노드 출력// , .

해당 노드의 단어와 빈도수 출력//

printf(" %-18s|%9d |", pRoot->word , pRoot->frequency );

while ( tmpLineNode ) { 가 널일때 까지// tmpLineNode .

라인번호 출력//

printf("%4d",tmpLineNode->line_number);

임시포인터는 링키드리스트의 다음 노드를 가리키게 함//

tmpLineNode = tmpLineNode->next_node;

}

printf("\n");

Page 10: 자료구조04

PrintTree( pRoot->right_child ); 오른쪽 자식노드 출력//

}

}

/************************************************************************

* 같은 단어가 존재시에는 해당 노드 반환 혹은

* 존재 하지 않을 시삽입 할 위치의 의 포인터 반환parent node

************************************************************************/

PWORDNODE Search( PWORDNODE pRoot , char* key ,bool* exist_same)

{

PWORDNODE preNode = pRoot; 노드를 기억 할 임시 변수// parent

while ( pRoot ) 해당노드가 널일때 까지// .

{

preNode = pRoot; //

해당노드를 기억.

if ( strcmp( key, pRoot->word ) == 0 ) 해당노드가 같은 단어의 노//

드일경우

{

*exist_same = TRUE; 같은것//

이 있다는것을 로 표시true

return pRoot; 그 노드//

를 반환.

}

if ( strcmp( key, pRoot->word ) < 0) 키가 해당노드의 단어보다//

앞쪽이라면

pRoot = pRoot->left_child; 왼쪽 자//

식노드로 이동.

else

pRoot = pRoot->right_child; 뒤쪽의 단어라면//

오른쪽 자식노드로 이동

}

널이라면 그 전 노드 노드 를 반환// (parent )

return preNode;

}

/************************************************************************

* 에 노드를 삽입 로 구성Tree . Binary Search Tree .

************************************************************************/

void InsertNode( PWORDNODE* pRoot, char* aKey, int aLineNumber )

{

bool exist_same_word = FALSE; 같은 단어가 트리내에 존재할시//

true

같은 단어가 트리 내에 존재 하면 그 단어에 대한 노드// ,

없을 시에 새로 삽입될 위치의 노드// parent

PWORDNODE tmpWordNode = Search( *pRoot , aKey

,&exist_same_word);

PWORDNODE insertWordNode = NULL; 트리에 삽입 될 노드//

줄번호를 저장 할 노드PLINENODE ptrLineNode = NULL; // .

Page 11: 자료구조04

/************************************************************

* 가 내에 존재할시key tree .

************************************************************/

if ( exist_same_word )

{

반환된 노드 즉 는 에 대한 노드// , tmpWordNode Key

노드 내의 빈도수 증가//

++(tmpWordNode->frequency);

라인번호에 대한 링키드 리스트의 끝 부분으로 이동// .

ptrLineNode = tmpWordNode->pLine_node;

while( ptrLineNode->next_node )

ptrLineNode = ptrLineNode->next_node;

새로운 라인노드를 붙여준다// .

ptrLineNode->next_node =

(PLINENODE)malloc(sizeof(LINENODE));

라인번ptrLineNode->next_node->line_number = aLineNumber ; //

호 저장

ptrLineNode->next_node->next_node = NULL; //

다음노드는 로 처리NULL .

}

else if ( tmpWordNode || !(*pRoot) )

{

/************************************************************

* 가 트리내에 없음key .

************************************************************/

//////////////////////////////////////////////////////////////////////////

새로운 노드 생성 라인번호와 단어를 저장// , .

insertWordNode = (PWORDNODE)malloc(sizeof(WORDNODE));

if (!insertWordNode) {

fprintf(stderr,"The Memory is full\n");

exit(1);

}

memset( insertWordNode , 0 , sizeof(WORDNODE)); //

초기화

strcpy( insertWordNode->word , aKey );

삽입될 노드에 키 복사//

++(insertWordNode->frequency);

빈도수 증가// .

새로운 라인노드를 붙여준다// .

insertWordNode->pLine_node =

(PLINENODE)malloc(sizeof(LINENODE));

해당단어가 출현한 라인번호 저장// .

insertWordNode->pLine_node->line_number = aLineNumber ;

다음노드는 로 처리// NULL .

insertWordNode->pLine_node->next_node = NULL;

Page 12: 자료구조04

//////////////////////////////////////////////////////////////////////////

그 노드를 적절한 위치에 삽입//

루트가 널이 아니라면if (*pRoot) //

키가 해당노드의 단어보다 앞쪽이라면{ //

if ( strcmp( aKey, tmpWordNode->word ) < 0)

tmpWordNode->left_child = insertWordNode; //

왼쪽 자식노드에 삽입.

else

tmpWordNode->right_child = insertWordNode;

아니라면 오른쪽 노드에 삽입// .

}

else 루트가 널이라면 루트에 해당 노드를 저장// .

*pRoot = insertWordNode;

}

}

// cross_reference_generator.c END

알고리즘 해석

단어 빈도수를 찾는 프로그램의 알고리즘은 먼저 단어를 저장할 문자열배열 빈(data),

도수를 나타내는 단어가 등장한 라인을 나타내는 다음 노드 구조체 를(data), (data), ( )

가르키는 두 개의 포인터 왼쪽 오른쪽 자식 으로 구성되있는 구조체를 사용 하여 이진트( , )

리를 구성하며 프로그램이 진행된다.

먼저 파일의 한 라인을 읽어와서 앞“`~!@#$%^&*()_-=+[]{};:\'\"|\\/?,.<>\t\n”

의 문자로 끊어 한 단어로 인식 하고 라인 별로 읽기 때문에 다음 라인으로 갈 때 마다

라인넘버를 씩 증가 시켜 로 사용 하게 된다1 data .

한 단어가 트리에 이미 저장되어 있는지 중복 검사 후 중복 되는 단어가 있다면 해당

단어가 저장 되있는 구조체에서 빈도수만 증가 시키고 중복되지 않는다면 처음 등장하, (

는 단어 새로운 구조체를 만들어 저장 하고 빈도수 등장하는 라인도 추가 시킨다) , .

단어를 추가시키는 방법은 접근한 구조체의 단어보다 앞의 단어이면 왼쪽 뒤의 단어이,

면 오른쪽으로 저장한다.

파일의 모든 문자들을 읽은 후 트리의 저장이 완료 되면 중위 순회 방법으로 트리의,

단어 빈도수 라인넘버를 출력 한다 중위 순회는 출력의 우선순위가 왼쪽 노드의 값 현, , >

재 노드의 값 오른쪽 노드의 값 으로 정해져 있고 이 순서대로 단어를 출력 하면 해당>

노드보다 앞의 단어는 왼쪽으로 게속 저장했으므로 이 방법을 사용 하여 사전식순으로

단어를 출력 한다.

출력은 다음 노드의 값이 없을때 까지 반복 하고 프로그램을 종료합니다.

반성.Ⅳ

과제를 마치면서

느낀 점

과제를 마무리하지 못해 알고리즘을 해석하면서 과제를 마무리하였다.

많은 아쉬움을 가진 프로젝트가 되었다.