SlideShare uma empresa Scribd logo
1 de 18
Baixar para ler offline
project #6

         오탈자 검사
 (Heap, Hash, Deap)



               자료구조 01
                  조 : C3
              조장 : 김시백
              조원 : 이용재
                  이상현
                  박구남
                  송하윤
순 서




1. 프로젝트 설명
 1) heap
 2) hash
 3) Deap
2. 프로젝트 전체일정
3. 업무분담
4. 소스
1. 프로젝트 설명
     이란?
heap 이란?
 최대 heap 이란 두 가지 조건을 만족하는 이진트리이다.
 1. complete binary tree
 1. parents node >= child node (최소 heap 은 parents node <= child node)
 최대 heap 이면 전체 데이터 중 루트 노드가 가장 큰 데이터가 된다.
 (예)




            사용하는가?
heap 구조는 언제 사용하는가?
 수시로 데이터가 삽입되는 구조에서 삽입된 데이터 중 가장 큰 데이터(혹은 작은 데이터)를 가져오고
 자 하는 경우
 예를 들어, 100 만건의 데이터가 있는 경우 이 중 가장 큰 데이터를 가져오기 위해서는 평균 50 만
 번의 비교가 일어날 것이다.
 heap 구조로 이를 처리한다면 100 만건의 데이터가 있을 때 최악의 경우도 약 20 번, 평균 10 번
 정도의 비교로 일을 끝낼 수 있다. (수시로 데이터가 삽입이 되므로 미리 소트해서 사용할 수는 없
 다)
 이런 삽입,삭제가 무수히 발생한다면 실행속도는 비교도 할 수 만큼의 차이를 보일 것이다. 이것이
 heap 의 위력이다.
heap 의 구현
 heap 구조는 complete binary tree 이므로 , 배열로 표현하는게 유리하다.
 •   i 번째 노드의 아버지노드 : i/2
 •   i 번째 노드의 왼쪽 아들: 2*i
 •   i 번째 노드의 오른쪽 아들: 2*i + 1


 (1) heap insert
 추가 데이터와 추가 노드의 조상노드(아버지,할아버지,증조 할아버지....)와 차례로 비교하면서 조상노
 드가 작으면 내리고 아니면 내린 노드의 위치에 데이터를 위치시키는 방법.
 예를 들면,




                     초기 heap 의 상태가 데이터 수 n 은 8 이고 왼쪽과 같은 경우 , 이
                     heap 에 데이터 item 7 을 추가하는 경우를 생각해보자.
                     먼저 데이터 수 n 은 8 에서 하나 증가해 9 가되고, 이 값을 임시변수
                     i 가 갖는다.




                         i        item      heap[i/2]
                         9          7          2
                             item >heap[i/2] 이므로
                                 •       heap[i/2] 는 i 위치로
                                     •    i 는 parents 노드로




                         i        item      heap[i/2]
                         4          7          6
                             item >heap[i/2] 이므로
                                 •       heap[i/2] 는 i 위치로
                                     •    i 는 parents 노드로




                         i     item      heap[i/2]
                         2       7          9
                         item <= heap[i/2] 이므로
                             •       item 을 i 번째 위치 끝.....
(2) heap delete




  루트노드(그림에서는 20)를 자른 후 다음을 위하여 재차 heap 을 만들어야 한다.
  complete binary tree 가 되어야 하므로 마지막 노드(그림에서 3)를 자른 후 , 세 값(4,18,15)을 비
  교후 가장 큰 데이터가 올라오는 동작이 반복되다 자른 데이터가 가장 크거나 같으면 위치시키는
  과정이다.
- heap delete 전체과정
maxheap의
maxheap의 정의
 max heap은 완전 이진 트리이며 heap의 한 노드는 그 노드의 모든 자손 노드들보다 큰 키 값을 가진다.
 max heap의 루트에는 항상 가장 큰 키 값을 가지는 노드가 위치하므로 우선순위 큐(priority queue)
 를 구성하는데 적합한 자료 구조이다.
 < max heap의 예>




maxheap에
maxheap에 임의의 키 값을 가지는 노드를 삽입
  max heap은 완전 이진 트리이므로 새로운 노드는 완전 이진 트리의 마지막 노드 다음 위치에 삽입
  된다.
  삽입된 노드와 그 부모 노드의 키 값을 비교한다. 삽입된 노드의 키 값이 부모 노드의 키 값보다 크
  면 두 노드의 위치를 바꾼다.
  삽입된 노드의 키 값이 자신의 부모 노드 키 값보다 작아질 때까지 2단계를 반복한다.

maxheap에서
maxheap에서 가장 큰 키 값을 가지는 노드를 삭제
  max heap의 루트에는 가장 큰 키 값을 가지는 노드가 들어있으므로 루트 노드를 삭제한다.
  빈 루트 노드 자리에는 완전 이진 트리의 마지막 노드를 삽입한다.
  삽입된 노드와 그 자식 노드의 키 값을 비교한다. 삽입된 노드의 키 값이 자식 노드의 키 값보다 작
  으면 두 노드의 위치를 바꾼다.
  삽입된 노드의 키 값이 자신의 자식 노드 키 값보다 커질 때까지 3단계를 반복한다.


minheap의
minheap의 정의
 min heap은 완전 이진 트리이며 heap의 한 노드는 그 노드의 모든 후손 노드들보다 작은 키 값을 가진다.




minheap에
minheap에 임의의 키 값을 가지는 노드를 삽입
  min heap은 완전 이진 트리이므로 새로운 노드는 완전 이진 트리의 마지막 노드 다음 위치에 삽입
  된다.
  삽입된 노드와 그 부모 노드의 키 값을 비교한다. 삽입된 노드의 키 값이 부모 노드의 키 값보다 작
  으면 두 노드의 위치를 바꾼다.
  삽입된 노드의 키 값이 자신의 부모 노드 키 값보다 작으면 두 노드의 위치를 바꾼다.
  삽입된 노드의 키 값이 자신의 부모 노드 키 값보다 커질 때까지 2단계를 반복한다.

minheap에서
minheap에서 가장 작은 키 값을 가지는 노드를 삭제
  min heap의 루트에는 가장 작은 키 값을 가지는 노드가 들어있으므로 루트 노드를 삭제한다.
  빈 루트 노드 자리에는 완전 이진 트리의 마지막 노드를 삽입한다.
  삽입된 노드의 그 자식 노드의 키 값을 비교한다. 삽입된 노드의 키 값이 자식 노드의 키 값보다 크
  면 두 노드의 위치를 바꾼다.
  삽입된 노드의 키 값이 자신의 자식 노드 키 값보다 작아질 때까지 3단계를 반복한다.
min-maxheap의
min-maxheap의 정의
 min-max heap은 완전 이진 트리이며 min 레벨과 max 레벨이 차례로 반복된다.
 루트는 min 레벨로 시작한다.
 min 레벨의 노드는 그 노드의 모든 후손들보다 작은 키 값을 가진다.
 max 레벨의 노드는 그 노드의 모든 후손들보다 큰 키 값을 가진다.
 min heap이나 max heap은 가장 작은 키 값을 가지는 노드는 가장 큰 키 값을 가지는 노드만을 찾
 기에 적합하도록 되어있지만 min-max heap은 두가지 노드를 모두 찾기에 적합한 자료 구조이다.




