ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 열혈강의 자료구조 정리(해싱)
    @ 16. 1 ~ 17. 1/자료구조 2015. 5. 3. 16:41

    해싱은 검색키에 대한 산술 연산을 이용한 검색 방식임

    검색 키 값을 입력값으로 계산을 실시하면 검색하려는 자료의 위치를 알 수 있다는 것이 기본 개념

    검색키 -> 해싱함수 -> 검색 자료의 주소를 -> 해시테이블에서 찾음

    그런데 계산된 주소에 다른 자료가 저장되어 있다면 충돌이 발생한다.

     

    해싱함수로 사용될 수 있는 방법

    1. 나머지 함수

    가장 일반적임 검색 키 값 k를 해시 테이블의 크기 m으로 나눈 나머지를 해시 주소로 사용

    2. 접기함수

    검색 키의 크기가 해시 테이블의 크기보다 큰 정수일 경우 사용

    검색 키 값 k가 데이블의 크기 m보다 큰 경우 k를 m의 자릿수와 같은 크기로 분할한 후 분할된 부분들을 이용하여 해시 테이블 주소 만듬

    예)

    검색 키값 : 1234512345(10자리)

    해시 테이블 크기 m : 999(3자리)

    123 451 234 5로 분할 후

    다 더하면 813나옴(값)

    3. 경계접기 함수

    위의 접기함수와 같으나 키값을 나누고

    123 451 234 5

    이럴때 123와 234를 뒤집어 더한다 321 432로

    그리고 초과하는 자릿수(1000단위) 버림

    4. 중간제곱함수

    검색 키를 제곱한 값 중에서 중간 부분을 해시 테이블 주소로 이용하는 방법

    검색 키 값 9451

    9451 * 9451 = 89321401

    여기서 중간부분 4자리를 이용하여 3214 사용

    5. 숫자분석방법

    숫자로 이뤄진 검색 키 값의 각 자릿수의 분포를 미리 분석하여 해시 주소로 사용하는 방법

    즉, 검색 키 값의 각 자릿수 중에서 가장 편중된 분산을 가지는(충돌 발생 가능성이 큰) 자릿수를 생략하고 가장 고르게 분포된(출동 가능성 낮은) 자릿수만을 추출하여 이를 주소로 활용

    예) 검색 키 값 : 학생의 학번 2010-9025

    단, 처음 4자리 입학연도

    다음 2자리 학과번호

    마지막 2자리 같은 학과내 학생고유 번호

    다 더하면 9025 주소값 사용

     

    *문자열의 경우 문자의 고유값(A는 65이런것.)이 있으므로 그걸 활용함..

     

    해싱함수를 잘 선택하여 충돌을 최소화하지만 충돌이 발생했다면 어떻게 해야할까..

    군집화(특정 주소들 주위로 뭉치는것)현상이 높게 발생하면 안좋음..그래서 최소화 설계해야함..

    이러한 해결방법중

    1. 충돌이 일어난 키 값을 다른 비어 있는 주소를 찾아 저장하는 개방주소(open addressing) 기법

    (모든 주소가 찬 경우에는 안되며 주소를 찾을때까지 반복함)

    2. 해싱 테이블의 구조 자체는 변경하는 체이닝(chaining) 기법

     

     

    개방 주소법에는

    1) 선형 조사법 2) 제곱 조사법 3) 이중 해싱 등이 있다.

     

    1) 선형 조사법 : 충돌이 발생할 경우 주소를 일정한 상수만큼 증가시켜 다시 조사하는 방법

    : 충돌한 주소를 시작으로 차례로 저장되기 때문에 군집화 현상이 발생할 가능성이 크다.

    예를 들어

    해시 테이블 크기 : 5

    해싱함수 : 나머지 함수(mod 5)

    저장되는 검색 키 값 : 1,3,8,13

    일경우에 해시 테이블에 주소는 해싱함수에 의해서 계산되는데..3, 8, 13이 동일하게 충돌된다

    3mod 5 = 3, 8 mod 5 = 3, 13 mod 5 = 3

    검색 키값을 순서대로 저장한다면 키값 1,3이 해싱함수에 의해 1,3주소에 저장되고

    키값 8가 해싱함수에 의해 주소가 3이 나오고 3이 있으므로 충돌되어 주소에 1증가(이때 증가는 키값에 증가시키는것이다) 주소 4에 저장됨..

    그리고 13도 마찬가지 3에 있고 4에 있고 5에 들어감(근데 크기가 5이니 0으로 들어가겠지..01234)

     

    2) 제곱 조사법 : 충돌이 발생한 경우 주소를 조사 횟수의 제곱만큼 증가시켜 다시 조사

    1차 충돌에서는 1더하고 2차에서는 2*2 4를 n번째는 n^2을 주소에 더함.

     

    3) 이중해싱 : 충돌이 발생할 경우 주소를 원래의 해싱 함수와는 다른 추가적인 해싱함수를 이용해 주소를 증가시켜 다시 조사

    여러가지 방법이 있으나 가장 간단한 방법으로 조사간격을 이용하는것.

    조사간격 = M - (k mod M) //M은 해시 테이블 크기 k는 검색 키

    예를 들어

    위으 해시 테이블 등 상황은 똑같고

    8번 키값 해싱함수시 3주소로 충돌발생

    조사간격 = M - (k mod M) = 5 - (8 mod 5) = 5 - 3 = 2

    이번 충돌한 주소 = 3

    새로운 주소는 : 3 + 2 mod 5 = 0

    이런식임..

    이중 해싱은 2차 집중까지 줄어드는 장점이 있음.

     

    아래예제는

    첫번째 충돌 해결방법 : 개방주소

    1) 나머지 함수로 구현된 해싱함수 2) 호너의 방법으로 키값을 정수로 변환 3) 선형 조사법으로 계산된 충돌처리

    이렇게 구현했다..

    해쉬element에는 해쉬상태와 값 그리고 키값(문자열)이 들어가고

    해쉬 테이블에서 element를 버킷사이즈를 활용해서 new받고 사이즈 확보하고...

     

     

    두번째 충돌 해결방법 : 체이닝

    해시테이블의 구조를 변경하여 각 주소에 하나 이상의 검색 키 값이 저장될 수 있도록 하는 방법..(연결리스트 활용이라 이거고..충돌이 발생할 때 동적으로 여러개의 검색 키 값을 저장할 수 있게 하는 방법)

    * 근데 연결리스트에 저장할때 무조건 앞? 뒤? 키값에 의한 정렬? 등을 선택해야함..

    충돌만 틀릴뿐 해싱함수에 의한 선형조사법은 마찬가지로 같음..

     

    아래소스는 1) 해싱함수로 나머지 함수 2) 검색키가 문자열 호너의 방법 3) 충돌 해결법으로 체이닝 사용

    위와는 다르게 STL vector와 list를 활용함. 키값은 string 문자열을 이용하여..

    삭제는 안만듬..

    하면서 문제가 발생되었던것..

    STL의 find함수를 특정 객체나 클래스의 멤버를 찾기위해서 사용한다면 해당 객체의 oprator== 구현해서 하면된다는것.?

    그러고 typedef 쓸모 있다는거..마지막으로 없는값 검색에서 어디가 오류나는지 알고 싶지 않다는거..ㅜ

Designed by Tistory.