30
project #4 상호참조 생성기 자료구조 01 조 : C3 조장 김창헌 : 조원 이상현 : 김시백 박가혜 김정

Project#4상호참조 생성기 Hwp

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Project#4상호참조 생성기 Hwp

project #4상호참조 생성기

자료구조 01조 : C3

조장 김창헌:조원 이상현:

김시백박가혜김정무

Page 2: Project#4상호참조 생성기 Hwp

순 서순 서순 서순 서

프로젝트 설명프로젝트 설명프로젝트 설명프로젝트 설명1.1.1.1.트리1) (trees)프로젝트 전체일정프로젝트 전체일정프로젝트 전체일정프로젝트 전체일정2.2.2.2.업무분담업무분담업무분담업무분담3.3.3.3.초안초안초안초안4.4.4.4.문제점문제점문제점문제점5.5.5.5.최종안최종안최종안최종안6.6.6.6.느낀점느낀점느낀점느낀점7.7.7.7.

Page 3: Project#4상호참조 생성기 Hwp

프로젝트 설명프로젝트 설명프로젝트 설명프로젝트 설명1.1.1.1.1) 트리 란( Tree ) ?

트리는 비선형 자료구조 배열이나 리스트는 선형 구조이다 기차 처럼 내 다음에 누가 있고 내 다음에( .

누가 있는.. )

와 로 구성됨 를 라고도 하고 를 라고도 표현한다Node( vertex ) Link( edge ) ( Node vertex Link edge . )

는 정보 를 포함하고 있음. Node ( data )

는 두 간의 연결 관계를 나타냄. Link Node

다음의 특징을 만족해야 함

. Root가 하나 존재 : 는 최상위Root Node

를 제외한 모든 는 하나의 부모를 가져야 함. Root Node

는 여러개의 자식을 가질 수 있음. Node

한 로 부터 다른 로 가는 경로는 유일해야 함. Node Node

• 전형적인 예 의 디렉토리 구조 이걸 볼때마다 이건 트리구조다 하고 생각하자) Windows ( . . )

트리의 예

는 가 아니다 그림이 잘못되었답니다I Leaf Node . .

Page 4: Project#4상호참조 생성기 Hwp

트리의 용어들

용 어 내 용 설명

Node vertex 정보를 나타냄 그림에서 와 같은 객체를 노A, B, C, D, ...드라고 한다.

Link edge 의 연결관계를 나타Node냄 그림에서 선으로 나타낸것을 링크라고 한다.

Root Node   부모가 없는 최상위 노드 하나만 존재해야 한다.

Leaf Node

Termina lNodeE x t e r n a lNode

자식이 없는 최하위 노드 그림에서 하늘색으로 색칠된 노드들이 Leaf(잎 이다) Node .

Internal Node Non-Terminal Node 가 아닌 노드Leaf Node 자식이 하나라도 있는 노드 그림에서 A, B,

가 인터널 노드가 된다C, I .

Sub tree   트리의 부분집합 를 시작으로 트리를 떼어내면 가B Sub tree된다.

Path  한 로 부터 다른Node

로 가는 경로Node

그림에서 에서 로 가는 경로는E C이다 이 경로는 유일해야 한다E->B->A->C . .

다른 경로는 없다 중복이 없어야 한다( . ) .만약 가 연결되어 있다면 이것은 트리라, G-C고 할 수 없다 이런 자료구조는 그래프라. (고 부른다. )

최소 공통 선조

L e a s tCommonAncestors

두 노드의 공통적인 선조중 가장 레벨이 높은 선조 노드

그림에서 와 를 보면 두 노드의 공통 선H J조는 가 있는데 그중 는 이 이A, C C Level 2므로 가 의 최소 공통 선조가 된다C H, J .

자식 Children 자신의 아래로 연결된 노드 의 자식 노드는 와 가 있다C H I .

부모 Parent 자신의 위로 연결된 노드 의 부모는 이고 의 노드는 이다I C C A .

조부모 G r a n dParent 자신의 부모의 부모노드 조부모란 할아버지급 노드를 말한다 즉 의. I

조부모는 이고 의 조부모는 이다A J C .

레벨 Level 에서 특정 노드로Root가는 경로의 노드 수

그림에서 를 보면 경로에 개의 노I A, C, I 3드를 갖는다 그래서 은 이다. Level 3 .

높이 Height 가장 높은 레벨 가 로써 제일 높은 레벨이 된다J 4 .

이진 트리7.2 ( Binary Tree )• 이진 트리의 정의

• Full Binary Tree

이진 트리 의 정의( Binary Tree )

이진 트리의 정의

모든 가Internal Node 두개 이하의 자식을 갖는 트리

와 두개의 자식을 가질 수 있음Left Child Right Child

가장 쓰임새가 많은 트리

이진 트리의 용도

수식 계산에 사용Parse Tree :

정렬 에 사용Heap : ( Sorting )

검색에 사용Binary Search Tree :

Full Binary Tree

Page 5: Project#4상호참조 생성기 Hwp

Full Binary Tree

마지막 레벨을 제외한 모든 레벨에 노드가 꽉차있음

Complete Binary Tree

모든 레벨에 노드가 꽉 차있음 

와<full binary tree complete binary tree>

왼쪽의 그림을 보자 자식이 많아 봐야 개이다 이런 트리를 이진트리라고 하는 것이다 그런데 이진. 2 . .

트리 중에서도 와 가 있는데 왼쪽은 마지막 레벨 즉 레벨Full binary tree Complete binary tree , , H, I, J 4

에서는 노드가 꽉 차있지 않지만 마지막 레벨을 제외한 모든 레벨에 노드가 꽉 차 있으므로 Full binary

