⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hash.c

📁 文件系统源代码!!!!! 文件系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** Copyright (C) 2008 Happy Fish / YuQing** FastDFS may be copied only under the terms of the GNU General* Public License V3, which may be found in the FastDFS source kit.* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.**/#include "hash.h"#include <stdlib.h>#include <stdio.h>#include <string.h>#include <errno.h>static unsigned int prime_array[] = {    1,              /* 0 */    3,              /* 1 */    17,             /* 2 */    37,             /* 3 */    79,             /* 4 */    163,            /* 5 */    331,            /* 6 */    673,            /* 7 */    1361,           /* 8 */    2729,           /* 9 */    5471,           /* 10 */    10949,          /* 11 */    21911,          /* 12 */    43853,          /* 13 */    87719,          /* 14 */    175447,         /* 15 */    350899,         /* 16 */    701819,         /* 17 */    1403641,        /* 18 */    2807303,        /* 19 */    5614657,        /* 20 */    11229331,       /* 21 */    22458671,       /* 22 */    44917381,       /* 23 */    89834777,       /* 24 */    179669557,      /* 25 */    359339171,      /* 26 */    718678369,      /* 27 */    1437356741,     /* 28 */    2147483647      /* 29 (largest signed int prime) */};#define PRIME_ARRAY_SIZE  30int _hash_alloc_buckets(HashArray *pHash){	ChainList *plist;	ChainList *list_end;	pHash->items=(ChainList *)malloc(sizeof(ChainList)*(*pHash->capacity));	if (pHash->items == NULL)	{		return ENOMEM;	}	list_end = pHash->items + (*pHash->capacity);	for (plist=pHash->items; plist!=list_end; plist++)	{		chain_init(plist, CHAIN_TYPE_APPEND, free, NULL);	}	return 0;}int hash_init(HashArray *pHash, HashFunc hash_func, \		const unsigned int capacity, const double load_factor){	unsigned int *pprime;	unsigned int *prime_end;	int result;	if (pHash == NULL || hash_func == NULL)	{		return EINVAL;	}	memset(pHash, 0, sizeof(HashArray));	prime_end = prime_array + PRIME_ARRAY_SIZE;	for (pprime = prime_array; pprime!=prime_end; pprime++)	{		if (*pprime > capacity)		{			pHash->capacity = pprime;			break;		}	}	if (pHash->capacity == NULL)	{		return EINVAL;	}	if ((result=_hash_alloc_buckets(pHash)) != 0)	{		return result;	}	pHash->hash_func = hash_func;	if (load_factor >= 0.10 && load_factor <= 1.00)	{		pHash->load_factor = load_factor;	}	else	{		pHash->load_factor = 0.50;	}	return 0;}void hash_destroy(HashArray *pHash){	ChainList *plist;	ChainList *list_end;	if (pHash == NULL || pHash->items == NULL)	{		return;	}	list_end = pHash->items + (*pHash->capacity);	for (plist=pHash->items; plist!=list_end; plist++)	{		chain_destroy(plist);	}	free(pHash->items);	pHash->items = NULL;	if (pHash->is_malloc_capacity)	{		free(pHash->capacity);		pHash->capacity = NULL;		pHash->is_malloc_capacity = false;	}}void hash_stat_print(HashArray *pHash){#define STAT_MAX_NUM  17	ChainList *plist;	ChainList *list_end;	int totalLength;	//ChainNode *pnode;	//HashData *hash_data;	int stats[STAT_MAX_NUM];	int last;	int index;	int i;	int max_length;	int list_count;	int bucket_used;	if (pHash == NULL || pHash->items == NULL)	{		return;	}	memset(stats, 0, sizeof(stats));	last = STAT_MAX_NUM - 1;	list_end = pHash->items + (*pHash->capacity);	max_length = 0;	bucket_used = 0;	for (plist=pHash->items; plist!=list_end; plist++)	{		list_count = chain_count(plist);		if (list_count == 0)		{			continue;		}		bucket_used++;		index = list_count - 1;		if (index > last)		{			index = last;		}		stats[index]++;		if (list_count > max_length)		{			max_length = list_count;		}		/*		pnode = plist->head;		while (pnode != NULL)		{			pnode = pnode->next;		}		*/	}	/*	printf("collision stat:\n");	for (i=0; i<last; i++)	{		if (stats[i] > 0) printf("%d: %d\n", i+1, stats[i]);	}	if (stats[i] > 0) printf(">=%d: %d\n", i+1, stats[i]);	*/	totalLength = 0;	for (i=0; i<STAT_MAX_NUM; i++)	{		if (stats[i] > 0) totalLength += (i+1) * stats[i];	}	printf("capacity: %d, item_count=%d, bucket_used: %d, " \		"avg length: %.4f, max length: %d, bucket / item = %.2f%%\n",                *pHash->capacity, pHash->item_count, bucket_used,               bucket_used > 0 ? (double)totalLength / (double)bucket_used:0.00,               max_length, (double)bucket_used*100.00/(double)*pHash->capacity);}static int _rehash1(HashArray *pHash, const int old_capacity, \		unsigned int *new_capacity){	ChainList *old_items;	ChainList *plist;	ChainList *list_end;	ChainNode *pnode;	HashData *hash_data;	ChainList *pNewList;	int result;	old_items = pHash->items;	pHash->capacity = new_capacity;	if ((result=_hash_alloc_buckets(pHash)) != 0)	{		pHash->items = old_items;		return result;	}	//printf("old: %d, new: %d\n", old_capacity, *pHash->capacity);	list_end = old_items + old_capacity;	for (plist=old_items; plist!=list_end; plist++)	{		pnode = plist->head;		while (pnode != NULL)		{			hash_data = (HashData *) pnode->data;			pNewList = pHash->items + (hash_data->hash_code % \				(*pHash->capacity));			//success to add node			if (addNode(pNewList, hash_data) == 0)			{			}			pnode = pnode->next;		}		plist->freeDataFunc = NULL;		chain_destroy(plist);	}	free(old_items);	return 0;}static int _rehash(HashArray *pHash){	int result;	unsigned int *pOldCapacity;	pOldCapacity = pHash->capacity;	if (pHash->is_malloc_capacity)	{		unsigned int *pprime;		unsigned int *prime_end;		pHash->capacity = NULL;		prime_end = prime_array + PRIME_ARRAY_SIZE;		for (pprime = prime_array; pprime!=prime_end; pprime++)		{			if (*pprime > *pOldCapacity)			{				pHash->capacity = pprime;				break;			}		}	}	else	{		pHash->capacity++;	}	if ((result=_rehash1(pHash, *pOldCapacity, pHash->capacity)) != 0)	{		pHash->capacity = pOldCapacity;  //rollback	}	else	{		if (pHash->is_malloc_capacity)		{			free(pOldCapacity);			pHash->is_malloc_capacity = false;		}	}	/*printf("rehash, old_capacity=%d, new_capacity=%d\n", \		old_capacity, *pHash->capacity);	*/	return result;}int _hash_conflict_count(HashArray *pHash){	ChainList *plist;	ChainList *list_end;	ChainNode *pnode;	ChainNode *pSubNode;	int conflicted;	int conflict_count;	if (pHash == NULL || pHash->items == NULL)	{		return 0;	}	list_end = pHash->items + (*pHash->capacity);	conflict_count = 0;	for (plist=pHash->items; plist!=list_end; plist++)	{		if (plist->head == NULL || plist->head->next == NULL)		{			continue;		}		conflicted = 0;		pnode = plist->head;		while (pnode != NULL)		{			pSubNode = pnode->next;			while (pSubNode != NULL)			{				if (((HashData *)pnode->data)->hash_code != \					((HashData *)pSubNode->data)->hash_code)				{					conflicted = 1;					break;				}				pSubNode = pSubNode->next;			}			if (conflicted)			{				break;			}			pnode = pnode->next;		}		conflict_count += conflicted;	}	return conflict_count;}int hash_best_op(HashArray *pHash, const int suggest_capacity){	int old_capacity;	int conflict_count;	unsigned int *new_capacity;	int result;	if ((conflict_count=_hash_conflict_count(pHash)) == 0)	{		return 0;	}	old_capacity = *pHash->capacity;	new_capacity = (unsigned int *)malloc(sizeof(unsigned int));	if (new_capacity == NULL)	{		return -ENOMEM;	}	if ((suggest_capacity > 2) && (suggest_capacity >= pHash->item_count))	{		*new_capacity = suggest_capacity - 2;		if (*new_capacity % 2 == 0)		{			++(*new_capacity);		}	}	else	{		*new_capacity = 2 * (pHash->item_count - 1) + 1;	}	do	{		do		{			*new_capacity += 2;		} while ((*new_capacity % 3 == 0) || (*new_capacity % 5 == 0) \			 || (*new_capacity % 7 == 0));		if ((result=_rehash1(pHash, old_capacity, new_capacity)) != 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -