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

📄 dict.cc

📁 This Source-Navigator, an IDE for C/C++/Fortran/Java/Tcl/PHP/Python and a host of other languages.
💻 CC
字号:
// $Header: /cvsroot/sourcenav/src/snavigator/demo/c++_demo/glish/Dict.cc,v 1.1.1.1 2002/04/18 23:35:24 mdejong Exp $#include <string.h>#include "Glish/Dict.h"// If the mean bucket length exceeds the following then Insert() will// increase the size of the hash table.#define TOO_CROWDED 3class DictEntry {public:	DictEntry( const char* k, void* val )		{ key = k; value = val; }	const char* key;	void* value;	};// The value of an iteration cookie is the bucket and offset within the// bucket at which to start looking for the next value to return.class IterCookie {public:	IterCookie( int b, int o )		{		bucket = b;		offset = o;		}	int bucket, offset;	};Dictionary::Dictionary( dict_order ordering, int initial_size )	{	Init( initial_size );	if ( ordering == ORDERED )		order = new PList(DictEntry);	else		order = 0;	}Dictionary::~Dictionary()	{	for ( int i = 0; i < num_buckets; ++i )		if ( tbl[i] )			delete tbl[i];	delete tbl;	if ( order )		{		while ( order->length() > 0 )			delete order->get();		delete order;		}	}void* Dictionary::Insert( const char* key, void* value )	{	DictEntry* new_entry = new DictEntry( key, value );	void* old_val = Insert( new_entry );	if ( old_val )		{		// We didn't need the new DictEntry, the key was already		// present.		delete new_entry;		}	else if ( order )		order->append( new_entry );	if ( num_entries / num_buckets >= TOO_CROWDED )		ChangeSize( num_buckets * 2 );	return old_val;	}void* Dictionary::Lookup( const char* key ) const	{	int h = Hash( key, num_buckets );	PList(DictEntry)* chain = tbl[h];	if ( chain )		{		for ( int i = 0; i < chain->length(); ++i )			{			DictEntry* entry = (*chain)[i];			if ( ! strcmp( key, entry->key ) )				return entry->value;			}		}	return NotFound;	}void* Dictionary::NthEntry( int n, const char*& key ) const	{	if ( ! order || n < 0 || n >= Length() )		return 0;	DictEntry* entry = (*order)[n];	key = entry->key;	return entry->value;	}char* Dictionary::Remove( const char* key )	{	int h = Hash( key, num_buckets );	PList(DictEntry)* chain = tbl[h];	if ( chain )		{		for ( int i = 0; i < chain->length(); ++i )			{			DictEntry* entry = (*chain)[i];			if ( ! strcmp( key, entry->key ) )				{				char* entry_key = (char*) entry->key;				chain->remove( entry );				if ( order )					order->remove( entry );				delete entry;				--num_entries;				return entry_key;				}			}		}	return 0;	}IterCookie* Dictionary::InitForIteration() const	{	return new IterCookie( 0, 0 );	}void* Dictionary::NextEntry( const char*& key, IterCookie*& cookie ) const	{	int b = cookie->bucket;	int o = cookie->offset;	DictEntry* entry;	if ( tbl[b] && tbl[b]->length() > o )		{		entry = (*tbl[b])[o];		++cookie->offset;		key = entry->key;		return entry->value;		}	++b;	while ( b < num_buckets && (! tbl[b] || tbl[b]->length() == 0) )		++b;	if ( b >= num_buckets )		{ // All done.		delete cookie;		return 0;		}	entry = (*tbl[b])[0];	key = entry->key;	cookie->bucket = b;	cookie->offset = 1;	return entry->value;	}void Dictionary::Init( int size )	{	num_buckets = NextPrime( size );	tbl = new PList(DictEntry)*[num_buckets];	for ( int i = 0; i < num_buckets; ++i )		tbl[i] = 0;	num_entries = 0;	}void* Dictionary::Insert( DictEntry* new_entry )	{	int h = Hash( new_entry->key, num_buckets );	PList(DictEntry)* chain = tbl[h];	if ( chain )		{		for ( int i = 0; i < chain->length(); ++i )			{			DictEntry* entry = (*chain)[i];			if ( ! strcmp( new_entry->key, entry->key ) )				{				void* old_value = entry->value;				entry->value = new_entry->value;				return old_value;				}			}		}	else		{ // Create new chain.		chain = tbl[h] = new PList(DictEntry);		}	// We happen to know (:-() that appending is more efficient	// on lists than prepending.	chain->append( new_entry );	++num_entries;	return 0;	}int Dictionary::Hash( const char* str, int hash_size ) const	{	int hashval;	hashval = 0;	while ( *str )		hashval = ((hashval << 1) + *str++) % hash_size;	return hashval;	}int Dictionary::NextPrime( int n ) const	{	while ( ! IsPrime( n ) )		++n;	return n;	}int Dictionary::IsPrime( int n ) const	{	if ( (n & 0x1) == 0 )		// Even.		return 0;	for ( int j = 3; j * j <= n; ++j )		if ( n % j == 0 )			return 0;	return 1;	}void Dictionary::ChangeSize( int new_size )	{	// First collect the current contents into a list.	PList(DictEntry)* current;	if ( order )		current = order;	else		{		current = new PList(DictEntry);		for ( int i = 0; i < num_buckets; ++i )			{			if ( tbl[i] )				{				PList(DictEntry)* chain = tbl[i];				for ( int j = 0; j < chain->length(); ++j )					current->append( (*chain)[j] );				}			}		}	delete tbl;	Init( new_size );	for ( int i = 0; i < current->length(); ++i )		Insert( (*current)[i] );	if ( ! order )		delete current;	}

⌨️ 快捷键说明

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