자바 오픈 주소 법 과 체인 주소 법 으로 hash 충돌 을 해결 하 는 방법 예시

hashMap 은 여러분 에 게 모 르 는 것 이 없습니다.사용 한 사람 은 hashMap 의 바 텀 실현 원 리 를 어느 정도 알 고 있 을 것 입 니 다.요약 하면 배열+링크 입 니 다.소스 코드 의 실현 에 대해 서 는 소스 코드 를 참조 하 셔 도 됩 니 다.오늘 말씀 드 리 고 싶 은 것 은 hashMap 이 hash 충돌 을 어떻게 해결 하 는 지 하 는 것 입 니 다.
먼저 그림 한 장 을 보고,
在这里插入图片描述
이 그림 에서 알 수 있 듯 이 hashMap 은 하나의 배열 을 유지 하고 배열 안의 모든 단원 은 하나의 링크 입 니 다.그러면 왜 hash 충돌 이 발생 합 니까?이것 이 바로 다음 에 토론 해 야 할 문제 다.
배열 이기 때문에 반드시 길이 가 있 을 것 입 니 다.우리 가 배열 에 데 이 터 를 삽입 할 때 어떤 유형의 데이터 든 배열 에 있어 서 특정한 아래 표 에 대응 하 는 공간 을 차지 하 는 것 입 니 다.그러면 가입 한 데이터 가 점점 많아 질 때 여러 개의 데이터 가 같은 위 치 를 차지 하 는 것 이 아 닙 니까?답 은 긍정 적 이다.이것 이 바로 hash 충돌 이 발생 하 는 원시 적 인 요소 이다.
먼저,우 리 는 몇 가지 개념 을 알 아 보 겠 습 니 다.hashMap 또는 다른 유사 한 map 에 있어 서 우리 가 안에 데 이 터 를 추가 할 때 배열 에 직접 추가 하 는 것 이 아니 라 이 데 이 터 를 삽입 하 는 hash 값 을 계산 하 는 것 입 니 다.즉,hash 알고리즘 을 통 해 이 값 을 추가 한 다음 에 데 이 터 를 찾 을 때 hashMap 역시 당신 의 key 에 따라이 hash 값 을 거꾸로 내 놓 고 데 이 터 를 꺼 냅 니 다.즉,이 hash 값 은 삽입 값 에 대응 하 는 배열 아래 표 로 이해 할 수 있 습 니 다.
그러나 실험 을 통 해 알 수 있 듯 이 hash 함수 가 서로 다른 key 를 계산 할 때 같은 hash 값 을 얻 을 수 있 습 니 다.그러면 이 hash 값 을 배열 의 표지 로 사용 하면 이 값 의 아래 표 시 를 찾 을 수 없습니다.이때 충돌 이 발생 합 니 다.
다음은 개발 주소 법 으로 hash 충돌 문 제 를 해결 하 는 코드 를 모 의 해 보 겠 습 니 다.먼저 대상 을 정의 합 니 다.여 기 는 Info 입 니 다.실제 장면 에 더욱 가 까 워 지기 위해 서 여기 있 는 속성 은 모두 문자열 입 니 다.
개방 주소 법 은 무엇 입 니까?
충돌 이 발생 했 을 때 배열 의 빈 자 리 를 찾 아 데 이 터 를 삽입 하고 hash 함수 로 획득 수의 아래 표 시 를 계산 하지 않 습 니 다.이 방법 을 개발 주소 법 이 라 고 합 니 다.

public class Info {
	private String key;			//   ,            
	private String name;		//  
	
