Data structure: Assignment 3 Seung-Hoon Na December 14, 2018 레드 블랙 트리 (Red-Black Tree) 1 본 절에서는 레드 블랙 트리를 2-3트리 또는 2-3-4트리 대한 동등한 자료구조로 보고, 두 가지 유형의 레드 블랙 트리를 구현하고자 한다. 1.1 2-3트리와 동등한 레드 블랙 트리 2-3트리와 동등한 레드 블랙 트리에서는, 교과서의 그림 13-24처럼, 2-노드와 3-노 드에 대응되는 레드브랙트리만 허용하고 4-노드는 허용하지 않는다. 따라서 다음그 림과 같이 4-노드에 해당되는 연결된 빨강링크를 갖는, 3가지 경우가 모두 허용되지 않는다. 그리고, 3-노드의 경우에는 빨강 링크가 어느방향으로 기울어지느냐에 따라 두 가지 경우가 존재하나, 본 문제에서는 빨강 링크가 왼쪽으로 기울어진 (lean left) 경우로만 한정한다 정리하면, 2-3트리와 등가인 레드 블랙 트리의 특징은 다음과 같다. 1
빨강 링크는 왼쪽으로 기울어진 좌측 경사의 경우만 허용한다 (lean left) 두 개이상의 연결된 빨강 링크는 허용하지 않는다. 검정 링크들은 완전 균형을 이룬다. 즉, 트리의 루트에서 모든 리프 노드에 이 르는 경로들의 검정 링크의 수는 모두 같다. 리프 노드에 이르는 검정 링크의 수를 black height라 한다. 1.1.1 2-3트리와 동등한 레드 블랙 트리: 삽입 및 삭제 알고리즘 2-3트리와 동등한 레드 블랙 트리상에서 삽입 및 삭제 알고리즘을 제시하고 각 경우에 대한 예제를 기술하시오. 1.1.2 2-3트리와 동등한 레드 블랙 트리: 삽입 및 삭제 알고리즘 구현 트리 노드를 위해 다음 자료구조를 가정하고, 위에서 설계한 삽입 및 삭제 알고리 즘을 구현하시오 (RBtree.cpp코드 작성). #define RED true #define BLACK false typedef struct treerecord int key; struct treerecord * LChild; struct treerecord * RChild; bool color; }node; typedef node* Nptr; 1.1.3 2-3트리와 동등한 레드 블랙 트리: 삽입 및 삭제 알고리즘 테스트 위의 구현된 내용을 테스트하기 위해 2-3트리와 동일한 레드블랙트리인지를 검사 하는 테스트 함수 RBVerify를 작성하시오 (필요하면 위의 자료구조를 확장해도 좋다 (black height등)). bool RBVerify(Nptr node); (위의 세 가지 특징을 검증해야 함) 또한, 다음을 테스트하는 코드를 작성하고, 출력결과를 요약적으로 리포트하시 오 (RBtree test.cpp코드 작성). (화면상 출력결과를 모두 copy할 필요는 없이, 핵심만 리포트) 10,20,30,40,50,60,70,80,90,100을 삽입, 트리 출력, RBVerify로 검증, 및 black height출력 10, 20,..., 1000의 1000개의 데이터를 순서대로 삽입, RBVerify로 검 증, 및 black height출력. 랜덤하게 10,000개의 데이터 삽입 RBVerify로 검증 및 black height출력. 랜덤하게 100,000개의 데이터 삽입 RBVerify로 검증 및 black height출력. 2
랜덤하게 100,000개의 데이터 삽입 후 100,000 삭제, 삭제시마다 RBVerify 로 검증 및 black height출력. 그외 다른 테스트 수행 테스트시 트리를 출력하는 경우에는 다음의 코드를 사용하라. void RBPrettyPrint(const std::string& prefix, Nptr node, bool isleft) if( node!= NULL ) cout << prefix; if(node->color == RED) cout << (isleft? " " : " " ); else cout << (isleft? " " : " " ); cout << node->key ; if(node->color == RED) cout << "*"; cout << endl; RBPrettyPrint( prefix + (isleft? " " : " "), node->lchild, true); RBPrettyPrint( prefix + (isleft? " " : " "), node->rchild, false); } } //RBPrettyPrint("", root, false); when calling it with the root node. 예를 들어, 다음은 10,20,30,40,50,60,70,80,90,100을 삽입후 위 코드를 이용한 출력 결과이다. 40 20 10 30 80 60 * 50 70 100 90 * 1.2 2-3-4트리와 동등한 레드 블랙 트리 2-3-4트리와 동등한 레드 블랙 트리에 대한 내용은 교과서 13장 5절을 참조하라. 1.2.1 2-3-4트리와 동등한 레드 블랙 트리: 삽입 및 삭제 알고리즘 (2-3트리의 문항에서처럼) 2-3-4트리와 동등한 레드 블랙 트리상에서 삽입 및 삭제 알고리즘을 제시하고 각 경우에 대한 예제를 기술하시오. 3
1.2.2 2-3-4트리와 동등한 레드 블랙 트리: 삽입 및 삭제 알고리즘 구현 (2-3트리의 문항에서처럼) 앞 문항의 treerecord를 사용하여 위에서 설계한 삽입 및 삭제 알고리즘을 구현하시오 (RBtree 234.cpp코드 작성). 1.2.3 2-3-4트리와 동등한 레드 블랙 트리: 삽입 및 삭제 알고리즘 테스트 2-3트리의 문항에서처럼, 2-3-4트리와 동일한 레드블랙트리인지를 검사하는 테스 트 함수 RBVerify를 작성하시오). 또한, 2-3트리의 문항에서 주어진 각 경우에 대해 테스트하는 코드를 작성하고, 출력결과를 요약적으로 리포트하시오 (RBtree 234 test.cpp코드 작성). (마찬가 지로 화면상 출력결과를 모두 copy할 필요는 없이, 핵심만 리포트) 2 트라이 (Trie) 본 절에서는 영문 소문자 알파벳을 radix단위로 하는 트라이(trie)를 구현하는 것이 목표이다. 다음은 by, bye, byte, data, day, done, do, did를 순서대로 삽입한 트라이의 구조이다. (값은 순서대로 0, 1,, 7까지 부여되었다고 가정) 본 절에서는 트라이 각 노드 표현을 위해 다음 자료구조를 사용한다. #define NUM_ALPHABET 26 typedef struct trierecord int val; struct trierecord **nodes; } node; typedef node* Nptr; Nptr CreateTrieNode() Nptr p = new node; 4
p->nodes = new node*[num_alphabet]; for(int i=0;i<num_alphabet;i++) p->nodes[i] = NULL; return p; } 2.1 트라이 클래스 구현 주어진 트라이 노드에 대한 자료구조에 기반하여, 영문 소문자 알파벳으로 구성된 문자열에 대해 트라이 클래스 class의 Insert, Update, Delete, Save, Open을 완성하시오. (Trie.h, Trie.cpp). class Trie public: int size; Nptr *root; public: void Create(); int Insert(const char *key, int val); Nptr Search(const char *key); void Delete(const char *key); void Save(const char *filename); void Open(const char *filename); ; } 각 함수에 대한 정의는 다음과 같다. Create: 트라이를 새롭게 생성한다. Insert: 주어진 key에 대해 값이 val인 노드를 트라이에 삽입한다. 만약 이미 동일한 key가 존재하면, val로 값을 변경한다. Search: 주어진 key에 대한 트라이 노드를 리턴한다. 만약 key가 존재하지 않으면 NULL을 리턴한다. Delete: 주어진 key에 대한 트라이 노드를 삭제한다. Save: 트라이를 binary또는 text파일로 저장한다. 차후 빠르게 loading할수 있도록 파일 포맷을 잘 설계해야 한다. Open: 저장한 트라이 파일을 읽어들여 메모리상으로 loading한다. 2.1.1 트라이를 이용한 Word count계산 및 사용자 테스트 트라이를 이용하여 주어진 텍스트 파일에 있는 각 단어의 word count를 계산하고, 계산된 결과를 해쉬 파일로 저장하는 Trie word count.cpp를 작성하시오. (word count를 1씩 증가시키기 위해 트라이 클래스상의 새로운 함수 Update를 추가해도 된다. 그렇지 않으면 Search후에 Insert하는 방식으로 word count를 계산하라.) 구동 테스트를 위해 다음 두 가지 입력 파일에 대해 테스트를 수행하고, 트 라이의 내용을 각각 The-Road-Not-Taken.trie, Dickens Oliver 1839.trie에 저장하시오.. 5
http://nlp.jbnu.ac.kr/ds2018/data/the-road-not-taken.tokens.txt http://nlp.jbnu.ac.kr/ds2018/data/dickens Oliver 1839.tokens.txt 추가로, 저장된 트라이 파일 The-Road-Not-Taken.trie, Dickens Oliver 1839. trie를 로딩하여 트라이를 메모리에 올린후, 사용자로부터 단어를 입력단어 Search 를 수행하여 해당 단어가 있으면 count를 그러지 않으면 Not found를 출력하는 코드 Trie word count test.cpp를 작성하시오. 2.1.2 트라이와 해시 및 이진탐색트리 효율 비교 과제2에서 구현된 해시와 이진탐색 효율 비교를 위해, Dickens Oliver 1839. tokens.txt상에서 N 개의 랜덤 key에 대해 Search를 호출할 때 트라이와 해시 그리고 이진탐색트리간의 소요시간을 비교하시오 (N = 100000이상). (본 절에서 는 트라이의 소요시간파악이 핵심 주제이다) 3 네비게이터 본 절에서는 임의의 랜덤 도로 맵에서 시작위치에서 끝 위치까지 최단 경로를 탐 색하는 네비게이터 (navigator)를 구현하는 것을 목표로 한다. 네비게이터는 1000 1000의 맵 프레임과 1) 랜덤 로드 생성, 2) 최단 경로 탐색, 3) MST 탐색 의 세 개의 버튼으로 구성된다. 다음은 구현하고자 하는 네이게이터 GUI의 개략도이다. 네이게이터 구동을 요약하면 다음과 같다. 먼저 맵 프레임상에서 N 개의 도로(road)를 랜덤하게 생성한 후에 도로들의 교차점을 계산한 후, 해당 교차점을 정점으로 하고, 인접된 두 교차점마다 간선을 형성하고, 두 교차점간의 도로상 직선 거리를 간선의 가중치로 하는 교차점 그래프 (가중치 그래프)를 만든다. 다음, 네비게이션 모드에서는, 사용자의 시작지점과 도착지점을 마우스로 입력 받은 후, 시작지점에서 가장 가까운 교차점을 시작교차점으로 도착지점에서 가장 가까운 교차점을 끝교차점 으로 하여 시작교차점에서 끝교차점까지의 최단경로를 6
다익스트라(Dijkstra)알고리즘을 통해 계산하고, 탐색된 최단 경로를 맵 프레임상 에서 출력한다. 사용자가 지정한 시작/도착지점별로 가까운 교차점까지 이동하는 경로도 출력에 포함되어야 한다. 다음은 최단 경로 출력 예를 보여준다. 이외에 교차점 그래프상에서 모든 교차점을 연결하는 최소신장트리를 구하여 화면에 출력한다. 네비게이터 GUI관련 요구사항을 정리하면 다음과 같다. 맵 프레임: 1000 1000크기의 프레임으로 초기에 랜덤으로 생성된 도로 (Road)를 보여준다. 각 도로는 프레임의 경계에서 시작하고 끝나야 하며, 모든 도로의 교차점은 보다 큰 원으로 표시하여 구분되어야 한다. Generate Random Roads 버튼: 맵을 다시 새롭게 생성하는 버튼이다. 이전 맵은 지우고, 랜덤하게 N 개의 로드를 생성하여 화면에 출력한다. Find Shortest Path 버튼: 사용자 마우스로부터 시작지점와 도착지점를 입력받은 후에 해당 버튼을 클릭하면 다익스트라알고리즘을 통해 최단 경 로를 탐색한다. 탐색결과의 최단 경로상의 도로들은 별도의 색상으로 다른 도로들과는 구분해서 보여주어야 한다. 만약 사용자로부터 아직 시작위치와 끝 위치를 입력받지 못한 경우에는 시작지점와 끝지점의 위치를 마우스로 클릭하시오 라는 대화상자를 제시한다. 최단경로의 최종 거리도 화면상 출 력하라 (시작지점 시작교차점 끝교차점 끝지점에 이르는 거리) Get MST 버튼: 프림알고리즘 (Prim s algorithm) 또는 크루스칼 알고리 즘 (Kruskal s algoirthm)을 적용하여 모든 교차점을 연결하는 Minimum Spanning Tree(MST)를 찾아, 화면에 출력한다. 마찬가지로, MST상의 로드 들은 별도의 색상으로 다른 도로들과 구분해서 보여주어야 한다. 최소신장 트리의 Cost도 화면상 출력하라. 마우스 입력: 시작/끝 지점 설정: 사용자의 마우스 왼쪽 버튼 클릭시에 위치 를 시작지점으로, 오른쪽 버튼 클릭시 위치를 도착지점으로 한다. 7
3.1 네비게이터 구현 (java로 작성) 네이게이터 GUI 요구사항이 모두 충족되도록 해당 코드를 java로 구현한다 (Navigator. java포함 각종 클래스 구현 파일). 구현할 내용의 핵심들은 다음과 같다. 랜덤 도로 생성 도로간 교차점 계산 교차점 그래프 생성 최단 경로 탐색 알고리즘 최소 신장 트리 계산 알고리즘 화면에 출력하는 GUI 코드 본 과제는 알고리즘 구현외에도, GUI환경에서 테스트가 될 수 있도록 GUI 입출력부분도 함께 정교하게 구현되어야함을 유의해야 한다. 3.2 네비게이터 테스트 콘솔모드 테스트와 GUI모드 테스트 모두 지원되도록 하고, 랜덤 도로의 갯수 N 을 7, 20, 50, 100을 포함하여 4개이상 시작지점와 끝지점을 달리하면서 다양하게 테스트하라. 보고서에는 N = 50인 경우의 콘솔모드 및 GUI출력 결과를 1) 랜덤도로생성, 2) 최단경로탐색결과, 3) MST계산결과 로 정리해서 제시하라. 콘솔모드의 경우 테스트 요구사항은 다음과 같다. 교차점 그래프 정보 출력: 콘솔모드의 경우에는 랜덤 로드 생성후, 다음과 같이 교차점 그래프 정보가 출력되도록 하라. 교차점 갯수, 간선 수 각 교차점 정보: 교차점의 위치 (x, y좌표)와 인덱스, 해당 교차점과 연 결된 교차점 인덱스와 거리의 리스트) 랜덤 입력 가정: 시작지점과 끝지점은 사용자 입력을 받는대신 랜덤으로 입 력되도록 하고, 이에 최단경로탐색을 수행한다. 출력 방법: 최단경로는 경로상의 교차점 인덱스들의 리스트를, MST는 간 선 및 간선의 가중치를 출력하여 표현하라. (간선은 (u, v)로 교차점 인덱스 쌍으로 출력) GUI모드의 경우에 1) 랜덤도로생성, 2) 최단경로탐색결과, 3) MST계산결 과 각 단계별로 출력되는 GUI화면을 캡처하여 제시하라. 콘솔모드는 대량의 랜덤 입력 테스트가 목적이며, GUI화면상의 인터페이스가 완벽하게 구동되는것이 본 절에서의 메인테스트임을 유의하라. 8
4 제출 내용 및 평가 방식 코드는 c++ (특별한 요구사항이 있을 경우 java)로 작성하도록 하고, c++프로 그램의 경우 구동os환경은 ubuntu 16.04 LTS 이상을 원칙으로 한다. 본 과제 결과물로 필수적으로 제출해야 내용들은 다음과 같다. java프로그램은 windows 10또는 ubuntu 16.04 LTS에서 동작되도록 하면 되며, 보고서에 구동 환경을 명확히 명시 (java버전 등도 함께 기술 )하라. 코드 전체 테스트 결과: 각 내용별 테스트 코드 및 해당 로그 파일 결과보고서: 구현 방법 및 실행 결과를 요약한 보고서 본 과제의 평가항목 및 배점은 다음과 같다. 각 세부내용의 구현 정확성 및 완결성 (80점) 코드의 Readability 및 쳬계성 (10점) 결과 보고서의 구체성 및 완결성 (10점) 9