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

📄 sarray.cc

📁 这是一款很好用的工具包
💻 CC
字号:
/* * SArray.cc -- *	Sorted array implementation * */#ifndef _SArray_cc_#define _SArray_cc_#ifndef lintstatic char SArray_Copyright[] = "Copyright (c) 1995-2005 SRI International.  All Rights Reserved.";static char SArray_RcsId[] = "@(#)$Header: /home/srilm/devel/dstruct/src/RCS/SArray.cc,v 1.39 2006/01/05 20:21:27 stolcke Exp $";#endif#include <new>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include "SArray.h"#undef INSTANTIATE_SARRAY#define INSTANTIATE_SARRAY(KeyT, DataT) \	template <> DataT *SArray< KeyT, DataT >::removedData = 0; \	template class SArray< KeyT, DataT >; \	template class SArrayIter< KeyT, DataT >#ifndef __GNUG__template <class KeyT, class DataT>DataT *SArray<KeyT,DataT>::removedData = 0;#endif /* __GNUG__ */#define BODY(b)	((SArrayBody<KeyT,DataT> *)b)staticint (*SArray_thisKeyCompare)();		/* used by SArrayIter() to communicate									* with compareIndex() */staticvoid *SArray_thisBody;			/* ditto */const double growSize = 1.1;template <class KeyT, class DataT>voidSArray<KeyT,DataT>::dump() const{    if (body == 0) {	cerr << "EMPTY" << endl;    } else {	unsigned nEntries = numEntries();	cerr << "maxEntries = " << BODY(body)->maxEntries;	cerr << " nEntries = " << nEntries;	for (unsigned i = 0; i < nEntries; i++) {	    cerr << " " << i << ": ";	    cerr << BODY(body)->data[i].key#ifdef DUMP_VALUES			/* 			 * Only certain types can be printed.			 */		     << "->" << BODY(body)->data[i].value#endif /* DUMP_VALUES */		     ;	}	cerr << endl;    }}template <class KeyT, class DataT>voidSArray<KeyT,DataT>::memStats(MemStats &stats) const{    stats.total += sizeof(*this);    if (body) {	unsigned maxEntries = BODY(body)->maxEntries;	stats.total += sizeof(*BODY(body)) +			sizeof(BODY(body)->data[0]) *				(maxEntries - 1);	stats.wasted += sizeof(BODY(body)->data[0]) *				(maxEntries - numEntries());    }}template <class KeyT, class DataT>voidSArray<KeyT,DataT>::alloc(unsigned size){    body = (SArrayBody<KeyT,DataT> *)malloc(sizeof(*BODY(body)) +			   (size - 1) * sizeof(BODY(body)->data[0]));    assert(body != 0);    BODY(body)->deleted = 0;    BODY(body)->maxEntries = size;    /*     * Fill the array with dummy keys, marking the unused space     */    for (unsigned i = 0; i < size; i ++) {	Map_noKey(BODY(body)->data[i].key);    }}template <class KeyT, class DataT>SArray<KeyT,DataT>::SArray(unsigned size)    : body(0){    if (size != 0) {	alloc(size);    }}template <class KeyT, class DataT>voidSArray<KeyT,DataT>::clear(unsigned size){    if (body) {	unsigned maxEntries = BODY(body)->maxEntries;	for (unsigned i = 0; i < maxEntries; i++) {	    KeyT thisKey = BODY(body)->data[i].key;	    if (Map_noKeyP(thisKey)) {		break;	    }	    Map_freeKey(thisKey);	}	free(body);	body = 0;    }    if (size != 0) {	alloc(size);    }}template <class KeyT, class DataT>SArray<KeyT,DataT>::~SArray(){    clear(0);}template <class KeyT, class DataT>unsignedSArray<KeyT,DataT>::numEntries() const{    if (body == 0) {	return 0;    } else if (Map_noKeyP(BODY(body)->data[0].key)) {	return 0;    } else {	/*	 * Do a binary search for the end of the used memory	 * lower always points to a filled entry	 * upper always points to a free entry beyond the end of used entries	 */	unsigned lower, upper;	lower = 0;			/* minimum index (inclusive) */	upper = BODY(body)->maxEntries;	/* maximum index (exclusive) */	while (lower + 1 < upper) {	    unsigned middle = (lower + upper)/2;	    if (Map_noKeyP(BODY(body)->data[middle].key)) {		    upper = middle;	    } else {		    lower = middle;	    }	}	/* lower + 1 == upper */	return upper;    }}template <class KeyT, class DataT>SArray<KeyT,DataT>::SArray(const SArray<KeyT,DataT> &source)    : body(0){#ifdef DEBUG    cerr << "warning: SArray copy constructor called\n";#endif    *this = source;}template <class KeyT, class DataT>SArray<KeyT,DataT> &SArray<KeyT,DataT>::operator= (const SArray<KeyT,DataT> &other){#ifdef DEBUG    cerr << "warning: SArray::operator= called\n";#endif    if (&other == this) {	return *this;    }    /*     * copy array entries from old to new      */    if (other.body) {	unsigned maxEntries = BODY(other.body)->maxEntries;	clear(maxEntries);	for (unsigned i = 0; i < maxEntries; i++) {	    KeyT thisKey = BODY(other.body)->data[i].key;	    if (Map_noKeyP(thisKey)) {		break;	    }	    /*	     * Copy key	     */	    BODY(body)->data[i].key = Map_copyKey(thisKey);	    /*	     * Initialize data, required for = operator	     */	    new (&(BODY(body)->data[i].value)) DataT;	    /*	     * Copy data	     */	    BODY(body)->data[i].value = BODY(other.body)->data[i].value;	}    } else {	clear(0);    }    return *this;}/* * Returns index into data array that has the key which is either * equal to key, or indicates the place where key would be placed if it * occurred in the array. */template <class KeyT, class DataT>BooleanSArray<KeyT,DataT>::locate(KeyT key, unsigned &index) const{    assert(!Map_noKeyP(key));    if (body) {	unsigned lower, upper;	lower = 0;			/* minimum index (inclusive) */	upper = BODY(body)->maxEntries;	/* maximum index (exclusive) */	while (lower < upper) {	    unsigned middle = (lower + upper)/2;	    KeyT thisKey = BODY(body)->data[middle].key;	    if (Map_noKeyP(thisKey)) {		upper = middle;		continue;	    }	    	    int compare = SArray_compareKey(key, thisKey);	    if (compare < 0) {		    upper = middle;	    } else if (compare > 0) {		    lower = middle + 1;	    } else {		    index = middle;		    return true;	    }	}	/* we have lower == upper */	if (lower == BODY(body)->maxEntries ||	    Map_noKeyP(BODY(body)->data[lower].key) ||	    SArray_compareKey(key, BODY(body)->data[lower].key) < 0)	{	    index = lower;	} else  {	    index = lower + 1;	}	return false;    } else {	return false;    }}template <class KeyT, class DataT>DataT *SArray<KeyT,DataT>::find(KeyT key, Boolean &foundP) const{    unsigned index;    if (foundP = locate(key, index)) {	return &(BODY(body)->data[index].value);    } else {	return 0;    }}template <class KeyT, class DataT>KeyTSArray<KeyT,DataT>::getInternalKey(KeyT key, Boolean &foundP) const{    unsigned index;    static KeyT zeroKey;    if (foundP = locate(key, index)) {	return BODY(body)->data[index].key;    } else {	return zeroKey;    }}template <class KeyT, class DataT>DataT *SArray<KeyT,DataT>::insert(KeyT key, Boolean &foundP){    unsigned index;    /*     * Make sure there is room for at least one entry     */    if (body == 0) {	alloc(1);    }    if (foundP = locate(key, index)) {	return &(BODY(body)->data[index].value);    } else {	unsigned nEntries = numEntries();	unsigned maxEntries = BODY(body)->maxEntries;	/*	 * Need to add an element.	 * First, enlarge array if necessary	 */	if (nEntries == maxEntries) {	    maxEntries = (int)(maxEntries * growSize);	    if (maxEntries == nEntries) {		maxEntries ++;	    }	    body = (SArrayBody<KeyT,DataT> *)realloc(body,			sizeof(*BODY(body)) +			   (maxEntries - 1) * sizeof(BODY(body)->data[0]));	    assert(body != 0);	    /*	     * Fill new space with dummy keys	     */	    for (unsigned i = BODY(body)->maxEntries; i < maxEntries; i ++) {		Map_noKey(BODY(body)->data[i].key);	    }	    BODY(body)->maxEntries = maxEntries;	}	memmove(&(BODY(body)->data[index + 1]),		&(BODY(body)->data[index]),		(nEntries - index) * sizeof(BODY(body)->data[0]));	BODY(body)->data[index].key = Map_copyKey(key);	/*	 * Initialize data to zero, but also call constructors, if any	 */	memset(&(BODY(body)->data[index].value), 0,		   sizeof(BODY(body)->data[index].value));	new (&(BODY(body)->data[index].value)) DataT;	return &(BODY(body)->data[index].value);    }}  template <class KeyT, class DataT>DataT *SArray<KeyT,DataT>::remove(KeyT key, Boolean &foundP){    unsigned index;    /*     * Allocate pseudo-static memory for removed objects (returned by     * remove()). We cannot make this static because otherwise      * the destructor for DataT would be called on it at program exit.     */    if (removedData == 0) {	removedData = (DataT *)malloc(sizeof(DataT));	assert(removedData != 0);    }    if (foundP = locate(key, index)) {	unsigned nEntries = numEntries();	Map_freeKey(BODY(body)->data[index].key);	memcpy(removedData, &BODY(body)->data[index].value, sizeof(DataT));	memmove(&(BODY(body)->data[index]),		&(BODY(body)->data[index + 1]),		(nEntries - index - 1) * sizeof(BODY(body)->data[0]));	/*	 * mark previous last slot as free	 */	Map_noKey(BODY(body)->data[nEntries-1].key);	/*	 * Indicate that deletion occurred	 */	BODY(body)->deleted = 1;	return removedData;    } else {	return 0;    }}  template <class KeyT, class DataT>voidSArrayIter<KeyT,DataT>::sortKeys(){    /*     * Store keys away and sort them to the user's orders.     */    unsigned *sortedIndex = new unsigned[numEntries];    assert(sortedIndex != 0);    unsigned i;    for (i = 0; i < numEntries; i++) {	sortedIndex[i] = i;    }    /*     * Due to the limitations of the qsort interface we have to      * pass extra information to compareIndex in these global     * variables - yuck.      */    SArray_thisKeyCompare = (int (*)())sortFunction;    SArray_thisBody = mySArrayBody;    qsort(sortedIndex, numEntries, sizeof(*sortedIndex), compareIndex);    /*     * Save the keys for enumeration.  The reason we save the keys,     * not the indices, is that indices may change during enumeration     * due to deletions.     */    sortedKeys = new KeyT[numEntries];    assert(sortedKeys != 0);    for (i = 0; i < numEntries; i++) {	sortedKeys[i] = mySArrayBody->data[sortedIndex[i]].key;    }    delete [] sortedIndex;}template <class KeyT, class DataT>SArrayIter<KeyT,DataT>::SArrayIter(const SArray<KeyT,DataT> &sarray,					int (*keyCompare)(KeyT, KeyT))    : mySArrayBody(BODY(sarray.body)), current(0),      numEntries(sarray.numEntries()), sortFunction(keyCompare){    /*     * Note: we access the underlying SArray through the body pointer,     * not the top-level SArray itself.  This allows the top-level object     * to be moved without affecting an ongoing iteration.     * XXX: This only works because     * - it is illegal to insert while iterating     * - deletions don't cause reallocation of the data     */    if (sortFunction && mySArrayBody) {	sortKeys();    } else {	sortedKeys = 0;    }    if (mySArrayBody) {	mySArrayBody->deleted = 0;    }}/* * This is the callback function passed to qsort for comparing array * entries. It is passed the indices into the data array, which are * compared according to the user-supplied function applied to the  * keys found at those locations. */template <class KeyT, class DataT>intSArrayIter<KeyT,DataT>::compareIndex(const void *idx1, const void *idx2){  return (*(compFnType)SArray_thisKeyCompare)		(BODY(SArray_thisBody)->data[*(unsigned *)idx1].key,		 BODY(SArray_thisBody)->data[*(unsigned *)idx2].key);}template <class KeyT, class DataT>SArrayIter<KeyT,DataT>::~SArrayIter(){    delete [] sortedKeys;}template <class KeyT, class DataT>voidSArrayIter<KeyT,DataT>::init(){    delete [] sortedKeys;    sortedKeys = 0;    current = 0;    {	/*	 * XXX: fake SArray object to access numEntries()	 */	SArray<KeyT,DataT> mySArray(0);	mySArray.body = mySArrayBody;	numEntries = mySArray.numEntries();	mySArray.body = 0;    }    if (mySArrayBody) {	if (sortFunction) {	    sortKeys();	}	mySArrayBody->deleted = 0;    }}template <class KeyT, class DataT>DataT *SArrayIter<KeyT,DataT>::next(KeyT &key){    if (mySArrayBody == 0) {	return 0;    } else {	unsigned index;	if (sortedKeys == 0) {	    /*	     * Detect deletion while iterating.	     * A legal deletion can only affect the current entry, so	     * adjust the current position to reflect the next entry was	     * moved.	     */	    if (mySArrayBody->deleted) {		numEntries --;		current --;	    }	    if (current == numEntries) {		return 0;	    }	    index = current++;	} else {	    if (current == numEntries) {		return 0;	    }	    /*	     * XXX: fake an SArray object to access locate()	     */	    SArray<KeyT,DataT> mySArray(0);	    mySArray.body = mySArrayBody;	    (void)mySArray.locate(sortedKeys[current++], index);	    mySArray.body = 0;	}	mySArrayBody->deleted = 0;	key = mySArrayBody->data[index].key;	return &(mySArrayBody->data[index].value);    }}#undef BODY#endif /* _SArray_cc_ */

⌨️ 快捷键说明

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