라고 하고 오른쪽 그림 처럼 모든 레벨에 노드가 꽉 차있으면 완벽한 라고tree , Complete( ) binary tree

부른다.

의 성질Full Binary Tree

레벨과 노드의 수 관계

레벨이 d일때, 트리의 노드수 N은 다음을 만족

2d-1 N 2≤ ≤ d - 1

개의 노드를 가진 이진 트리의 레벨 는 다음과 같다N d .

d = [ log2 는 소수점 이하는 버림한다N ] + 1 ( [ ] . )

숫자놀이를 해보자. ( Level = d, Node count = N )

2d-1 N 2≤ ≤ d 노드의 갯수는 이 범위안에 속한다- 1 ( . )

일때d = 2 , 22-1 노드의 갯수 2≤ ≤ 2 - 1

2 N 3≤ ≤ 이 된다.

일때d = 3 , 23-1 노드의 갯수 2≤ ≤ 3 - 1

이 된다4 N 7 .≤ ≤

일때d = 4 8 N 15≤ ≤

그림을 보고 이해해 보도록 하자.

최소 개 최대 이렇게 개가 된다 아마 최대갯수가 홀 수 인것은( A, B, C, D 4 , A, B, C, D, E, F, G 7 .

노드가 홀 수 이기 때문인거 같다Root . 2n으로 표현되는 것은 자식의 노드가 2n만큼 늘어나기 때문인

것 같은데 최소 노드의 갯수가, 2n-1인 것은 예를들어 이 이면 인 노드를 기준으로, Level 4 Level 1 Root 2

개씩 번 나누어졌기 때문에 개가 되고 최대 노드의 갯수가3 , 8 2n 인 것은 번씩 나뉜 만큼의 수에- 1 2

서 노드를 뺀 갯수가 되는 것이다Root . )

Page 6: Project#4상호참조 생성기 Hwp

를 구하는 이 증명은 자료구조 시험문제에 가끔 나오니 알아두도록 하자Level d .

2d-1 N 2≤ ≤ d - 1

부등식에 log2를 취하면,

d - 1 log≤ 2N log≤ 2( 2d - 1 )

log2( 2d 는- 1 ) log22

d - log2 즉1 , log2와 가 소거되어 가 되고2 d - log2 은 이 된다1 - 0 . ( 2n 일때= 1

은n 0 )

결국 수식을 정리해 보면

d - 1 log≤ 2N <d 이렇게 되는데 부등식에 을 더하면, 1

d log≤ 2 여기에서N + 1 <d + 1 log2 의 소수점 이하 부분을 잘라낸 것과 같다는 의미가 된다N + 1 . (

log2 = 0.3010 )

그래서 d = [ log2N ] + 1 이다.

이진 트리의 구현7.3 ( Project : Tree )• 이진 트리 구현 방법

• 이진 트리 모델링

• Skeleton

이진 트리의 구현 방법

배열로 구현하는 방법

인 경우에만 사용가능. Full Binary Tree

이진 트리의 특징을 이용한 인덱스 조작.

에서 자세히 살펴볼 것임. Heap Sort

연결 리스트로 구현하는 방법

클래스가 하나의 노드를 나타냄. Node

이 노드는 와 로 두 자식을 가리킴. pLeft pRight

모든 자료구조의 기본이 되는 배열과 연결 리스트가 또 나왔다.

이진트리를 이중 연결리스트 로 구현하는 법에 대해서 알아보자( Doubly Linked List ) .

이진 트리 모델링

시작 과 끝 을 나타내는 가짜 노드 사용Head( ) Tail( )

. m_pNodeHead / m_pNodeTail

. Root Node == m_pNodeHead->pLeft

모든 의 와. Leaf Node pLeft pRight == m_pNodeTail

Page 7: Project#4상호참조 생성기 Hwp

와 를 보면 이 객체가 무엇을 의미하는지는 변수명을 보자 은 클래스의m_pNodeHead m_pNodeTail .. ( . m

멤버 변수라는 뜻이고 의 와 의 이라는 뜻이다, Node Head Node Tail . )

일단 비어있는 한 트리로 시작하게 되는데 헤드 노드의 와 는 꼬리 노드의 시작주( Empty ) pLeft pRight

소를 가리키고 있고 꼬리 노드의 와 는 자기 자신의 시작주소를 가리키고 있다, pLeft pRight .

여기서 클래스와 객체의 구분은 는 멤버 변수와 함수들을 정의 해 놓은 것이고 객체는 그 클래스( class

를 이용해 만들어 낸 것을 말한다.

이게 클래스이고class People { m_pName, m_pAge, void SetName() }; ,

김철수 여기서 이 객체가 되는것이다People p1( " ", 26 ); p1 . )

오른쪽 그림을 보면 로 나타낸 개념적 트리가 있는데 이것을 물리적 트리로 오른쪽 그림과A, B, C, D

같이 표현할 수 있다.

가짜 노드 는 리스트의 시작을 의미하고 에 노드 를 링크하게 된다m_pNodeHead( ) pLeft Root A . pRight

에는 가짜 노드 를 가리키게 된다 의 는 잘 사용하지 않을 것이다m_pNodeTail( ) . m_pNodeHead pRight .

이제 노드 를 보자 노드의 에는 노드가 에는 노드가 있고 다시 노드의 에Root A . A pLeft B pRight C B pLeft

는 노드가 있으며 가 없는 노드들은 모두 끝 을 가리키고 있다D pRight m_pNodeTail( ) .

Binary Tree Skeleton

구성

• 노드를 나타내는 struct Node

• 시작과 끝을 나타내는 m_pNodeHead, m_pNodeTail