	public Info(String key, String name) {
		this.key = key;
		this.name = name;
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
다음은 hashTable 을 손 으로 써 서 hashMap 을 모 의 하 는 데 사용 합 니 다.

/**
 *   hashMap
 *
 */
public class HashTable {
	
	private Info[] arr;
	
	/**
	 *        
	 */
	public HashTable() {
		arr = new Info[100];
	}
	
	/**
	 *          
	 */
	public HashTable(int maxSize) {
		arr = new Info[maxSize];
	}
	
	/**
	 *     
	 */
	public void insert(Info info) {
		//     
		String key = info.getKey();
		//          
		int hashVal = hashCode(key);
		//           ,              
		while(arr[hashVal] != null && arr[hashVal].getName() != null) {
			//    ,    
			++hashVal;
			//  
			hashVal %= arr.length;
		}
		arr[hashVal] = info;
	}
	
	/**
	 *     
	 */
	public Info find(String key) {
		int hashVal = hashCode(key);
		while(arr[hashVal] != null) {
			if(arr[hashVal].getKey().equals(key)) {
				return arr[hashVal];
			}
			++hashVal;
			hashVal %= arr.length;
		}
		return null;
	}
	
	/**
	 *     
	 */
	public Info delete(String key) {
		int hashVal = hashCode(key);
		//    ,      hashVal  ,      null
		while(arr[hashVal] != null) {
			if(arr[hashVal].getKey().equals(key)) {
				Info tmp = arr[hashVal];
				tmp.setName(null);
				return tmp;
			}
			++hashVal;			//          ,      ,       
			hashVal %= arr.length;
		}
		return null;
	}
	
	/**
	 *       hash ,      
	 */
	public int hashCode(String key) {
		
		BigInteger hashVal = new BigInteger("0");
		BigInteger pow27 = new BigInteger("1");
		for(int i = key.length() - 1; i >= 0; i--) {
			int letter = key.charAt(i) - 96;
			BigInteger letterB = new BigInteger(String.valueOf(letter));
			hashVal = hashVal.add(letterB.multiply(pow27));
			pow27 = pow27.multiply(new BigInteger(String.valueOf(27)));
		}
		return hashVal.mod(new BigInteger(String.valueOf(arr.length))).intValue();
	}
}
이 를 통 해 알 수 있 듯 이 우 리 는 삽입 할 수 있 는 수치 에 대해 hash 인 코딩 을 한 다음 에 수치의 길 이 를 모드 i 로 합 니 다.이렇게 얻 은 위 치 는 항상 수치의 길이 안에 떨 어 질 수 있 습 니 다.
안에 이해 하기 어 려 운 부분 이 있 습 니 다.바로 데 이 터 를 삽입 할 때 우 리 는 while 순환 으로 삽입 합 니 다.개발 주소 인 만큼 배열 의 모든 유 휴 공간 을 우 리 는 사용 할 수 있 습 니 다.전 제 는 이 위치 가 다른 값 에 의 해 점용 되 지 않 았 다 는 것 입 니 다.배열 이 연속 적 이기 때문에 우 리 는 순환 적 으로 이런 위 치 를 찾 아야 합 니 다.그래서++hashVal 이라는 코드 가 있 습 니 다.빈 자 리 를 찾 을 때 까지 데 이 터 를 삽입 합 니 다.
在这里插入图片描述
테스트 main 방법 을 실행 합 니 다.우 리 는 데이터 가 성공 적 으로 삽입 되 었 음 을 보 았 습 니 다.그러나 hash 함 수 를 통 해 계산 한'a'와'ct'는 똑 같 습 니 다.앞에서 말 한 문 제 를 다시 한 번 입증 하 였 습 니 다.
在这里插入图片描述
이상 은 바로 개발 주소 법 으로 hash 충돌 을 해결 하 는 해결 방법 을 말 한 것 입 니 다.그러나 이렇게 하면 만전 을 기 할 수 있 습 니까?
우 리 는 데이터 의 길이 가 유한 하 다 는 것 을 고려 해 보 겠 습 니 다.그러나 우 리 는 배열 에 많은 데 이 터 를 추가 할 수 있 습 니 다.배열 은 항상 채 워 질 때 가 있 습 니 다.그러면 주소 법 을 개발 하 는 것 도 소 용이 없습니다.물론 실제 업무 에서 데이터 의 크기 를 예측 할 수 있다 면 우 리 는 이런 방식 으로 일부 문 제 를 해결 할 수 있 습 니 다.문 제 는 이렇다.확실한 해결책 은 아니다.
더 적합 한 방법 은 무엇 일 까요?사실은 hashMap 에서 비교적 많은 체인 주소 법 을 사 용 했 습 니 다.즉,처음에 우리 그림 에서 보 여 준 것 입 니 다.기본 구 조 는 아직도 하나의 배열 입 니 다.그러나 배열 의 모든 단원 이 하나의 데이터 가 아니 라 하나의 링크 입 니 다.즉,linkedList 와 같은 구조 입 니 다.새로 삽 입 된 여러 데 이 터 는 hash 함 수 를 계산 하여 같은 배열 아래 표 시 를 얻 었 을 때우 리 는 이 색인 위치 에서 유지 하 는 링크 에 값 을 삽입 하면 됩 니 다.무엇이 체인 주소 법 입 니까?
**
hash 표 의 각 단원 에 링크 를 설정 합 니 다.삽입 할 데이터 항목 의 키 워드 는 보통 hash 표 의 한 단원 에 투사 되 고 데이터 항목 자 체 는 이 단원 이 유지 하 는 링크 에 삽 입 됩 니 다.
**
다음은 코드 로 이 과정 을 실현 하 겠 습 니 다.위의 모든 것 과 다른 것 은 링크 중의 구 조 는 우리 가 관리자 의 한 노드,즉 Node 를 통 해 링크 구조 에 익숙 하지 않 은 학생 들 이 먼저 스스로 바 이 두 를 할 수 있 습 니 다.어렵 지 않 습 니 다.
1.대상 Info 를 정의 합 니 다.

public class Info {
	
	private String key;
	private String name;
	
	public Info(String key, String name) {
		this.key = key;
		this.name = name;
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	
	
}
2.노드 를 링크 의 기본 저장 장치 로 정의 합 니 다.

public class Node {

	//    
	public Info info;
	//    ,          
	public Node next;

	public Node(Info info) {
		this.info = info;
	}

}
3.링크 를 정의 합 니 다.

/**
 *   linkedList
 * 
 * @author asus
 *
 */
public class LinkList {

	//    
	private Node first;

	public LinkList() {
		first = null;
	}

	//       
	public void insertFirst(Info info) {
		Node node = new Node(info);
		node.next = first;
		first = node;
	}

	//       ,         
	public Node deleteFirst() {
		Node temp = first;
		first = temp.next;
		return temp;
	}

	/**
	 *     
	 */
	public Node find(String key) {
		Node current = first;
		while (!key.equals(current.info.getKey())) {
			if (current.next == null) {
				return null;
			}
			current = current.next;
		}
		return current;
	}

	/**
	 *     
	 */
	public Node delete(String key) {
		Node current = first;
		Node previous = first;
		while (!key.equals(current.info.getKey())) {
			if (current.next == null) {
				return null;
			}
			previous = current;
			current = current.next;
		}

		if (current == first) {
			first = first.next;
		} else {
			previous.next = current.next;
		}
		return current;

	}

}
4.hashMap 을 모 의 하 는 몇 가지 방법,

public class HashTable {

	private LinkList[] arr;

	/**
	 *        
	 */
	public HashTable() {
		arr = new LinkList[100];
	}

	/**
	 *          
	 */
	public HashTable(int maxSize) {
		arr = new LinkList[maxSize];
	}

	/**
	 *     
	 */
	public void insert(Info info) {
		String key = info.getKey();
		//          hash  
		int hashVal = hashCode(key);

		if (arr[hashVal] == null) {		//             ,         linkList
			arr[hashVal] = new LinkList();
		}
		arr[hashVal].insertFirst(info);
	}

	/**
	 *     
	 */
	public Info find(String key) {
		int hashVal = hashCode(key);
		return arr[hashVal].find(key).info;
	}
	
	/**
	 *     
	 */
	public Info delete(String key){
		int hashVal = hashCode(key);
		return arr[hashVal].delete(key).info;
	}
	

	/**
	 *      hash   
	 */
	public int hashCode(String key) {

		BigInteger hashVal = new BigInteger("0");
		BigInteger pow27 = new BigInteger("1");
		for (int i = key.length() - 1; i >= 0; i--) {
			int letter = key.charAt(i) - 96;
			BigInteger letterB = new BigInteger(String.valueOf(letter));
			hashVal = hashVal.add(letterB.multiply(pow27));
			pow27 = pow27.multiply(new BigInteger(String.valueOf(27)));
		}
		return hashVal.mod(new BigInteger(String.valueOf(arr.length))).intValue();
	}

}
위 에서 개발 한 주소 법 에 데 이 터 를 삽입 하고 데 이 터 를 찾 는 것 과 달리 이런 방식 으로 데 이 터 를 찾 을 때 사실은 두 번 이나 찾 은 것 이다.첫 번 째 포 지 셔 닝 배열 의 위 치 를 두 번 째 로 링크 에 가서 링크 의 검색 방법 으로 찾 는 것 도 주의해 야 한다.삽입 과 삭제 의 사상 도 비슷 하 다.
在这里插入图片描述
다음 에 우리 가 테스트 를 해 보면 아직도 효 과 를 얻 었 다 는 것 을 알 수 있다.이 는 우리 가 모 의 한 체인 주소 법 도 효력 이 발생 했다 는 것 을 의미한다.
在这里插入图片描述
이상 은 주소 법 과 체인 주소 법 을 개발 하여 hash 충돌 을 해결 하 는 두 가지 방식 입 니 다.hashMap 의 바 텀 원 리 를 이해 하 는 데 도움 이 되 기 를 바 랍 니 다.시청 해 주 셔 서 감사합니다.많은 응원 부 탁 드 리 겠 습 니 다.

좋은 웹페이지 즐겨찾기