min-maxheap에
min-maxheap에 임의의 키 값을 가지는 노드를 삽입
  min-max heap은 완전 이진 트리이므로 새로운 노드는 완전 이진 트리의 마지막 노드 다음 위치에
  삽입된다.
  삽입된 노드가 어느 레벨에 있는지 검사하고, 삽입된 노드와 그 부모 노드의 키 값을 비교한다.
  새로운 노드가 어느 레벨에 있는지 검사하고, 삽입된 노드의 키 값이 부모 노드의 키 값보다 작으면
  삽입된 노드의 키 값과 같은 min 레벨에 있는 조부모 노드의 키 값을 비교한다.
  삽입된 노드의 키 값이 조부모 노드의 키 값보다 작으면 두 노드를 바꿔준다.
  변경된 노드의 키 값이 조부모 노드의 키 값보다 클 때까지 4단계를 반복한다.
  새로운 노드가 min 레벨에 삽입되고, 삽입된 노드의 키 값이 부모 노드의 키 값보다 크면 두노드를
  바꿔준다.
  변경된 노드의 키 값과 같은 max 레벨에 있는 조부모 노드이 키 값을 비교한다.
  변경된 노드의 키 값이 조부모 노드의 키 값보다 크면 두 노드를 바꿔준다.
  변경된 노드의 키 값이 조부모 노드의 키 값보다 작을 때까지 7,8단계를 반복한다.
  새로운 노드가 max 레벨에 삽입되고 삽입된 노드의 키 값이 부모 노드의 키 값보다 크면 삽입된 노
  드의 키 값과 같은 max 레벨에 있는 조부모 노드의 키 값을 비교한다.
  삽입된 노드의 키 값이 조부모 노드의 키 값보다 크면 두 노드를 바꿔준다.
  변경된 노드의 키 값이 조부모 노드의 키 값보다 작을 때까지 11단계를 반복한다.
  새로운 노드가 max 레벨에 삽입되고, 삽입된 노드의 키 값이 부모 노드의 키 값보다 작으면 두 노드
  를 바꿔준다.
  변경된 노드의 키 값과 같은 min 레벨에 있는 조부모 노드의 키 값을 비교한다.
  변경된 노드의 키 값이 조부모 노드의 키 값보다 작으면 두 노드를 바꿔준다.
  변경된 노드의 키 값이 조부모 노드의 키 값보다 클 때까지 14,15단계를 반복한다.
min-maxheap에서
min-maxheap에서 최소 키 값을 가지는 노드를 삭제
  min-max heap의 루트에는 최소키 값을 가지는 노드가 있으므로 루트 노드를 삭제한다.
 빈 루트 노드 자리에는 완전 이진 트리의 마지막 노드를 삽입한다.
 삽입된 노드와 자식 노드및 손자 노드의 키 값을 비교한다.
 자식 노드는 max 레벨에 있으므로 삽입된 노드의 키 값이 자식 노드의 키 값보다 큰 경우는 삽입될
 노드가 그 노드를 포함한 모든 후손들보다 큰 키 값을 가지게 된다. 따라서 삽입된 노드와 자식 노드
 를 바꿔준다.
 손자 노드는 같은 min 레벨에 있으므로 삽입된 노드의 키 값이 손자 노드의 키 값보다 큰 경우는 두
 노드를 바꿔준다.
 더이상 바꿀 노드가 없을때까지 3-5단계를 반복한다.



min-maxheap에서
min-maxheap에서 최대 키 값을 가지는 노드를 삭제
  min-max heap의 루트의 자식 노드를 중에 하나는 최대 키 값을 가지는 노드이다 따라서 두 노드중
 에 큰 키 값을 가지는 노드를 삭제한다.
 빈 자리에는 완전 이진 트리의 마지막 노드를 삽입한다.
 삽입된 노드와 자식 노드및 손자 노드의 키 값을 비교한다.
 자식 노드는 min 레벨에 있으므로 삽입된 노드의 키 값이 자식 노드의 키 값보다 작은 경우는 삽입
 된 노드가 그 노드를 포함한 모든 후손들보다 작은 키 값을 가지게 된다. 따라서 삽입된 노드와 자식
 노드를 바꿔준다.
 손자 노드는 같은 max 레벨에 있으므로 삽입된 노드의 키 값이 손자 노드의 키 값보다 작은 경우는
 두 노드를 바꿔준다.
 더이상 바꿀 노드가 없을때까지 3-5단계를 반복한다.
hash
해시(Hash)는 자료를 입력할 때부터 검색하기 쉬운 위치에 삽입하는 방법이다. 따라서 해시는 검색 방법
이라기보다는 빠른 검색을 위해 자료를 관리하는 기법이라고 볼 수 있다. 실생활에서도 해시 기법이 흔히
사용되는데 수첩에 주소록을 작성할 때 가나다순으로 페이지를 미리 분류하고 이름의 첫 글자를 기준으로
주소를 적는 방법이 바로 해싱이다.




수첩에 아무렇게나 주소를 적어 놓으면 새 주소를 추가하기는 간편하지만 다음에 찾기가 무척 어려워질
것이다. 하지만 성별로 분류해 놓으면 처음에 제 위치를 찾아 적기는 좀 귀찮지만 다음에 찾아 보기는 아
주 쉬워진다. 김가, 강가는   칸에서 찾고 황가, 한가는        칸에서 찾으면 쉽게 찾을 수 있다. 이런 검색 방
법이 바로 해싱이다.

자료가 저장되는 전체 저장소를 해시 테이블(Hash Table)이라고 한다. 해시 테이블은 여러 개의 버킷
(Bucket)으로 나누어지는데 주소록 예에서   ,   ,   ,   각 페이지가 버킷이다. 데이터를 삽입할 때 데이
터의 값으로부터 적절한 버킷을 선택해서 삽입해야 한다. 버킷은 또한 여러 개의 슬롯(Slot)으로 구성되는
데 슬롯은 버킷에 데이터가 저장되는 단위이다. 주소록의 각 페이지별로 한 명만 적을 수 있는 것이 아니
라 여러 명을 적을 수 있어야 하는데 이때 한 명의 주소를 적는 칸이 슬롯이다.




해싱의 가장 기초적인 연산은 자료가 새로 입력될 때 이 자료를 어떤 버킷에 넣을지를 결정하는 것인데
이 연산을 하는 함수를 해시 함수라고 한다. 해시 함수는 입력된 키값으로 버킷의 번호(해시값)를 찾아내
는 함수인데 새로 자료를 삽입할 때 해시 함수가 리턴하는 버킷 번호에 자료를 삽입한다. 다음에 특정 자
료를 검색할 때는 다시 해시 함수로 버킷 번호를 찾아 여기에 원하는 자료가 있는지를 보면 된다.

주소록 예에서 해시 함수는 이름의 첫글자 자음으로부터 버킷 번호를 찾는다. 김 아무개는            칸에, 장 아
무개는    칸을 찾아 선택된 버킷에 자료를 삽입하는 식이다. 이렇게 관리되는 주소록에서 "장군"이라는 사
람의 주소를 알고 싶다면 "장군"을 다시 해시 함수로 넣어         버킷을 찾고 이 페이지만 검색하면 쉽게 찾을
수 있다. 다음은 해시의 기본 동작 원리를 보여주는 아주 간단한 예제이다. 해시에 들어가는 수가 양의 정
수 뿐이라고 가정하고 0은 버킷이 비어 있다는 특이값으로 사용한다.
예제 : Hashing

#include <Turboc.h>

#define BK 10

#define SL 1

int hashtable[BK][SL];

int hash(int key) {

return key % 10;

}

void AddKey(int key) {

int bucket;

bucket=hash(key);

if (hashtable[bucket][0] == 0) {

hashtable[bucket][0]=key;

}

}

BOOL FindKey(int key) {

int bucket;

bucket=hash(key);

return (hashtable[bucket][0]==key);

}

void main() {

int i,key;

memset(hashtable,0,sizeof(hashtable));

for (i=0;i<5;i++) {

printf("%d번째 값을 입력하세요 : ",i+1);scanf("%d",&key);

AddKey(key);

}

printf("검색할 키를 입력하세요 : ");scanf("%d",&key);

if (FindKey(key)) {

puts("검색되었습니다.");

} else {

puts("입력하신 값은 없습니다..");

}

}
해시 함수 hash는 키의 마지막 자리 수 하나만으로 해시값을 계산하는데 이는 % 연산자로 쉽게 구할 수
있다. 15는 5를, 347은 7을, 83은 3을 선택할 것이다. 10으로 나눈 나머지를 해시값으로 선택하므로 버킷
은 10개를 준비하면 된다. 그래서 해시 테이블의 버킷 수는 10으로 정의했으면 충돌 현상을 쉽게 관찰하
기 위해 슬롯은 일부러 1로 정의해 두었다.