• Ctors / Dtors

• 제거를 위한 RemoveAll

도 어떤 객체들의 컨테이너 역할을 하는 것이기 때문에 를 사용 하였다고 한다Binary Tree template .

클래스의 뼈대를 간단히 살펴보면 위의 구성 내용과 같다Binary Tree .

template<class TYPE >

class BinaryTree

{

Page 8: Project#4상호참조 생성기 Hwp

public:

    BinaryTree();

    ~BinaryTree();

    void RemoveAll();

protected:

    struct Node

    {

        TYPE data;

        Node* pLeft;

        Node* pRight;

    };

    Node* m_pNodeHead;

    Node* m_pNodeTail;

    void RemoveSubtree( Node* pNode );

};

일단 가 있고struct Node{ TYPE data, Node* pLeft, Node* pRight }; ,

이를 로 표현 하려면 이 필요하다 구class BinaryTree [Head] - [Node1] - [Node2] - [ ... ] - [Tail] . Node

조체를 안에 포함 시키고 시작 주소를 나타내는 와 을class Node* m_pNodeHead Node* m_pNodeTail

추가시켜 주자.

그리고 클래스의 기능에 필요한 멤버 함수들을 추가시켜 주자 여기에서는 모든 노드를 소거BinaryTree .

시키는 기능과 를 소거 시키는 기능이 추가되어 있다SubTree .

기능과 기능이 없는 이유는 에는 다양한 가 있는데 이는 나중에 이 기본 클래Insert() Remove() Tree Tree

스에서 계승 받아 구현하려고 하기 때문이다 일단 그렇게 알아두자 이라는 전체적으. . void RemoveAll()

로 필요한 기능만 추가되어 있는 것이다.

생성자와 제거자의 약자Ctors / Dtors ( )

Constructor

시작과 끝을 나타내는 가짜노드 두개를 만듦

Desturctor

을 호출한 뒤 가짜 노드를 지움RemoveAll ,

의 모든 를 지우기 위해서 모든 노드를 방문하는 방법이 필요함Tree Node

생성자에서는 그러니까 나중에 함수에서 이 클래스를 사용해 객체를 만들때.. void Main() , BinaryTree

객체 이 생성될때 어떠한 구조로 생성이 되는가b1(); b1 ?

인 은 메모리상에 가짜노드와 가짜노드가 만들어 지고 그 와 의BinaryTree b1 Head Tail Head Tail pLeft,

는 저 기 위쪽 그림과 같이 연결되어 있다pRight ~ .

그럼 이 의 객체에 홍길동 하게 되면 그 노드가 삽입되어 연결되는 것이다b1 b1.Insert( " " ); .

생성자에서 어떤 구조를 형성하는지 잘 생각해보고 넘어가자.

Page 9: Project#4상호참조 생성기 Hwp

template<class TYPE >

BinaryTree< TYPE >::BinaryTree()

{

    m_pNodeHead =new Node;

    m_pNodeTail =new Node;

    m_pNodeHead->pLeft = m_pNodeTail;

    m_pNodeHead->pRight = m_pNodeTail;

    m_pNodeTail->pLeft = m_pNodeTail;

    m_pNodeTail->pRight = m_pNodeTail;

}

제거자에서는 이 객체가 사라질때 객체에서 사용한 모든 메모리를 해제시켜주는 역할을BinaryTree b1 b1

하게 된다.

이렇게 형성된 메모리를 전부 날려버리는 것이다[Head] - [Node1] - [Node2] - [ ... ] - [Tail] .

template<class TYPE >

BinaryTree< TYPE >::~BinaryTree()

{

    RemoveAll();     중간 노드들 제거//

    if( m_pNodeHead )delete m_pNodeHead;     가짜 노드 와// Head

    if( m_pNodeTail )delete m_pNodeTail;     제거// Tail

}

트리 순회7.4 Tree Traversal ( )• Pre-order Traversal

• In-order Traversal

• Post-order Traversal

• Level-order Traversal

이 필요한 이유Tree Traversal ?

• 비선형 구조여서 전체 노드를 방문하는 방법이 필요함.

여러가지 방법이 존재함 선형구조라면 으로 간다던가 으로 간다던가 하는데( -> <- .. )

기반 이런 방법들이 있다. Stack     : Pre-order, Post-order, In-order ( . )

기반. Queue     : Level-order

전산학 학부생 같은경우 이 내용이 시험에 자주 나올 만큼 중요한 부분이다 정보처리 기사 시험에서도.

자주 나오는 내용이다.

Pre-Order Traversal

• 알고리즘

1. Root를 방문한다

1. 왼쪽 Subtree를 방문한다.

1. 오른쪽 Subtree를 방문한다.

Page 10: Project#4상호참조 생성기 Hwp

을 방문하고 를 방문하고 을 방문한다 안에서 또 가 있다면 왼쪽부터 방문하게 된다1 2 3 . ( 2 subTree . ==

재귀호출의 맛보기.. )

void BinaryTree::PreOrderTraverse( Node* pNode )     부터 시작해서 방문// pNode

{

    if( pNode != m_pNodeTail )     재귀 호출 함수는 종료 조건이 꼭 필요하다// .

    {

        Visit( pNode );    // Do Something

        PreOrderTraverse( pNode->pLeft );         방문했으면 에 결린다 그리고 가// Do Something . pNode

이 아니면 또 왼쪽으로 링크된 노드에 방문하게 되어있다Tail .

        PreOrderTraverse( pNode->pRight );     위 함수가 종료되면 여기부터 시작//

    }

}

이런식으로 방문하게 되는 가 앞 순서 방문 이 된다Tree Pre-order Traversal( ) .

를 방문하는 타이밍에 대해 자세히 보자Root .

In-Order Traversal

• 알고리즘

1. 왼쪽 를 방문한다Subtree .

1. 를 방문한다Root .

1. 오른쪽 를 방문한다Subtree .

Page 11: Project#4상호참조 생성기 Hwp

을 방문하고 를 방문하고 을 방문한다1 2.Root 3 .

void BinaryTree::InOrderTraverse( Node* pNode )

{

    if( pNode != m_pNodeTail )

    {

        InOrderTraverse( pNode->pLeft );

        Visit( pNode );    // Do Something

        InOrderTraverse( pNode->pRight );

    }

}

InOrderTraverse( pNode->pLeft );를 계속 만나게 되므로일단 까지 내려 간다 그다음 에 다다랐을G . Tail

때 함수가 종료되고 다음 라인 함수를 만나게 되어 방문하게 된다Visit( pNode ); . Do Something(

라던가 를 하고 나서 함수가 발동되는데 노드에는 도printf .. ) pRight G pRight Tail if( pNode !=

m_pNodeTail ) 이니까 재귀호출 함수를 빠져나가게 된다 그럼 노드의 함수부터 시작. D Visit( pNode );

하게 되고 노드의 를 방문하게 된다, D pRight .

Post-Order Traversal

• 알고리즘

1. 왼쪽 를 방문한다Subtree .

1. 오른쪽 를 방문한다Subtree .

1. 를 방문한다Root .

Page 12: Project#4상호참조 생성기 Hwp

void BinaryTree::InOrderTraverse( Node* pNode )

{

    if( pNode != m_pNodeTail )

    {

        InOrderTraverse( pNode->pLeft );

        InOrderTraverse( pNode->pRight );

        Visit( pNode );

    }

}

를 호출하였다면InOrderTraverse( A );

InOrderTraverse( A->pLeft );         가 링크되어 있다 재귀호출 함수에 의해// B .

InOrderTraverse( B->pLeft );

InOrderTraverse( D->pLeft );

InOrderTraverse( G->pLeft );         모두 하여 를 출력// pLeft, pRight Tail.. Visit G

InOrderTraverse( D->pRight );

InOrderTraverse( H->pLeft );     모두 하여 를 출력// pLeft, pRight Tail.. Visit H

의 를 방문함수 재귀호출 를 이행하였으므로 그 다음라인D pLeft, pRight ( ) Visit( D );     를 출력// D

InOrderTraverse( B->pRight );

// ...

그림을 놓고 이해를 하는게 빠르다.

Page 13: Project#4상호참조 생성기 Hwp

버전Pre-Order Traversal : Stack

재귀 호출은

일반적으로 을 사용하여 방식으로 바꿀 수 있다stack non-recursive .

는 다소 복잡하다Post-Order, In-Order .

재귀호출을 사용하면 코드가 깔끔하지만 성능이 않좋아서 옛날에 사용..

이 함수는 재귀호출이 아니다.

void BinaryTree::PreOrderTraverse_Stack( Node* pNode )

{

    ListStack< Node*> stack;

    stack.Push( pNode );

    while(!stack.IsEmpty())

    {

        pNode = stack.Pop();

        if( pNode != m_pNodeTail )

        {

            Visit( pNode );

            stack.Push( pNode->pRight );

            stack.Push( pNode->pLeft );

        }

    }

}

여기서 Node* 를 사용하여 노드포인터 를 가져오는 것은 만약 가져오는 객체의 크기가( pNode )

라면 가져오기 난감할 것이다 포인터로 주소를 가져오게 되면 그 객체에 접근할 수가 있다 함100byte . .

수 구현 첫번째 라인을 보면 Node* 포인터를 스택에 담는것을 알 수 있다 큰 객체를 다 담아버리게 되.

면 말도 안되는 메모리를 사용하게 되므로 그 객체를 포인팅 하고 있는 포인터를 담아두면 언제든지 그

객체에 접근할 수 있기 때문이다 에 넣는다는것은 프링글즈를 생각하면 되는데 소스 코드를 보면. stack ..

일단 함수 호출을 통해 가지고 온 노드를 에 한번 하고 다시 빼내어 방문하게 되는것을 볼 수stack Push

있다.

를 먼저 하는 이유는 이기 때문이다 먼저 하면 바닥쪽에 깔리고 나중에 하면pRight Push stack . Push Push

윗쪽으로 올라가기 때문에 할때는 부터 나오기 때문이다Pop pLeft .

재귀호출 방식을 이용하는게 좋으나 알고리즘 구현 방식에도 다양한 방법이 있다는 것을 상기하자, .

Level-Order Traversal

가장 직관적인 Traversal

위에서 아래로 좌에서 우로 진행, ( A ~ I )

Page 14: Project#4상호참조 생성기 Hwp

로 진행을 하는데 앞 소스와 거의 똑같은데 과 의 차이점에 의해 방문순서가 이렇게Queue , Stack Queue

된다.

void BinaryTree::LevelOrderTraverse( Node* pNode )

{

    ListQueue< Node*> queue;

    queue.Put( pNode );

    while(!queue.IsEmpty())

    {

        pNode = queue.Get();

        if( pNode != m_pNodeTail )

        {

            Visit( pNode );

            queue.Put( pNode->pLeft );

            queue.Put( pNode->pRight );

        }

    }

}

노드를 가져오고 에 하고 다시 꺼내어 그 노드를 방문하고 를 에 하고A queue Put pLeft queue Put pRight

를 하고 꺼내어 하게 된다 는 은행 번호표를 생각하면 되는데 에 된 순서로 빠Put Visit . Queue queue Put

