Your SlideShare is downloading. ×
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
자료구조4보고서
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

자료구조4보고서

404

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
404
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. project #4 상호참조 생성기 자료구조 01 조 : C3 조장 : 20093463 김창헌 조원 : 이상현 20093452 김시백 20113286 박가혜 20113281 김정무
  • 2. 순 서1. 프로젝트 설명 1) 트리(trees) 2) AVL 트리(trees)2. 프로젝트 전체일정3. 업무분담4. 초안5. 문제점6. 최종안7. 느낀점8. 조원평가
  • 3. 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가 아니다. 그림이 잘못되었답니다. 
  • 4. 트리의 용어들 용 어 내 용 설명 Node vertex 정보를 나타냄 그림에서 A, B, C, D, ... 와 같은 객체를 노 드라고 한다. Link edge Node의 연결관계를 나타 그림에서 선으로 나타낸것을 링크라고 한다. 냄 Root Node   부모가 없는 최상위 노드 하나만 존재해야 한다. Terminal Leaf Node Node 자식이 없는 최하위 노드 그림에서 하늘색으로 색칠된 노드들이 Leaf( External 잎 ) Node이다. Node Internal Node Non-Term Leaf Node가 아닌 노드 자식이 하나라도 있는 노드 그림에서 A, B, inal Node C, I 가 인터널 노드가 된다. B를 시작으로 트리를 떼어내면 Sub tree가 Sub tree   트리의 부분집합 된다. 그림에서 E 에서 C로 가는 경로는 E->B->A->C이다. 이 경로는 유일해야 한다. Path   한 Node로 부터 다른 ( 다른 경로는 없다. ) 중복이 없어야 한다. Node로 가는 경로 만약, G-C가 연결되어 있다면 이것은 트리라 고 할 수 없다. ( 이런 자료구조는 그래프라 고 부른다. ) 최소 공통 선 L e a s t 두 노드의 공통적인 선조 그림에서 H와 J를 보면 두 노드의 공통 선 조 C o mm on 중 가장 레벨이 높은 선 조는 A, C가 있는데 그중 C는 Level이 2 이 Ancestors 조 노드 므로 C가 H, J의 최소 공통 선조가 된다. 자식 Children 자신의 아래로 연결된 노 C의 자식 노드는 H와 I가 있다. 드 부모 Parent 자신의 위로 연결된 노드 I의 부모는 C이고 C의 노드는 A이다. G r a n d 조부모란 할아버지급 노드를 말한다. 즉 I의 조부모 Parent 자신의 부모의 부모노드 조부모는 A이고 J의 조부모는 C이다. Root에서 특정 노드로 그림에서 I를 보면 경로에 A, C, I 3개의 노 레벨 Level 가는 경로의 노드 수 드를 갖는다. 그래서 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
  • 5. Full Binary Tree마지막 레벨을 제외한 모든 레벨에 노드가 꽉차있음Complete Binary Tree모든 레벨에 노드가 꽉 차있음 <full binary tree와 complete binary tree>왼쪽의 그림을 보자. 자식이 많아 봐야 2개이다. 이런 트리를 이진트리라고 하는 것이다. 그런데 이진트리 중에서도 Full binary tree와 Complete binary tree가 있는데, 왼쪽은 마지막 레벨 즉, H, I, J 4레벨에서는 노드가 꽉 차있지 않지만 마지막 레벨을 제외한 모든 레벨에 노드가 꽉 차 있으므로 Full binarytree라고 하고, 오른쪽 그림 처럼 모든 레벨에 노드가 꽉 차있으면 Complete( 완벽한 ) binary tree라고부른다. Full Binary Tree의 성질레벨과 노드의 수 관계레벨이 d일때, 트리의 노드수 N은 다음을 만족2d-1 ≤ N ≤ 2d - 1N개의 노드를 가진 이진 트리의 레벨 d는 다음과 같다.d = [ log2N ] + 1 ( [ ]는 소수점 이하는 버림한다. )숫자놀이를 해보자. ( Level = d, Node count = N ) d-1 d2 ≤ N ≤ 2 - 1 ( 노드의 갯수는 이 범위안에 속한다. )d = 2일때, 22-1 ≤ 노드의 갯수 ≤ 22 - 12 ≤ N ≤ 3 이 된다.d = 3 일때, 23-1 ≤ 노드의 갯수 ≤ 23 - 14 ≤ 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노드를 뺀 갯수가 되는 것이다. ) 
  • 6. Level d를 구하는 이 증명은 자료구조 시험문제에 가끔 나오니 알아두도록 하자. d-1 d2 ≤ N ≤ 2 - 1부등식에 log2를 취하면,d - 1 ≤ log2N ≤ log2( 2d - 1 ) d d n log2( 2 - 1 )는 log22 - log21즉, log2와2가 소거되어 d가 되고 - log21은 - 0이 된다. ( 2 = 1일때 n은 0 )결국 수식을 정리해 보면d - 1 ≤ log2N <d 이렇게 되는데, 부등식에 1을 더하면d ≤ log2N + 1 <d + 1 여기에서 log2N + 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
  • 7. 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{
  • 8. 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시작과 끝을 나타내는 가짜노드 두개를 만듦DesturctorRemoveAll을 호출한 뒤, 가짜 노드를 지움Tree의 모든 Node를 지우기 위해서 모든 노드를 방문하는 방법이 필요함 생성자에서는 그러니까.. 나중에 void Main()함수에서 이 클래스를 사용해 객체를 만들때, BinaryTreeb1(); 객체 b1이 생성될때 어떠한 구조로 생성이 되는가? BinaryTree인 b1은 메모리상에 Head 가짜노드와 Tail 가짜노드가 만들어 지고 그 Head와Tail의 pLeft,pRight는 저~기 위쪽 그림과 같이 연결되어 있다.그럼 이 b1의 객체에 b1.Insert( "홍길동" ); 하게 되면 그 노드가 삽입되어 연결되는 것이다.생성자에서 어떤 구조를 형성하는지 잘 생각해보고 넘어가자.
  • 9. 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를 방문한다.
  • 10. 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를 방문한다.
  • 11. 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를 방문한다.
  • 12.  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 );// ... 그림을 놓고 이해를 하는게 빠르다. 
  • 13. 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 )
  • 14. 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를 배치
  • 15. . 모든 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에 Push2. Operator를 만나면 Node를 생성하여1. Stack에서 Pop한 노드를 오른쪽 자식으로 하고2. Stack에서 또 Pop한 노드를 왼쪽 자식으로 하고3. Operator Node와 링크된 두 자식 노드 자체를 Stack에 Push3. Stack에 마지막으로 남은 노드가Root 이다.위에 그림과 같이 되게 된다. 7.6 수식 트리의 구현 • Skeleton • BuildParseTree ParseTree skeleton구성. template의 instance로 부터 계승을 받음. BuildParseTree : ParseTree 구성. Traversal Functions
  • 16. 상위 클래스에서 이미 구현된 부분은 구현할 필요가 없다. 이게 계승의 장점이다.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++;            }
  • 17.             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
  • 18. 2. 프로젝트 전체일정 기 간 5 / 8 5 / 10 - 조원별 업무 분담 및 계획 작성 - 프로젝트 문제파악 - 알고리즘에 대해 토의하고 이해 내 용 - 프로젝트에 필요한 학습내용 토의 - 문제점 토의 - 프로젝트 진행방향 토의 기 간 5 / 15 5 / 17 - 프로젝트 검토 내 용 - 소스 구현 및 보고서 작성 - 최종보고서 작성 - 발표준비3. 업무분담 이 름 업 무 김창헌 보고서 작성 및 회의 진행, 프로젝트에 필요한 학습내용 숙지 김시백 알고리즘 설계와 소스에 대한 문제점 검토와 보완 박가혜 소스구현 및 코딩 문제의 해결을 위한 방안 제시 김정무 알고리즘 설계 및 프로젝트 수행 시 필요한 자료 수집 이상현 알고리즘 설계 및 프로젝트 수행 시 필요한 자료 수집
  • 19. 4. 초안#include <stdio.h>#include <string.h>#include <stdlib.h>#define MAX 1000char SIGN[] = " .,!?:"trn";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 array(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 i; for(i=0; i < n; i++) { printf("%20s : %dn",W[i]->word, W[i]->count); }}
  • 20. List* F_Token(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 = F_Token(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 free_token(){ List *temp; while (temp = head.next) { if (temp->word) free(temp->word); head.next = temp->next;
  • 21. free(temp); } tail = &head;}typedef List *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);}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 quick_p(T *A, int left, int right){ int pivot; int index;
  • 22. if (right > left) { pivot = (right+left)/2; index = partition(A, left, right, pivot); quick_p(A, left, index-1); quick_p(A, index+1, right); }}void quicksort(T *A, int n){ quick_p(A,0,n-1);}int main(void){ char *str; char *token; long length; int i=0; FILE* fp = fopen("C:test.txt", "rt"); 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("****************단어 : 빈도수******"); fread(str, 1, length, fp); fclose(fp); token=strtok(str,SIGN); while (token!=NULL) { InsertList(token);
  • 23. token=strtok(NULL,SIGN); } W = (List **)malloc(sizeof(List*)*word_count); array(&head, W); quicksort(W,word_count);// qsort(W,word_count,sizeof(T),comp); printW(W,word_count); free(W); free_token(); system("pause"); return 0;}
  • 24. 5. 문제점단어별 라인이 나오지 않음.단어의 대소문자 구별해서 나옴.단어의 총 개수가 출력되지 않음.
  • 25. 6. 최종안#include <stdio.h>#include <string.h>#include <stdlib.h>#define MAX 1000char SIGN[] = " .,!?:"trn";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 : %dn",W[i]->word, W[i]->count); count++; }
  • 26. printf("tttotal=%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()
  • 27. { List *temp = head.next; FILE* fw = fopen("daulOuput.txt", "wt"); while (temp) { fprintf(fw, "%s : %dn", 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; // 정렬할 자료형 Tvoid 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);}
  • 28. 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"); //텍스트모드로 읽기
  • 29. // 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("****************단어 : 빈도수******"); 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;}
  • 30. 7. 느낀점초안에서의 문제점은 아래와 같다.단어별 라인이 나오지 않음.->개선X:fscanf를 이용하여,라인출력을 하고자 하였으나, 실패함.단어의 대소문자 구별해서 나옴.->개선Xstrtok을 이용하여, 단어를 구분해주었는데, 여기서 대소문자 구별하는 방법을 찾아내지 못함.단어의 총 개수가 출력되지 않음.->개선O

×