AddKey 함수는 입력된 키로부터 hash 함수를 호출하여 해시값을 찾고 이 버킷이 비어 있을 때 해시 테
이블에 데이터를 추가한다. 만약 이미 버킷이 점령되어 있다면 값을 추가할 수 없다. FindKey 함수는 키
가 해시 테이블에 있는지만 조사하는데 해시값을 먼저 찾고 버킷에 들어있는 값과 키값을 비교한 결과를
리턴한다. 존재 여부만을 조사하도록 했는데 실제 예에서는 키가 들어있는 버킷과 슬롯 번호를 리턴하는
것이 더 실용적이다.

main 함수는 해시 테이블을 0으로 모두 초기화하여 비우는데 만약 이 테이블에 0도 입력될 수 있다면 -1
등의 다른 특이값으로 초기화해야 할 것이다. 그리고 다섯 개의 값을 입력받아 해시 테이블에 추가하고 검
색할 키를 입력받은 후 FindKey 함수로 이 값이 해시 테이블에 들어 있는지 조사한다. 예제를 실행해 보
자.

1번째 값을 입력하세요 : 7

2번째 값을 입력하세요 : 28

3번째 값을 입력하세요 : 942

4번째 값을 입력하세요 : 69

5번째 값을 입력하세요 : 33

검색할 키를 입력하세요 : 28

검색되었습니다.

다섯 개의 값을 입력했는데 각 입력에 의해 AddKey 함수는 뒷자리 번호에 해당하는 버킷에 값을 저장한
다. 입력이 완료된 후 해시 테이블은 다음과 같은 상태가 될 것이다.




이 상태에서 28이 있는지 검색하는 방법은 아주 간단하고 빠르다. 해시 함수로 28이 들어갈 버킷 번호를
찾고 이 버킷에 과연 28이 들어 있는지만 점검하면 된다. FindKey는 28이 들어갈 8번 버킷만 보면 이 값
의 존재 유무를 쉽게 알 수 있다. 해시 테이블이 아무리 크고 데이터가 많다 하더라도 검색 시간은 상수로
항상 일정하다. 검색 시간으로만 본다면 해시는 모든 검색 알고리즘 중에 가장 빠르다.
그러나 해싱도 여러 가지 문제점이 있는데 가장 큰 문제는 버킷끼리 충돌할 수 있다는 점이다. 새로 삽입
하고자 하는 키의 버킷이 이미 점령되어 있다면 이 키는 해시 테이블에 추가할 수 없다. 예를 들어 38이
8번 버킷에 이미 들어 있을 때 48이나 58이 입력되면 이 값을 저장할 버킷이 없는 것이다. 버킷이 이미
점령되어 값을 추가할 수 없는 상황을 충돌(Collision)이라고 한다. 이 충돌을 어떻게 해결할 것인가가 해
싱의 관건이며 물론 다수의 합리적인 해결 방법이 있다.
Deap의
Deap의 정의
deap은 min-max heap보다 간단하게 최대및 최소 키 값을 가지는 노드를 찾아낼 수 있도록 고안된 자
료 구조이다.
deap은 완전 이진 트리이며 루트 노드는 비어있다. 루트의 왼쪽 서브트리는 min heap이고 오른쪽 서브
트리는 max heap이다.
왼쪽 서브트리에 있는 임의의 노드는 오른쪽 서브트리의 같은 위치에 대응되는 노드를 가진다. 같은 위
치에 아직 노드가 채워지지 않은 경우는 그 부모 노드가 대응된다. 위의 그림에서 왼쪽 서브트리의 8노
드에는 오른쪽 서브트리의 40노드가 대응되고, 왼쪽 서브트리의 30노드에 대해서는 오른쪽 서브트리에
대응하는 노드가 없으므로 그 부모 노드인 40노드가 대응된다.




deap에
deap에 임의의 키 값을 가지는 노드를 삽입
deap은 완전 이진 트리이므로 새로운 노드는 완전 이진 트리의 마지막 노드 다음 위치에 삽입된다.
삽입된 노드의 키 값과 반대편 서브트리의 대응하는 노드의 키 값을 비교한다.
왼쪽 서브트리 (min heap)에서의 노드의 키 값이 대응하는 오른쪽 서브트리(max heap)에서의 노드의
키 값보다 크면 두 노드를 바꿔준다.
새로 노드가 삽입된 서브트리에서는 min heap이나 max heap에 새로운 노드가 삽입된 것과 같으므로
min heap의 노드 삽입 방법이나 max heap의 노드 삽입 방법에 따라 처리해준다.
그림을 마우스로 클릭하세요

deap에서
deap에서 최소 키 값을 가지는 노드를 삭제
deap루트의 왼쪽 서브트리인 min heap에서 루트 노드를 삭제한다.
deap의 마지막 노드를 빈 자리에 삽입한다.
min heap에서 최소 키 값 노드 삭제 방법에 따라 삽입된 노드의 키 값과 그 자식 노드의 키 값을 비교
하여 삽입된 노드이 키 값이 큰 경우는 두 노드를 차례로 바꿔준다.
min heap이 정의되면 삽입된 노드의 최종 위치에 대응하는 max heap노드를 찾아서 두 노드의 키 값
을 비교한다.
min heap노드의 키 값이 max heap노드의 키 값보다 크면 두 노드를 바꿔준다.

deap에서
deap에서 최대 키 값을 가지는 노드를 삭제
deap루트의 오른쪽 서브트리인 max heap에서 루트 노드를 삭제한다.
deap의 마지막 노드를 빈 자리에 삽입한다.
min heap에서 최대 키 값 노드 삭제 방법에 따라 삽입된 노드의 키 값과 그 자식 노드의 키 값을 비교
하여 삽입된 노드이 키 값이 작은 경우는 두 노드를 차례로 바꿔준다.
max heap이 정이되면 삽입된 노드의 최종 위치에 대응하는 min heap노드를 찾아서 두노드의 키 값을
비교한다.
max heap노드의 키 값이 min heap노드의 키 값보다 작으면 두 노드를 바꿔준다.
2. 프로젝트 전체일정
   기 간            6 / 12                6 / 14
         -   조원별 업무 분담 및 계획 작성
         -   프로젝트 문제파악         - 알고리즘에 대해 토의하고 이해
   내 용   -   프로젝트에 필요한 학습내용 토의
                                - 문제점 토의
         -   프로젝트 진행방향 토의


  기 간             6 / 19                6 / 21

                               - 프로젝트 검토

  내 용     - 소스 구현 및 보고서 작성     - 최종보고서 작성
                               - 발표준비



3. 업무분담

  이 름                      업   무

  김시백    보고서 작성 및 회의 진행, 프로젝트에 필요한 학습내용 숙지




  송하윤    알고리즘 설계와 소스에 대한 문제점 검토와 보완




  이용재    소스구현 및 코딩 문제의 해결을 위한 방안 제시




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




  박구남    알고리즘 설계 및 프로젝트 수행 시 필요한 자료 수집
4. 소스
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>


struct Node {


            char name;
            Node *link[26];
            };




Node AddTree (Node *A, Node *B) {



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


        if (A->link[i] == 0) {
                           A -> link[i] = B;
                           printf("%c의 LINK%d에 %c를 삽입 n",A -> name,i,B -> name);
                           break;
                         } else {}



        }



    return *A;


    } // 노드 A 에 노드 B을 링크합니다.



Node AddNode (char A) {



    Node *B = (Node *)malloc(sizeof(Node));


    B->name = A;
    for (int i = 0; i < 26 ; i++) {
                           B->link[i] = 0;
        }


    return *B;
} // 노드 생성 함수




int search (Node *A, char B) {


    for (int i=0;i<26;i++) {
         if (A -> link[i] != 0) {
         if (A->link[i]->name == B) {return i;}
         }
         }
         return -1;



} // 위치 찾기


void PL(Node *A, char arr[], int x) {


     x++;
     arr[x]=A->name;
     if (A->link[0] == 0) {
                      for (int i = 0 ; i <= x ; i++) {
                          printf("%c",arr[i]);
                          }
                          printf("n");
                          return;
                      }
     PL(A,arr,x);
     return;


     }




int main () {



   FILE *file;
   char a, arr[20];
   int i, j, x=0;
   Node *ans = (Node *)malloc(sizeof(Node));
   Node *MyspotEEE;


   file=fopen("D://wordlist.txt","r");


         if(file==NULL)
{
                 return 1;
     }
i = 0;



ans[0] = AddNode('/');
MyspotEEE = &ans[0];


for (;;) {                // MyspotEEE 현제 위치, j search 값, x = 생성 노드 위치
         a=fgetc(file);


         if (a == 'n') { // n 이면 단어 하나가 끝났으므로 루트로 돌아간다.
                 MyspotEEE = &ans[0];


                 continue;


                 }



         if (a < 91) { // 대문자는 소문자로 바꿔준다[대소문자 구분 안하므로.]
                 a += 32;
                 }


         if(a==EOF) {
                 break;
                      }



         j = search(MyspotEEE,a); // 다음 노드에 이미 같은 이름의 노드가 생성되었는지 조사한다.


         if (j == -1) { // 같은 이름의 노드가 존재하면 그대로 내려가고, 아니면 새로 생성해서 내려간다.
                 x++;
                 ans[x] = AddNode(a);
                 *MyspotEEE = AddTree(MyspotEEE,&ans[x]);
                 MyspotEEE = &ans[x];
                 } else {
                          MyspotEEE = MyspotEEE->link[j];
                          }
    }


 fclose(file);


 file=fopen("D://wordlist.txt","r");


if(file==NULL)
     {
                 return 1;
}



        MyspotEEE = &ans[0];


        for (;;) {


    a=fgetc(file);


            if ( (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z') ) { // n 이면 단어 하나가 끝났으므로 루트로
돌아간다.
                 MyspotEEE = &ans[0];
                 x = 0;
                 continue;


                 }



            if (a < 91) { // 대문자는 소문자로 바꿔준다[대소문자 구분 안하므로.]
                 a += 32;
                 }


            if(a==EOF) {
                 break;
                      }


    j = search(MyspotEEE,a);




    if (j == -1) { // 존재하지 않는다면
             printf("사전에 없는 단어입니다.n유사 단어는n");


             PL(MyspotEEE,arr,x);
             printf("가 존재합니다. 다음 단어로 넘어갑니다.n");


               a=fgetc(file);


               if ( (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z') ) { // 다음 단어로 넘어감
                      printf(" ");
                     } else {
                             printf("n");
                             break;
                             }


                 if(a==EOF) {
                 break;
                      }
for (;;) { // 다음단어로 넘어감


                  a=fgetc(file);


                  i=0;



                  if ( (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z') ) {
                          printf(" ");
                      } else {
                               printf("n");
                               break;
                               }
                  if(a==EOF) {
                  break;
                          }
                  }
        } else { // 존재하지 않는다면의 else
                      MyspotEEE = MyspotEEE->link[j];
                      x++;
                      }
                  if(a==EOF) {
                  break;
                          }


       }


    getch();
return 0;
}

Mais conteúdo relacionado

Mais procurados

Jupyter notebook 이해하기
Jupyter notebook 이해하기 Jupyter notebook 이해하기
Jupyter notebook 이해하기 Yong Joon Moon
 
Javascript prototype & inheritance
Javascript prototype & inheritanceJavascript prototype & inheritance
Javascript prototype & inheritance지수 윤
 
Data Structures
Data StructuresData Structures
Data Structuresskku_npc
 
[GPG 스터디] 1.4 게임프로그래밍에서의 STL 활용
[GPG 스터디] 1.4 게임프로그래밍에서의 STL 활용 [GPG 스터디] 1.4 게임프로그래밍에서의 STL 활용
[GPG 스터디] 1.4 게임프로그래밍에서의 STL 활용 Sehyeon Nam
 
엘라스틱서치 분석 이해하기 20160623
엘라스틱서치 분석 이해하기 20160623엘라스틱서치 분석 이해하기 20160623
엘라스틱서치 분석 이해하기 20160623Yong Joon Moon
 
파이썬+Json+이해하기 20160301
파이썬+Json+이해하기 20160301파이썬+Json+이해하기 20160301
파이썬+Json+이해하기 20160301Yong Joon Moon
 
[Commit Again] 1주차 STL study
[Commit Again] 1주차 STL study[Commit Again] 1주차 STL study
[Commit Again] 1주차 STL study경 송
 
파이썬 파일처리 이해하기
파이썬 파일처리 이해하기파이썬 파일처리 이해하기
파이썬 파일처리 이해하기Yong Joon Moon
 
[Swift] Data Structure - Binary Search Tree
[Swift] Data Structure - Binary Search Tree[Swift] Data Structure - Binary Search Tree
[Swift] Data Structure - Binary Search TreeBill Kim
 
파이썬정리 20160130
파이썬정리 20160130파이썬정리 20160130
파이썬정리 20160130Yong Joon Moon
 
파이썬+함수 데코레이터+이해하기 20160229
파이썬+함수 데코레이터+이해하기 20160229파이썬+함수 데코레이터+이해하기 20160229
파이썬+함수 데코레이터+이해하기 20160229Yong Joon Moon
 
[Swift] Data Structure - Heap
[Swift] Data Structure - Heap[Swift] Data Structure - Heap
[Swift] Data Structure - HeapBill Kim
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 Yong Joon Moon
 
엘라스틱서치 이해하기 20160612
엘라스틱서치 이해하기 20160612엘라스틱서치 이해하기 20160612
엘라스틱서치 이해하기 20160612Yong Joon Moon
 
Haskell study 12
Haskell study 12Haskell study 12
Haskell study 12Nam Hyeonuk
 

Mais procurados (20)

Jupyter notebook 이해하기
Jupyter notebook 이해하기 Jupyter notebook 이해하기
Jupyter notebook 이해하기
 
Javascript prototype & inheritance
Javascript prototype & inheritanceJavascript prototype & inheritance
Javascript prototype & inheritance
 
Data Structures
Data StructuresData Structures
Data Structures
 
[GPG 스터디] 1.4 게임프로그래밍에서의 STL 활용
[GPG 스터디] 1.4 게임프로그래밍에서의 STL 활용 [GPG 스터디] 1.4 게임프로그래밍에서의 STL 활용
[GPG 스터디] 1.4 게임프로그래밍에서의 STL 활용
 
자료구조06
자료구조06자료구조06
자료구조06
 
자료구조06
자료구조06자료구조06
자료구조06
 
엘라스틱서치 분석 이해하기 20160623
엘라스틱서치 분석 이해하기 20160623엘라스틱서치 분석 이해하기 20160623
엘라스틱서치 분석 이해하기 20160623
 
파이썬+Json+이해하기 20160301
파이썬+Json+이해하기 20160301파이썬+Json+이해하기 20160301
파이썬+Json+이해하기 20160301
 
[Commit Again] 1주차 STL study
[Commit Again] 1주차 STL study[Commit Again] 1주차 STL study
[Commit Again] 1주차 STL study
 
파이썬 파일처리 이해하기
파이썬 파일처리 이해하기파이썬 파일처리 이해하기
파이썬 파일처리 이해하기
 
[Swift] Data Structure - Binary Search Tree
[Swift] Data Structure - Binary Search Tree[Swift] Data Structure - Binary Search Tree
[Swift] Data Structure - Binary Search Tree
 
파이썬정리 20160130
파이썬정리 20160130파이썬정리 20160130
파이썬정리 20160130
 
파이썬+함수 데코레이터+이해하기 20160229
파이썬+함수 데코레이터+이해하기 20160229파이썬+함수 데코레이터+이해하기 20160229
파이썬+함수 데코레이터+이해하기 20160229
 
[Swift] Data Structure - Heap
[Swift] Data Structure - Heap[Swift] Data Structure - Heap
[Swift] Data Structure - Heap
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기
 
엘라스틱서치 이해하기 20160612
엘라스틱서치 이해하기 20160612엘라스틱서치 이해하기 20160612
엘라스틱서치 이해하기 20160612
 
Haskell study 12
Haskell study 12Haskell study 12
Haskell study 12
 
3. linked list
3. linked list3. linked list
3. linked list
 
Haskell study 2
Haskell study 2Haskell study 2
Haskell study 2
 
C++ stl
C++ stlC++ stl
C++ stl
 

Semelhante a 프로젝트#6 (오탈자 검사)보고서

2012 Ds A1 06
2012 Ds A1 062012 Ds A1 06
2012 Ds A1 06seonhyung
 
2012 Ds A1 06
2012 Ds A1 062012 Ds A1 06
2012 Ds A1 06seonhyung
 
Project#2말의여행 Hwp
Project#2말의여행 HwpProject#2말의여행 Hwp
Project#2말의여행 HwpKimjeongmoo
 
Python+numpy pandas 1편
Python+numpy pandas 1편Python+numpy pandas 1편
Python+numpy pandas 1편Yong Joon Moon
 
자료구조 트리 보고서
자료구조 트리 보고서자료구조 트리 보고서
자료구조 트리 보고서mil23
 
Python_numpy_pandas_matplotlib 이해하기_20160815
Python_numpy_pandas_matplotlib 이해하기_20160815Python_numpy_pandas_matplotlib 이해하기_20160815
Python_numpy_pandas_matplotlib 이해하기_20160815Yong Joon Moon
 
[알고리즘 스터디 2주차]병합정렬/퀵정렬/힙정렬
[알고리즘 스터디 2주차]병합정렬/퀵정렬/힙정렬[알고리즘 스터디 2주차]병합정렬/퀵정렬/힙정렬
[알고리즘 스터디 2주차]병합정렬/퀵정렬/힙정렬Codingclub
 
TAOCP1 - 2.2.2 - 순차할당
TAOCP1 - 2.2.2 - 순차할당TAOCP1 - 2.2.2 - 순차할당
TAOCP1 - 2.2.2 - 순차할당JangHyuk You
 
Stl vector, list, map
Stl vector, list, mapStl vector, list, map
Stl vector, list, mapNam Hyeonuk
 

Semelhante a 프로젝트#6 (오탈자 검사)보고서 (10)

2012 Ds A1 06
2012 Ds A1 062012 Ds A1 06
2012 Ds A1 06
 
2012 Ds A1 06
2012 Ds A1 062012 Ds A1 06
2012 Ds A1 06
 
Project#2말의여행 Hwp
Project#2말의여행 HwpProject#2말의여행 Hwp
Project#2말의여행 Hwp
 
Python+numpy pandas 1편
Python+numpy pandas 1편Python+numpy pandas 1편
Python+numpy pandas 1편
 
자료구조 트리 보고서
자료구조 트리 보고서자료구조 트리 보고서
자료구조 트리 보고서
 
Python_numpy_pandas_matplotlib 이해하기_20160815
Python_numpy_pandas_matplotlib 이해하기_20160815Python_numpy_pandas_matplotlib 이해하기_20160815
Python_numpy_pandas_matplotlib 이해하기_20160815
 
[알고리즘 스터디 2주차]병합정렬/퀵정렬/힙정렬
[알고리즘 스터디 2주차]병합정렬/퀵정렬/힙정렬[알고리즘 스터디 2주차]병합정렬/퀵정렬/힙정렬
[알고리즘 스터디 2주차]병합정렬/퀵정렬/힙정렬
 
TAOCP1 - 2.2.2 - 순차할당
TAOCP1 - 2.2.2 - 순차할당TAOCP1 - 2.2.2 - 순차할당
TAOCP1 - 2.2.2 - 순차할당
 
Stl vector, list, map
Stl vector, list, mapStl vector, list, map
Stl vector, list, map
 
자료구조02
자료구조02자료구조02
자료구조02
 

Mais de mil23

이산치 과제7
이산치 과제7이산치 과제7
이산치 과제7mil23
 
이산치수학 데이터베이스
이산치수학 데이터베이스이산치수학 데이터베이스
이산치수학 데이터베이스mil23
 
이산치보고서
이산치보고서이산치보고서
이산치보고서mil23
 
길찾기
길찾기길찾기
길찾기mil23
 
과제 1,2,3
과제 1,2,3과제 1,2,3
과제 1,2,3mil23
 
파스칼삼각형
파스칼삼각형파스칼삼각형
파스칼삼각형mil23
 
자료구조 그래프 보고서
자료구조 그래프 보고서자료구조 그래프 보고서
자료구조 그래프 보고서mil23
 
보고서1
보고서1보고서1
보고서1mil23
 
말의여행
말의여행말의여행
말의여행mil23
 

Mais de mil23 (9)

이산치 과제7
이산치 과제7이산치 과제7
이산치 과제7
 
이산치수학 데이터베이스
이산치수학 데이터베이스이산치수학 데이터베이스
이산치수학 데이터베이스
 
이산치보고서
이산치보고서이산치보고서
이산치보고서
 
길찾기
길찾기길찾기
길찾기
 
과제 1,2,3
과제 1,2,3과제 1,2,3
과제 1,2,3
 
파스칼삼각형
파스칼삼각형파스칼삼각형
파스칼삼각형
 
자료구조 그래프 보고서
자료구조 그래프 보고서자료구조 그래프 보고서
자료구조 그래프 보고서
 
보고서1
보고서1보고서1
보고서1
 
말의여행
말의여행말의여행
말의여행
 

프로젝트#6 (오탈자 검사)보고서

  • 1. project #6 오탈자 검사 (Heap, Hash, Deap) 자료구조 01 조 : C3 조장 : 김시백 조원 : 이용재 이상현 박구남 송하윤
  • 2. 순 서 1. 프로젝트 설명 1) heap 2) hash 3) Deap 2. 프로젝트 전체일정 3. 업무분담 4. 소스
  • 3. 1. 프로젝트 설명 이란? heap 이란? 최대 heap 이란 두 가지 조건을 만족하는 이진트리이다. 1. complete binary tree 1. parents node >= child node (최소 heap 은 parents node <= child node) 최대 heap 이면 전체 데이터 중 루트 노드가 가장 큰 데이터가 된다. (예) 사용하는가? heap 구조는 언제 사용하는가? 수시로 데이터가 삽입되는 구조에서 삽입된 데이터 중 가장 큰 데이터(혹은 작은 데이터)를 가져오고 자 하는 경우 예를 들어, 100 만건의 데이터가 있는 경우 이 중 가장 큰 데이터를 가져오기 위해서는 평균 50 만 번의 비교가 일어날 것이다. heap 구조로 이를 처리한다면 100 만건의 데이터가 있을 때 최악의 경우도 약 20 번, 평균 10 번 정도의 비교로 일을 끝낼 수 있다. (수시로 데이터가 삽입이 되므로 미리 소트해서 사용할 수는 없 다) 이런 삽입,삭제가 무수히 발생한다면 실행속도는 비교도 할 수 만큼의 차이를 보일 것이다. 이것이 heap 의 위력이다.
  • 4. heap 의 구현 heap 구조는 complete binary tree 이므로 , 배열로 표현하는게 유리하다. • i 번째 노드의 아버지노드 : i/2 • i 번째 노드의 왼쪽 아들: 2*i • i 번째 노드의 오른쪽 아들: 2*i + 1 (1) heap insert 추가 데이터와 추가 노드의 조상노드(아버지,할아버지,증조 할아버지....)와 차례로 비교하면서 조상노 드가 작으면 내리고 아니면 내린 노드의 위치에 데이터를 위치시키는 방법. 예를 들면, 초기 heap 의 상태가 데이터 수 n 은 8 이고 왼쪽과 같은 경우 , 이 heap 에 데이터 item 7 을 추가하는 경우를 생각해보자. 먼저 데이터 수 n 은 8 에서 하나 증가해 9 가되고, 이 값을 임시변수 i 가 갖는다. i item heap[i/2] 9 7 2 item >heap[i/2] 이므로 • heap[i/2] 는 i 위치로 • i 는 parents 노드로 i item heap[i/2] 4 7 6 item >heap[i/2] 이므로 • heap[i/2] 는 i 위치로 • i 는 parents 노드로 i item heap[i/2] 2 7 9 item <= heap[i/2] 이므로 • item 을 i 번째 위치 끝.....
  • 5. (2) heap delete 루트노드(그림에서는 20)를 자른 후 다음을 위하여 재차 heap 을 만들어야 한다. complete binary tree 가 되어야 하므로 마지막 노드(그림에서 3)를 자른 후 , 세 값(4,18,15)을 비 교후 가장 큰 데이터가 올라오는 동작이 반복되다 자른 데이터가 가장 크거나 같으면 위치시키는 과정이다. - heap delete 전체과정
  • 6. maxheap의 maxheap의 정의 max heap은 완전 이진 트리이며 heap의 한 노드는 그 노드의 모든 자손 노드들보다 큰 키 값을 가진다. max heap의 루트에는 항상 가장 큰 키 값을 가지는 노드가 위치하므로 우선순위 큐(priority queue) 를 구성하는데 적합한 자료 구조이다. < max heap의 예> maxheap에 maxheap에 임의의 키 값을 가지는 노드를 삽입 max heap은 완전 이진 트리이므로 새로운 노드는 완전 이진 트리의 마지막 노드 다음 위치에 삽입 된다. 삽입된 노드와 그 부모 노드의 키 값을 비교한다. 삽입된 노드의 키 값이 부모 노드의 키 값보다 크 면 두 노드의 위치를 바꾼다. 삽입된 노드의 키 값이 자신의 부모 노드 키 값보다 작아질 때까지 2단계를 반복한다. maxheap에서 maxheap에서 가장 큰 키 값을 가지는 노드를 삭제 max heap의 루트에는 가장 큰 키 값을 가지는 노드가 들어있으므로 루트 노드를 삭제한다. 빈 루트 노드 자리에는 완전 이진 트리의 마지막 노드를 삽입한다. 삽입된 노드와 그 자식 노드의 키 값을 비교한다. 삽입된 노드의 키 값이 자식 노드의 키 값보다 작 으면 두 노드의 위치를 바꾼다. 삽입된 노드의 키 값이 자신의 자식 노드 키 값보다 커질 때까지 3단계를 반복한다. minheap의 minheap의 정의 min heap은 완전 이진 트리이며 heap의 한 노드는 그 노드의 모든 후손 노드들보다 작은 키 값을 가진다. minheap에 minheap에 임의의 키 값을 가지는 노드를 삽입 min heap은 완전 이진 트리이므로 새로운 노드는 완전 이진 트리의 마지막 노드 다음 위치에 삽입 된다. 삽입된 노드와 그 부모 노드의 키 값을 비교한다. 삽입된 노드의 키 값이 부모 노드의 키 값보다 작 으면 두 노드의 위치를 바꾼다. 삽입된 노드의 키 값이 자신의 부모 노드 키 값보다 작으면 두 노드의 위치를 바꾼다. 삽입된 노드의 키 값이 자신의 부모 노드 키 값보다 커질 때까지 2단계를 반복한다. minheap에서 minheap에서 가장 작은 키 값을 가지는 노드를 삭제 min heap의 루트에는 가장 작은 키 값을 가지는 노드가 들어있으므로 루트 노드를 삭제한다. 빈 루트 노드 자리에는 완전 이진 트리의 마지막 노드를 삽입한다. 삽입된 노드의 그 자식 노드의 키 값을 비교한다. 삽입된 노드의 키 값이 자식 노드의 키 값보다 크 면 두 노드의 위치를 바꾼다. 삽입된 노드의 키 값이 자신의 자식 노드 키 값보다 작아질 때까지 3단계를 반복한다.
  • 7. min-maxheap의 min-maxheap의 정의 min-max heap은 완전 이진 트리이며 min 레벨과 max 레벨이 차례로 반복된다. 루트는 min 레벨로 시작한다. min 레벨의 노드는 그 노드의 모든 후손들보다 작은 키 값을 가진다. max 레벨의 노드는 그 노드의 모든 후손들보다 큰 키 값을 가진다. min heap이나 max heap은 가장 작은 키 값을 가지는 노드는 가장 큰 키 값을 가지는 노드만을 찾 기에 적합하도록 되어있지만 min-max heap은 두가지 노드를 모두 찾기에 적합한 자료 구조이다. min-maxheap에 min-maxheap에 임의의 키 값을 가지는 노드를 삽입 min-max heap은 완전 이진 트리이므로 새로운 노드는 완전 이진 트리의 마지막 노드 다음 위치에 삽입된다. 삽입된 노드가 어느 레벨에 있는지 검사하고, 삽입된 노드와 그 부모 노드의 키 값을 비교한다. 새로운 노드가 어느 레벨에 있는지 검사하고, 삽입된 노드의 키 값이 부모 노드의 키 값보다 작으면 삽입된 노드의 키 값과 같은 min 레벨에 있는 조부모 노드의 키 값을 비교한다. 삽입된 노드의 키 값이 조부모 노드의 키 값보다 작으면 두 노드를 바꿔준다. 변경된 노드의 키 값이 조부모 노드의 키 값보다 클 때까지 4단계를 반복한다. 새로운 노드가 min 레벨에 삽입되고, 삽입된 노드의 키 값이 부모 노드의 키 값보다 크면 두노드를 바꿔준다. 변경된 노드의 키 값과 같은 max 레벨에 있는 조부모 노드이 키 값을 비교한다. 변경된 노드의 키 값이 조부모 노드의 키 값보다 크면 두 노드를 바꿔준다. 변경된 노드의 키 값이 조부모 노드의 키 값보다 작을 때까지 7,8단계를 반복한다. 새로운 노드가 max 레벨에 삽입되고 삽입된 노드의 키 값이 부모 노드의 키 값보다 크면 삽입된 노 드의 키 값과 같은 max 레벨에 있는 조부모 노드의 키 값을 비교한다. 삽입된 노드의 키 값이 조부모 노드의 키 값보다 크면 두 노드를 바꿔준다. 변경된 노드의 키 값이 조부모 노드의 키 값보다 작을 때까지 11단계를 반복한다. 새로운 노드가 max 레벨에 삽입되고, 삽입된 노드의 키 값이 부모 노드의 키 값보다 작으면 두 노드 를 바꿔준다. 변경된 노드의 키 값과 같은 min 레벨에 있는 조부모 노드의 키 값을 비교한다. 변경된 노드의 키 값이 조부모 노드의 키 값보다 작으면 두 노드를 바꿔준다. 변경된 노드의 키 값이 조부모 노드의 키 값보다 클 때까지 14,15단계를 반복한다.
  • 8. min-maxheap에서 min-maxheap에서 최소 키 값을 가지는 노드를 삭제 min-max heap의 루트에는 최소키 값을 가지는 노드가 있으므로 루트 노드를 삭제한다. 빈 루트 노드 자리에는 완전 이진 트리의 마지막 노드를 삽입한다. 삽입된 노드와 자식 노드및 손자 노드의 키 값을 비교한다. 자식 노드는 max 레벨에 있으므로 삽입된 노드의 키 값이 자식 노드의 키 값보다 큰 경우는 삽입될 노드가 그 노드를 포함한 모든 후손들보다 큰 키 값을 가지게 된다. 따라서 삽입된 노드와 자식 노드 를 바꿔준다. 손자 노드는 같은 min 레벨에 있으므로 삽입된 노드의 키 값이 손자 노드의 키 값보다 큰 경우는 두 노드를 바꿔준다. 더이상 바꿀 노드가 없을때까지 3-5단계를 반복한다. min-maxheap에서 min-maxheap에서 최대 키 값을 가지는 노드를 삭제 min-max heap의 루트의 자식 노드를 중에 하나는 최대 키 값을 가지는 노드이다 따라서 두 노드중 에 큰 키 값을 가지는 노드를 삭제한다. 빈 자리에는 완전 이진 트리의 마지막 노드를 삽입한다. 삽입된 노드와 자식 노드및 손자 노드의 키 값을 비교한다. 자식 노드는 min 레벨에 있으므로 삽입된 노드의 키 값이 자식 노드의 키 값보다 작은 경우는 삽입 된 노드가 그 노드를 포함한 모든 후손들보다 작은 키 값을 가지게 된다. 따라서 삽입된 노드와 자식 노드를 바꿔준다. 손자 노드는 같은 max 레벨에 있으므로 삽입된 노드의 키 값이 손자 노드의 키 값보다 작은 경우는 두 노드를 바꿔준다. 더이상 바꿀 노드가 없을때까지 3-5단계를 반복한다.
  • 9. hash 해시(Hash)는 자료를 입력할 때부터 검색하기 쉬운 위치에 삽입하는 방법이다. 따라서 해시는 검색 방법 이라기보다는 빠른 검색을 위해 자료를 관리하는 기법이라고 볼 수 있다. 실생활에서도 해시 기법이 흔히 사용되는데 수첩에 주소록을 작성할 때 가나다순으로 페이지를 미리 분류하고 이름의 첫 글자를 기준으로 주소를 적는 방법이 바로 해싱이다. 수첩에 아무렇게나 주소를 적어 놓으면 새 주소를 추가하기는 간편하지만 다음에 찾기가 무척 어려워질 것이다. 하지만 성별로 분류해 놓으면 처음에 제 위치를 찾아 적기는 좀 귀찮지만 다음에 찾아 보기는 아 주 쉬워진다. 김가, 강가는 칸에서 찾고 황가, 한가는 칸에서 찾으면 쉽게 찾을 수 있다. 이런 검색 방 법이 바로 해싱이다. 자료가 저장되는 전체 저장소를 해시 테이블(Hash Table)이라고 한다. 해시 테이블은 여러 개의 버킷 (Bucket)으로 나누어지는데 주소록 예에서 , , , 각 페이지가 버킷이다. 데이터를 삽입할 때 데이 터의 값으로부터 적절한 버킷을 선택해서 삽입해야 한다. 버킷은 또한 여러 개의 슬롯(Slot)으로 구성되는 데 슬롯은 버킷에 데이터가 저장되는 단위이다. 주소록의 각 페이지별로 한 명만 적을 수 있는 것이 아니 라 여러 명을 적을 수 있어야 하는데 이때 한 명의 주소를 적는 칸이 슬롯이다. 해싱의 가장 기초적인 연산은 자료가 새로 입력될 때 이 자료를 어떤 버킷에 넣을지를 결정하는 것인데 이 연산을 하는 함수를 해시 함수라고 한다. 해시 함수는 입력된 키값으로 버킷의 번호(해시값)를 찾아내 는 함수인데 새로 자료를 삽입할 때 해시 함수가 리턴하는 버킷 번호에 자료를 삽입한다. 다음에 특정 자 료를 검색할 때는 다시 해시 함수로 버킷 번호를 찾아 여기에 원하는 자료가 있는지를 보면 된다. 주소록 예에서 해시 함수는 이름의 첫글자 자음으로부터 버킷 번호를 찾는다. 김 아무개는 칸에, 장 아 무개는 칸을 찾아 선택된 버킷에 자료를 삽입하는 식이다. 이렇게 관리되는 주소록에서 "장군"이라는 사 람의 주소를 알고 싶다면 "장군"을 다시 해시 함수로 넣어 버킷을 찾고 이 페이지만 검색하면 쉽게 찾을 수 있다. 다음은 해시의 기본 동작 원리를 보여주는 아주 간단한 예제이다. 해시에 들어가는 수가 양의 정 수 뿐이라고 가정하고 0은 버킷이 비어 있다는 특이값으로 사용한다.
  • 10. 예제 : Hashing #include <Turboc.h> #define BK 10 #define SL 1 int hashtable[BK][SL]; int hash(int key) { return key % 10; } void AddKey(int key) { int bucket; bucket=hash(key); if (hashtable[bucket][0] == 0) { hashtable[bucket][0]=key; } } BOOL FindKey(int key) { int bucket; bucket=hash(key); return (hashtable[bucket][0]==key); } void main() { int i,key; memset(hashtable,0,sizeof(hashtable)); for (i=0;i<5;i++) { printf("%d번째 값을 입력하세요 : ",i+1);scanf("%d",&key); AddKey(key); } printf("검색할 키를 입력하세요 : ");scanf("%d",&key); if (FindKey(key)) { puts("검색되었습니다."); } else { puts("입력하신 값은 없습니다.."); } }
  • 11. 해시 함수 hash는 키의 마지막 자리 수 하나만으로 해시값을 계산하는데 이는 % 연산자로 쉽게 구할 수 있다. 15는 5를, 347은 7을, 83은 3을 선택할 것이다. 10으로 나눈 나머지를 해시값으로 선택하므로 버킷 은 10개를 준비하면 된다. 그래서 해시 테이블의 버킷 수는 10으로 정의했으면 충돌 현상을 쉽게 관찰하 기 위해 슬롯은 일부러 1로 정의해 두었다. AddKey 함수는 입력된 키로부터 hash 함수를 호출하여 해시값을 찾고 이 버킷이 비어 있을 때 해시 테 이블에 데이터를 추가한다. 만약 이미 버킷이 점령되어 있다면 값을 추가할 수 없다. FindKey 함수는 키 가 해시 테이블에 있는지만 조사하는데 해시값을 먼저 찾고 버킷에 들어있는 값과 키값을 비교한 결과를 리턴한다. 존재 여부만을 조사하도록 했는데 실제 예에서는 키가 들어있는 버킷과 슬롯 번호를 리턴하는 것이 더 실용적이다. main 함수는 해시 테이블을 0으로 모두 초기화하여 비우는데 만약 이 테이블에 0도 입력될 수 있다면 -1 등의 다른 특이값으로 초기화해야 할 것이다. 그리고 다섯 개의 값을 입력받아 해시 테이블에 추가하고 검 색할 키를 입력받은 후 FindKey 함수로 이 값이 해시 테이블에 들어 있는지 조사한다. 예제를 실행해 보 자. 1번째 값을 입력하세요 : 7 2번째 값을 입력하세요 : 28 3번째 값을 입력하세요 : 942 4번째 값을 입력하세요 : 69 5번째 값을 입력하세요 : 33 검색할 키를 입력하세요 : 28 검색되었습니다. 다섯 개의 값을 입력했는데 각 입력에 의해 AddKey 함수는 뒷자리 번호에 해당하는 버킷에 값을 저장한 다. 입력이 완료된 후 해시 테이블은 다음과 같은 상태가 될 것이다. 이 상태에서 28이 있는지 검색하는 방법은 아주 간단하고 빠르다. 해시 함수로 28이 들어갈 버킷 번호를 찾고 이 버킷에 과연 28이 들어 있는지만 점검하면 된다. FindKey는 28이 들어갈 8번 버킷만 보면 이 값 의 존재 유무를 쉽게 알 수 있다. 해시 테이블이 아무리 크고 데이터가 많다 하더라도 검색 시간은 상수로 항상 일정하다. 검색 시간으로만 본다면 해시는 모든 검색 알고리즘 중에 가장 빠르다. 그러나 해싱도 여러 가지 문제점이 있는데 가장 큰 문제는 버킷끼리 충돌할 수 있다는 점이다. 새로 삽입 하고자 하는 키의 버킷이 이미 점령되어 있다면 이 키는 해시 테이블에 추가할 수 없다. 예를 들어 38이 8번 버킷에 이미 들어 있을 때 48이나 58이 입력되면 이 값을 저장할 버킷이 없는 것이다. 버킷이 이미 점령되어 값을 추가할 수 없는 상황을 충돌(Collision)이라고 한다. 이 충돌을 어떻게 해결할 것인가가 해 싱의 관건이며 물론 다수의 합리적인 해결 방법이 있다.
  • 12. Deap의 Deap의 정의 deap은 min-max heap보다 간단하게 최대및 최소 키 값을 가지는 노드를 찾아낼 수 있도록 고안된 자 료 구조이다. deap은 완전 이진 트리이며 루트 노드는 비어있다. 루트의 왼쪽 서브트리는 min heap이고 오른쪽 서브 트리는 max heap이다. 왼쪽 서브트리에 있는 임의의 노드는 오른쪽 서브트리의 같은 위치에 대응되는 노드를 가진다. 같은 위 치에 아직 노드가 채워지지 않은 경우는 그 부모 노드가 대응된다. 위의 그림에서 왼쪽 서브트리의 8노 드에는 오른쪽 서브트리의 40노드가 대응되고, 왼쪽 서브트리의 30노드에 대해서는 오른쪽 서브트리에 대응하는 노드가 없으므로 그 부모 노드인 40노드가 대응된다. deap에 deap에 임의의 키 값을 가지는 노드를 삽입 deap은 완전 이진 트리이므로 새로운 노드는 완전 이진 트리의 마지막 노드 다음 위치에 삽입된다. 삽입된 노드의 키 값과 반대편 서브트리의 대응하는 노드의 키 값을 비교한다. 왼쪽 서브트리 (min heap)에서의 노드의 키 값이 대응하는 오른쪽 서브트리(max heap)에서의 노드의 키 값보다 크면 두 노드를 바꿔준다. 새로 노드가 삽입된 서브트리에서는 min heap이나 max heap에 새로운 노드가 삽입된 것과 같으므로 min heap의 노드 삽입 방법이나 max heap의 노드 삽입 방법에 따라 처리해준다. 그림을 마우스로 클릭하세요 deap에서 deap에서 최소 키 값을 가지는 노드를 삭제 deap루트의 왼쪽 서브트리인 min heap에서 루트 노드를 삭제한다. deap의 마지막 노드를 빈 자리에 삽입한다. min heap에서 최소 키 값 노드 삭제 방법에 따라 삽입된 노드의 키 값과 그 자식 노드의 키 값을 비교 하여 삽입된 노드이 키 값이 큰 경우는 두 노드를 차례로 바꿔준다. min heap이 정의되면 삽입된 노드의 최종 위치에 대응하는 max heap노드를 찾아서 두 노드의 키 값 을 비교한다. min heap노드의 키 값이 max heap노드의 키 값보다 크면 두 노드를 바꿔준다. deap에서 deap에서 최대 키 값을 가지는 노드를 삭제 deap루트의 오른쪽 서브트리인 max heap에서 루트 노드를 삭제한다. deap의 마지막 노드를 빈 자리에 삽입한다. min heap에서 최대 키 값 노드 삭제 방법에 따라 삽입된 노드의 키 값과 그 자식 노드의 키 값을 비교 하여 삽입된 노드이 키 값이 작은 경우는 두 노드를 차례로 바꿔준다. max heap이 정이되면 삽입된 노드의 최종 위치에 대응하는 min heap노드를 찾아서 두노드의 키 값을 비교한다. max heap노드의 키 값이 min heap노드의 키 값보다 작으면 두 노드를 바꿔준다.
  • 13. 2. 프로젝트 전체일정 기 간 6 / 12 6 / 14 - 조원별 업무 분담 및 계획 작성 - 프로젝트 문제파악 - 알고리즘에 대해 토의하고 이해 내 용 - 프로젝트에 필요한 학습내용 토의 - 문제점 토의 - 프로젝트 진행방향 토의 기 간 6 / 19 6 / 21 - 프로젝트 검토 내 용 - 소스 구현 및 보고서 작성 - 최종보고서 작성 - 발표준비 3. 업무분담 이 름 업 무 김시백 보고서 작성 및 회의 진행, 프로젝트에 필요한 학습내용 숙지 송하윤 알고리즘 설계와 소스에 대한 문제점 검토와 보완 이용재 소스구현 및 코딩 문제의 해결을 위한 방안 제시 이상현 알고리즘 설계 및 프로젝트 수행 시 필요한 자료 수집 박구남 알고리즘 설계 및 프로젝트 수행 시 필요한 자료 수집
  • 14. 4. 소스 #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <string.h> struct Node { char name; Node *link[26]; }; Node AddTree (Node *A, Node *B) { for (int i = 0; i < 26 ; i++) { if (A->link[i] == 0) { A -> link[i] = B; printf("%c의 LINK%d에 %c를 삽입 n",A -> name,i,B -> name); break; } else {} } return *A; } // 노드 A 에 노드 B을 링크합니다. Node AddNode (char A) { Node *B = (Node *)malloc(sizeof(Node)); B->name = A; for (int i = 0; i < 26 ; i++) { B->link[i] = 0; } return *B;
  • 15. } // 노드 생성 함수 int search (Node *A, char B) { for (int i=0;i<26;i++) { if (A -> link[i] != 0) { if (A->link[i]->name == B) {return i;} } } return -1; } // 위치 찾기 void PL(Node *A, char arr[], int x) { x++; arr[x]=A->name; if (A->link[0] == 0) { for (int i = 0 ; i <= x ; i++) { printf("%c",arr[i]); } printf("n"); return; } PL(A,arr,x); return; } int main () { FILE *file; char a, arr[20]; int i, j, x=0; Node *ans = (Node *)malloc(sizeof(Node)); Node *MyspotEEE; file=fopen("D://wordlist.txt","r"); if(file==NULL)
  • 16. { return 1; } i = 0; ans[0] = AddNode('/'); MyspotEEE = &ans[0]; for (;;) { // MyspotEEE 현제 위치, j search 값, x = 생성 노드 위치 a=fgetc(file); if (a == 'n') { // n 이면 단어 하나가 끝났으므로 루트로 돌아간다. MyspotEEE = &ans[0]; continue; } if (a < 91) { // 대문자는 소문자로 바꿔준다[대소문자 구분 안하므로.] a += 32; } if(a==EOF) { break; } j = search(MyspotEEE,a); // 다음 노드에 이미 같은 이름의 노드가 생성되었는지 조사한다. if (j == -1) { // 같은 이름의 노드가 존재하면 그대로 내려가고, 아니면 새로 생성해서 내려간다. x++; ans[x] = AddNode(a); *MyspotEEE = AddTree(MyspotEEE,&ans[x]); MyspotEEE = &ans[x]; } else { MyspotEEE = MyspotEEE->link[j]; } } fclose(file); file=fopen("D://wordlist.txt","r"); if(file==NULL) { return 1;
  • 17. } MyspotEEE = &ans[0]; for (;;) { a=fgetc(file); if ( (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z') ) { // n 이면 단어 하나가 끝났으므로 루트로 돌아간다. MyspotEEE = &ans[0]; x = 0; continue; } if (a < 91) { // 대문자는 소문자로 바꿔준다[대소문자 구분 안하므로.] a += 32; } if(a==EOF) { break; } j = search(MyspotEEE,a); if (j == -1) { // 존재하지 않는다면 printf("사전에 없는 단어입니다.n유사 단어는n"); PL(MyspotEEE,arr,x); printf("가 존재합니다. 다음 단어로 넘어갑니다.n"); a=fgetc(file); if ( (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z') ) { // 다음 단어로 넘어감 printf(" "); } else { printf("n"); break; } if(a==EOF) { break; }
  • 18. for (;;) { // 다음단어로 넘어감 a=fgetc(file); i=0; if ( (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z') ) { printf(" "); } else { printf("n"); break; } if(a==EOF) { break; } } } else { // 존재하지 않는다면의 else MyspotEEE = MyspotEEE->link[j]; x++; } if(a==EOF) { break; } } getch(); return 0; }