져나오기 때문에 의 순서가 나오게 된다A~I .

수식 트리7.5 ( Parse Tree )• 수식 트리 개념

• 수식 트리 구축법

수식트리의 개념

정의

수식을 연산순서에 따라 트리로 구성.

. 에 에 를 배치Root Oeprator, Child Operand

Page 15: Project#4상호참조 생성기 Hwp

모든 는 는. Operator Non-Terminal, Operand Terminal Node

( ( A + B ) * ( C - D ) ) / E + ( F * G )

를 더하고 와 를 뺼셈하고 그 값을 곱하고A B C D ...

수식 트리를

1. 하면In-Order Traverse Infix Notation

1. 하면Pre-Order Traverse Prefix Notation

1. 하면Post-Order Traverse Postfix Notation

후위 표기 에서 수식 트리 구성( Post-Order )

후위 표기는 컴퓨터가 이해하기 가장 편리하게 되어있다.

알고리즘

는 를 만들어1. Operand Node Stack에 Push

를 만나면 를 생성하여2. Operator Node

에서 한 노드를 오른쪽 자식으로 하고1. Stack Pop

에서 또 한 노드를 왼쪽 자식으로 하고2. Stack Pop

와 링크된 두 자식 노드 자체를 에3. Operator Node Stack Push

에 마지막으로 남은 노드가 이다3. Stack Root .

위에 그림과 같이 되게 된다.

수식 트리의 구현7.6• Skeleton

• BuildParseTree

ParseTree skeleton

구성

의 로 부터 계승을 받음. template instance

구성. BuildParseTree : ParseTree

. Traversal Functions

Page 16: Project#4상호참조 생성기 Hwp

상위 클래스에서 이미 구현된 부분은 구현할 필요가 없다 이게 계승의 장점이다. .

class ParseTree :public BinaryTree< String >     이진 트리// TYPE : String

{

public:

    void BuildParseTree(const String& strPostfix );

    bool IsOperator(char c )

    {

        return( c =='+'|| c =='-'|| c =='*'|| c =='/');

    }

    void PreOrderTraverse( Node* pNode =0);

    void PostOrderTraverse( Node* pNode =0);

    void InOrderTraverse( Node* pNode =0);

    void LevelOrderTraverse( Node* pNode =0);

    void Visit( Node* pNode );

};

함수에서 만드는거나 함수 안에서 만드는 거나 그게 그거// Main .. ..

void ParseTree::BuildParseTree(const String& strPostfix )

{

    Node* pNode;     의 포인터를 준비// Node

    int i =0;

    ListStack< Node*> NodeStack;     스택 리스트를 준비//

    RemoveAll();

    while( strPostfix[ i ])     을 읽자// String .

    {

        while( strPostfix[ i ]==' ')

            i++;     공백 문자는 무시//

        pNode =new Node;

        if( IsOperator( strPostfix[ i ]))     연산자이면//

        {

            pNode->data = strPostfix[ i ];

            i++;

            pNode->pRight = NodeStack.Pop();

            pNode->pLeft = NodeStack.Pop();

        }

        else     피연산자 숫자 이면// ( )

        {

            do

            {

                pNode->data += strPostfix[ i ];

                i++;

            }

Page 17: Project#4상호참조 생성기 Hwp

            while( strPostfix[ i ]!=' '&& i < strPostfix.GetLength());

            pNode->pLeft = m_pNodeTail;

            pNode->pRight = m_pNodeTail;

        }

        NodeStack.Push( pNode );

    }

    m_pNodeHead->pLeft = NodeStack.Pop();    // Root

}

결론7.트리는 노드와 링크로 구성된 비선형 자료구조

이진 트리는 두개 이하의 자식을 가지는 트리

이진 트리의 은 트리의 모든 노드를 방문하기 위한 방법이다Traversal .

가 있다InOrder, PreOrder, PostOrder, LevelOrder .

스택을 이용하여 후위 표기로 부터 수식 트리 를 만들었다( Parse Tree ) .

방법에 따라 다른 수식 표기가 나옴Traversal

