source of hsearch_r
은 온라인으로 찾을 수 있습니다.
키가 테이블에 있으면 작업을 확인하기 전에 발견 된 항목과 함께 함수가 반환되므로 기존 키를 추가하면 찾은 것처럼 작동합니다. (찾은 구조체의 값을 hsearch(ADD)
으로 호출 한 후 덮어 쓸 수 있고 이전 값을 덮어 쓸 수 있습니다.)
구현은 요소 삭제에 적합하지 않습니다. 버킷 배열을 유지 관리합니다. 해시 충돌은 다른 빈 버킷을 찾아 처리하므로 버킷 인덱스가 해시 코드와 반드시 같지는 않습니다. 동일한 해시 코드로 두 개의 값을 삽입하면 두 번째 값은 해시 코드가 버킷 인덱스가 아닌 곳에 버킷을 가져옵니다.
이제 첫 번째 항목을 삭제 한 다음 두 번째 항목을 찾으려고하면 "다른"버킷은 해시 코드가 버킷 색인 인 "최적"버킷이 가득 찬 경우에만 고려되므로 찾을 수 없습니다. .
업데이트되지 않은 다시 추가 및 누락 된 삭제 옵션 외에도 hsearch_r
에 대한 다른 제한 사항이 있습니다. 예를 들어, 항목의 최대 누벨은 사전에 추정되어야하며 나중에 변경할 수 없습니다. 나는 hsearch_r
이 제한된 범위의 응용 프로그램을위한 빠른 해시 테이블로 의도되었다고 생각합니다. 좀 더 일반적인 해시 테이블 구현으로 더 나아질 수 있습니다.
또는 "없음"을 의미하는 기본 데이터 매개 변수를 사용할 수 있습니다. entry->data
유형은 void *
입니다. 따라서 NULL
은 확실한 선택입니다.
#include <stdio.h>
#include <stdlib.h>
#define _GNU_SOURCE
#define __USE_GNU
#include <search.h>
#define NIL (-1L)
void hadd(struct hsearch_data *tab, char *key, long value)
{
ENTRY item = {key, (void *) value};
ENTRY *pitem = &item;
if (hsearch_r(item, ENTER, &pitem, tab)) {
pitem->data = (void *) value;
}
}
void hdelete(struct hsearch_data *tab, char *key)
{
ENTRY item = {key};
ENTRY *pitem = &item;
if (hsearch_r(item, FIND, &pitem, tab)) {
pitem->data = (void *) NIL;
}
}
long hfind(struct hsearch_data *tab, char *key)
{
ENTRY item = {key};
ENTRY *pitem = &item;
if (hsearch_r(item, FIND, &pitem, tab)) {
return (long) pitem->data;
}
return NIL;
}
int main()
{
char *data[] = {
"apple", "pear", "cherry", "kiwi",
"orange", "plum", "pomegranate", NULL
};
char **p = data;
struct hsearch_data tab = {0};
int i;
hcreate_r(10, &tab);
for (i = 0; i < 5; i++) hadd(&tab, data[i], i + 1L);
hdelete(&tab, "pear");
hadd(&tab, "cherry", 144);
while (*p) {
long value = hfind(&tab, *p);
if (value == NIL) {
printf("%s: NIL\n", *p);
} else {
printf("%s: %ld\n", *p, value);
}
p++;
}
hdestroy_r(&tab);
return 0;
}
참고 : 다음과 같은 데이터는 hsearch_r
보다 더 자연스러운 구문이 래퍼 함수와 맨 페이지의 예 수정 당신이 데이터로 ponters를 사용하여 해시 테이블은 데이터를 소유하고 있다면, 당신은을 free
합니다 파괴에 대한 데이터뿐만 아니라 기존 값을 덮어 쓸 때도 마찬가지입니다.
@M Oehm,'hsearch_r'에 대한 세 번째 인수는 반환 값을 포함 할 구조체입니다. 맞습니까? 그럼, 왜 그것을 & item'에 초기화할까요? ps : 나는 hsearch_r을 사용하려고 애쓰는 초보자입니다. – venkrao
@venkrao :'pitem'을 초기화 할 필요가 없습니다. 덮어 쓰기되기 때문에 초기화되지 않은 포인터의 주소를 전달할 수 있습니다. 그래서'& item'에 대한 초기화는 혼란 스럽지만 뜨겁고 해로운 것입니다. 'pitem'을 초기화해야한다면 더 좋은 값은'NULL' 일 수 있습니다. –
@M Oehm, 감사합니다. 'hsearch_r'가 해시 테이블에'ENTER' 요소를 넣을 수있는 코드에서이 이상한 동작을 관찰하고 있습니다. 그러나 '찾기'를 시도하면 검색이 실패합니다. 일부 인쇄 문을 사용하여 더 많은 디버깅을 수행하면서 마지막으로 삽입 된 요소 만 해시 테이블에 머물러 있다는 것을 알게되었습니다. 다른 사람은 그렇지 않거나, 그냥 덮어 씁니다. 왜 하나의 요소 만 존재하는지 이해하기 어렵습니다 (왜 겹쳐 씁니까). 비슷한 행동을 보았는지 궁금하고, 문제를 잘 설명해 주었으면합니다. – venkrao