출처출처출처출처[[[[ http://blog.naver.com/hkn10004?Redirect=Log&logNo=20109208779

Page 18: Project#4상호참조 생성기 Hwp

프로젝트 전체일정프로젝트 전체일정프로젝트 전체일정프로젝트 전체일정2.2.2.2.기 간 5 / 8 5 / 10

내 용- 조원별 업무 분담 및 계획 작성프로젝트 문제파악-

- 프로젝트에필요한학습내용토의프로젝트 진행방향 토의-

- 알고리즘에 대해 토의하고 이해문제점 토의-

기 간 5 / 15 5 / 17

내 용 소스 구현 및 보고서 작성-프로젝트 검토-최종보고서 작성-발표준비-

업무분담업무분담업무분담업무분담3.3.3.3.이 름이 름이 름이 름 업 무업 무업 무업 무김창헌 보고서 작성 및 회의 진행 프로젝트에 필요한 학습내용 숙지,

김시백 알고리즘 설계와 소스에 대한 문제점 검토와 보완

박가혜 소스구현 및 코딩 문제의 해결을 위한 방안 제시

김정무 알고리즘 설계 및 프로젝트 수행 시 필요한 자료 수집

이상현 알고리즘 설계 및 프로젝트 수행 시 필요한 자료 수집

Page 19: Project#4상호참조 생성기 Hwp

초안초안초안초안4.4.4.4.#include <stdio.h>#include <stdio.h>#include <stdio.h>#include <stdio.h>#include <string.h>#include <string.h>#include <string.h>#include <string.h>#include <stdlib.h>#include <stdlib.h>#include <stdlib.h>#include <stdlib.h>

#define MAX 1000#define MAX 1000#define MAX 1000#define MAX 1000

char SIGN[] = " .,!?:\"\t\r\n";char SIGN[] = " .,!?:\"\t\r\n";char SIGN[] = " .,!?:\"\t\r\n";char SIGN[] = " .,!?:\"\t\r\n";

typedef struct Listtypedef struct Listtypedef struct Listtypedef struct List{{{{

char *word;char *word;char *word;char *word;int count;int count;int count;int count;struct List *next;struct List *next;struct List *next;struct List *next;

} List;} List;} List;} List;

List head={0,};List head={0,};List head={0,};List head={0,};List* tail = &head;List* tail = &head;List* tail = &head;List* tail = &head;

int word_count = 0; // # of wordsint word_count = 0; // # of wordsint word_count = 0; // # of wordsint word_count = 0; // # of wordsList **W = 0;List **W = 0;List **W = 0;List **W = 0;

void array(List *head, List **W)void array(List *head, List **W)void array(List *head, List **W)void array(List *head, List **W){{{{

List *temp = head->next;List *temp = head->next;List *temp = head->next;List *temp = head->next;int i = 0;int i = 0;int i = 0;int i = 0;while (temp)while (temp)while (temp)while (temp){{{{

W[i++] = temp;W[i++] = temp;W[i++] = temp;W[i++] = temp;temp = temp->next;temp = temp->next;temp = temp->next;temp = temp->next;

}}}}}}}}

void printW(List **W, int n)void printW(List **W, int n)void printW(List **W, int n)void printW(List **W, int n){{{{

int i;int i;int i;int i;for(i=0; i < n; i++) {for(i=0; i < n; i++) {for(i=0; i < n; i++) {for(i=0; i < n; i++) {

printf("%20s : %d\n",W[i]->word, W[i]->count);printf("%20s : %d\n",W[i]->word, W[i]->count);printf("%20s : %d\n",W[i]->word, W[i]->count);printf("%20s : %d\n",W[i]->word, W[i]->count);}}}}

}}}}

Page 20: Project#4상호참조 생성기 Hwp

List* F_Token(const char* token)List* F_Token(const char* token)List* F_Token(const char* token)List* F_Token(const char* token){{{{

List *temp = head.next;List *temp = head.next;List *temp = head.next;List *temp = head.next;while (temp)while (temp)while (temp)while (temp){{{{

if (strcmp(temp->word,token)==0)if (strcmp(temp->word,token)==0)if (strcmp(temp->word,token)==0)if (strcmp(temp->word,token)==0)return temp;return temp;return temp;return temp;

temp = temp->next;temp = temp->next;temp = temp->next;temp = temp->next;}}}}return 0;return 0;return 0;return 0;

}}}}

void InsertList(char *token)void InsertList(char *token)void InsertList(char *token)void InsertList(char *token){{{{

List *temp = F_Token(token);List *temp = F_Token(token);List *temp = F_Token(token);List *temp = F_Token(token);if (temp) // Found,if (temp) // Found,if (temp) // Found,if (temp) // Found,{{{{

temp->count++;temp->count++;temp->count++;temp->count++;}}}}elseelseelseelse{{{{

int len = strlen(token)+1;int len = strlen(token)+1;int len = strlen(token)+1;int len = strlen(token)+1;temp = (List*)malloc(sizeof(List));temp = (List*)malloc(sizeof(List));temp = (List*)malloc(sizeof(List));temp = (List*)malloc(sizeof(List));temp->word = (char*)malloc(sizeof(char)*len);temp->word = (char*)malloc(sizeof(char)*len);temp->word = (char*)malloc(sizeof(char)*len);temp->word = (char*)malloc(sizeof(char)*len);strncpy(temp->word, token, len);strncpy(temp->word, token, len);strncpy(temp->word, token, len);strncpy(temp->word, token, len);temp->count = 1;temp->count = 1;temp->count = 1;temp->count = 1;temp->next = 0;temp->next = 0;temp->next = 0;temp->next = 0;tail->next = temp;tail->next = temp;tail->next = temp;tail->next = temp;tail=temp;tail=temp;tail=temp;tail=temp;

word_count++;word_count++;word_count++;word_count++;}}}}

}}}}

void free_token()void free_token()void free_token()void free_token(){{{{

List *temp;List *temp;List *temp;List *temp;while (temp = head.next)while (temp = head.next)while (temp = head.next)while (temp = head.next){{{{

if (temp->word)if (temp->word)if (temp->word)if (temp->word)free(temp->word);free(temp->word);free(temp->word);free(temp->word);

head.next = temp->next;head.next = temp->next;head.next = temp->next;head.next = temp->next;

Page 21: Project#4상호참조 생성기 Hwp

free(temp);free(temp);free(temp);free(temp);}}}}tail = &head;tail = &head;tail = &head;tail = &head;

}}}}

typedef List *T;typedef List *T;typedef List *T;typedef List *T;

void swap(T *a, T *b)void swap(T *a, T *b)void swap(T *a, T *b)void swap(T *a, T *b){{{{

T t = *a;T t = *a;T t = *a;T t = *a;*a = *b;*a = *b;*a = *b;*a = *b;*b = t;*b = t;*b = t;*b = t;

}}}}

int comp(const void *pa, const void *pb)int comp(const void *pa, const void *pb)int comp(const void *pa, const void *pb)int comp(const void *pa, const void *pb){{{{

const T a = *(const T *)pa;const T a = *(const T *)pa;const T a = *(const T *)pa;const T a = *(const T *)pa;const T b = *(const T *)pb;const T b = *(const T *)pb;const T b = *(const T *)pb;const T b = *(const T *)pb;

return strcmp(a->word,b->word);return strcmp(a->word,b->word);return strcmp(a->word,b->word);return strcmp(a->word,b->word);}}}}

int partition(T *A, int left, int right, int pivot)int partition(T *A, int left, int right, int pivot)int partition(T *A, int left, int right, int pivot)int partition(T *A, int left, int right, int pivot){{{{

int i, index;int i, index;int i, index;int i, index;T value = A[pivot];T value = A[pivot];T value = A[pivot];T value = A[pivot];

swap(&A[pivot],&A[right]);swap(&A[pivot],&A[right]);swap(&A[pivot],&A[right]);swap(&A[pivot],&A[right]);index = left;index = left;index = left;index = left;for (i = left; i < right; i++) {for (i = left; i < right; i++) {for (i = left; i < right; i++) {for (i = left; i < right; i++) {

if (comp(&A[i],&value) < 0) {if (comp(&A[i],&value) < 0) {if (comp(&A[i],&value) < 0) {if (comp(&A[i],&value) < 0) {swap(&A[i],&A[index]);swap(&A[i],&A[index]);swap(&A[i],&A[index]);swap(&A[i],&A[index]);++index;++index;++index;++index;

}}}}}}}}swap(&A[index],&A[right]);swap(&A[index],&A[right]);swap(&A[index],&A[right]);swap(&A[index],&A[right]);return index;return index;return index;return index;

}}}}

void quick_p(T *A, int left, int right)void quick_p(T *A, int left, int right)void quick_p(T *A, int left, int right)void quick_p(T *A, int left, int right){{{{

int pivot;int pivot;int pivot;int pivot;int index;int index;int index;int index;

Page 22: Project#4상호참조 생성기 Hwp

if (right > left) {if (right > left) {if (right > left) {if (right > left) {pivot = (right+left)/2;pivot = (right+left)/2;pivot = (right+left)/2;pivot = (right+left)/2;index = partition(A, left, right, pivot);index = partition(A, left, right, pivot);index = partition(A, left, right, pivot);index = partition(A, left, right, pivot);quick_p(A, left, index-1);quick_p(A, left, index-1);quick_p(A, left, index-1);quick_p(A, left, index-1);quick_p(A, index+1, right);quick_p(A, index+1, right);quick_p(A, index+1, right);quick_p(A, index+1, right);

}}}}}}}}

void quicksort(T *A, int n)void quicksort(T *A, int n)void quicksort(T *A, int n)void quicksort(T *A, int n){{{{

quick_p(A,0,n-1);quick_p(A,0,n-1);quick_p(A,0,n-1);quick_p(A,0,n-1);}}}}

int main(void)int main(void)int main(void)int main(void){{{{

char *str;char *str;char *str;char *str;char *token;char *token;char *token;char *token;long length;long length;long length;long length;int i=0;int i=0;int i=0;int i=0;

FILE* fp = fopen("C:\\test.txt", "rt");FILE* fp = fopen("C:\\test.txt", "rt");FILE* fp = fopen("C:\\test.txt", "rt");FILE* fp = fopen("C:\\test.txt", "rt");

if (fp==NULL)if (fp==NULL)if (fp==NULL)if (fp==NULL){{{{

puts("File open fail!");puts("File open fail!");puts("File open fail!");puts("File open fail!");return -1;return -1;return -1;return -1;

}}}}

fseek(fp, 0, SEEK_END);fseek(fp, 0, SEEK_END);fseek(fp, 0, SEEK_END);fseek(fp, 0, SEEK_END);length = ftell(fp);length = ftell(fp);length = ftell(fp);length = ftell(fp);rewind(fp);rewind(fp);rewind(fp);rewind(fp);

str = (char*)malloc(sizeof(char)*length+1);str = (char*)malloc(sizeof(char)*length+1);str = (char*)malloc(sizeof(char)*length+1);str = (char*)malloc(sizeof(char)*length+1);memset(str, 0, sizeof(char)*length+1);memset(str, 0, sizeof(char)*length+1);memset(str, 0, sizeof(char)*length+1);memset(str, 0, sizeof(char)*length+1);

상호참조 생성기상호참조 생성기상호참조 생성기상호참조 생성기puts("***************** *****************");puts("***************** *****************");puts("***************** *****************");puts("***************** *****************");단어 빈도수단어 빈도수단어 빈도수단어 빈도수puts("**************** : ******");puts("**************** : ******");puts("**************** : ******");puts("**************** : ******");

fread(str, 1, length, fp);fread(str, 1, length, fp);fread(str, 1, length, fp);fread(str, 1, length, fp);fclose(fp);fclose(fp);fclose(fp);fclose(fp);token=strtok(str,SIGN);token=strtok(str,SIGN);token=strtok(str,SIGN);token=strtok(str,SIGN);while (token!=NULL)while (token!=NULL)while (token!=NULL)while (token!=NULL){{{{

InsertList(token);InsertList(token);InsertList(token);InsertList(token);

Page 23: Project#4상호참조 생성기 Hwp

token=strtok(NULL,SIGN);token=strtok(NULL,SIGN);token=strtok(NULL,SIGN);token=strtok(NULL,SIGN);}}}}

W = (List **)malloc(sizeof(List*)*word_count);W = (List **)malloc(sizeof(List*)*word_count);W = (List **)malloc(sizeof(List*)*word_count);W = (List **)malloc(sizeof(List*)*word_count);array(&head, W);array(&head, W);array(&head, W);array(&head, W);

quicksort(W,word_count);quicksort(W,word_count);quicksort(W,word_count);quicksort(W,word_count);// qsort(W,word_count,sizeof(T),comp);// qsort(W,word_count,sizeof(T),comp);// qsort(W,word_count,sizeof(T),comp);// qsort(W,word_count,sizeof(T),comp);

printW(W,word_count);printW(W,word_count);printW(W,word_count);printW(W,word_count);

free(W);free(W);free(W);free(W);free_token();free_token();free_token();free_token();

system("pause");system("pause");system("pause");system("pause");return 0;return 0;return 0;return 0;

}}}}

Page 24: Project#4상호참조 생성기 Hwp

문제점문제점문제점문제점5.5.5.5.

단어별 라인이 나오지 않음.단어의 대소문자 구별해서 나옴.단어의 총 개수가 출력되지 않음.

Page 25: Project#4상호참조 생성기 Hwp

최종안최종안최종안최종안6.6.6.6.#include <stdio.h>#include <string.h>#include <stdlib.h>

#define MAX 1000

char SIGN[] = " .,!?:\"\t\r\n";

typedef struct List{

char *word;int count;struct List *next;

} List;

List head={0,};List* tail = &head;

int word_count = 0; // # of wordsList **W = 0;

void list2array(List *head, List **W){

List *temp = head->next;int i = 0;while (temp){

W[i++] = temp;temp = temp->next;

}}

void printW(List **W, int n){

int count=0;int i;for(i=0; i < n; i++) {

printf("%20s : %d\n",W[i]->word, W[i]->count);count++;

}

Page 26: Project#4상호참조 생성기 Hwp

printf("\t\ttotal=%d",count);

}

List* FindToken(const char* token){

List *temp = head.next;while (temp){

if (strcmp(temp->word,token)==0)return temp;

temp = temp->next;}return 0;

}

void InsertList(char *token){

List *temp = FindToken(token);if (temp) // Found,{

temp->count++;}else{

int len = strlen(token)+1;temp = (List*)malloc(sizeof(List));temp->word = (char*)malloc(sizeof(char)*len);strncpy(temp->word, token, len);temp->count = 1;temp->next = 0;tail->next = temp;tail=temp;

word_count++;}

}

void print_token()

Page 27: Project#4상호참조 생성기 Hwp

{List *temp = head.next;FILE* fw = fopen("daul\\Ouput.txt", "wt");

while (temp){

fprintf(fw, "%s : %d\n", temp->word, temp->count);temp = temp->next;

}fclose(fw);

}

void free_token(){

List *temp;while (temp = head.next){

if (temp->word)free(temp->word);

head.next = temp->next;free(temp);

}tail = &head;

}

정렬할 자료형typedef List *T; // T

void swap(T *a, T *b){

T t = *a;*a = *b;*b = t;

}

int comp(const void *pa, const void *pb){

const T a = *(const T *)pa;const T b = *(const T *)pb;

return strcmp(a->word,b->word);}

Page 28: Project#4상호참조 생성기 Hwp

int partition(T *A, int left, int right, int pivot){

int i, index;T value = A[pivot];

swap(&A[pivot],&A[right]);index = left;for (i = left; i < right; i++) {

if (comp(&A[i],&value) < 0) {swap(&A[i],&A[index]);++index;

}}swap(&A[index],&A[right]);return index;

}

void quickpart(T *A, int left, int right){

int pivot;int index;

if (right > left) {pivot = (right+left)/2;index = partition(A, left, right, pivot);quickpart(A, left, index-1);quickpart(A, index+1, right);

}}

void quicksort(T *A, int n){

quickpart(A,0,n-1);}

int main(void){

char *str; // File total Length,char *token; // token,

파일전체길이long length; //int i=0;

텍스트모드로 읽기FILE* fp = fopen("cmake.txt", "rt"); //

Page 29: Project#4상호참조 생성기 Hwp

// Open not file,if (fp==NULL){

puts("File open fail!");return -1;

}

fseek(fp, 0, SEEK_END);length = ftell(fp);rewind(fp);

str = (char*)malloc(sizeof(char)*length+1);memset(str, 0, sizeof(char)*length+1);

상호참조 생성기상호참조 생성기상호참조 생성기상호참조 생성기puts("***************** *****************");puts("***************** *****************");puts("***************** *****************");puts("***************** *****************");단어 빈도수단어 빈도수단어 빈도수단어 빈도수puts("**************** : ******");puts("**************** : ******");puts("**************** : ******");puts("**************** : ******");

자료주소값 바이트크기 개수 파일포인터fread(str, 1, length, fp); // , , ,파일 닫기fclose(fp); //

단어 수집//문자열자르기token=strtok(str,SIGN); //

while (token!=NULL){

InsertList(token);두번째토큰 호출부터는 첫 번째 인수자리에 기입// , NULL

token=strtok(NULL,SIGN);}

단어의 포인터 배열//W = (List **)malloc(sizeof(List*)*word_count);

리스트에서 배열로list2array(&head, W); //

정렬quicksort(W,word_count); //정렬// qsort(W,word_count,sizeof(T),comp); //

정렬 출력printW(W,word_count); //

free(W);free_token();return 0;

}

Page 30: Project#4상호참조 생성기 Hwp

느낀점느낀점느낀점느낀점7.7.7.7.

초안에서의 문제점은 아래와 같다.단어별 라인이 나오지 않음 개선.-> X

를 이용하여라인출력을 하고자 하였으나 실패함:fscanf , , .

단어의 대소문자 구별해서 나옴 개선.-> X을 이용하여 단어를 구분해주었는데 여기서 대소문자 구별하는 방법을 찾아내지 못함strtok , , .

단어의 총 개수가 출력되지 않음 개선.-> O