1. 1 任意数据类型处理的设计方法
在数据结构与算法中,必然要涉及数据类型的问题,数据类型几乎是无限的集合,我们不可能为每种类型写一套代码,因此,要在一套代码中适应各种数据类型,C++的模板是一种实现方法。其实在C语言中,void指针也是一种很好的方法,它可以指向任意类型的数据,只要使用时做一个简单的类型强制转换就可以了。
当任意类型的数据都用void指针来表示时,由于不知道调用者会传什么类型的数据过来,因此,对数据的操作在数据结构与算法代码内部是不知道的,只有外部的调用者才知道数据类型和对数据操作的方法。在数据结构与算法中对数据的操作通常有以下几种方法。
① 数据的比较;
② 数据的资源释放;
③ 数据的访问操作;
④ 数据的拷贝操作;
⑤ 数据的一些其他计算操作。
当外部调用者调用数据结构与算法提供接口时,如果接口要用到对数据的操作,则必须由调用者将数据操作方法告诉接口。在C语言中,一般都是通过回调函数来实现。我们可以把上面的数据比较操作定义成如下回调函数。
/** 通用类型数据比较函数
@param void *pData1——要比较的第1个参数
@param void *pData2——要比较的第2个参数
@return INT——小于0表示pData1小于pData2;等于0表示pData1等于pData2;
大于0表示pData1大于pData2
*/
typedef INT (*COMPAREFUNC) ( void *pData1,void *pData2 );
比如在排序时,由于不知道数据类型,我们必须知道如何比较数据的大小。因此用户要定义一个比较函数。比较函数的原型与上面COMPAREFUNC函数指针的定义一样,调用排序函数时,将比较函数传给排序函数作为参数,这样,在排序函数里面就知道如何比较数据了。
1. 2 任意数据类型处理的实例
例1-3 设计一个简单的排序函数,排序的数据放在数组中,且数据类型可以是任意的。
void Sort( void **ppData,int nLen,COMPAREFUNC Compare)
{
int i,j;
void *pTemp;
for ( i = 0; i < nLen; i++ )
{
for ( j = i+1; j <nLen; j++ )
{
if ( (*Compare) (ppData[i],ppData[j] ) > 0 )
{
pTemp = ppData[j];
ppData[j] = ppData[i];
ppData[i] = pTemp;
}
}
}
}
例1-4 调用Sort()函数来排序一个字符串数组。
INT StrCmp( void *p1,void *p2)
{
return strcmp( (char *)p1,(char *)p2);
}
void main()
{
#define MSG_COUNT 6
char *pszMsg[MSG_COUNT] = {"ah","bee","sea","degree","chineses","quit"};
Sort( pszMsg,sizeof(pszMsg),StrCmp);
for ( int i = 0; i < MSG_COUNT; i++ )
{
printf("%s/n",pszMsg[i] );
}
}
1. 3 任意数据类型处理的回调函数封装
下面给出本书要用到的7个任意类型处理的回调函数定义。
/** 通用类型数据比较函数
@param void *pData1——要比较的第1个参数
@param void *pData2——要比较的第2个参数
@return INT—— 小于0表示pData1小于pData2;等于0表示pData1等于pData2;
大于0表示pData1大于pData2
*/
typedef INT (*COMPAREFUNC) ( void *pData1,void *pData2 );
/** 通用类型数据释放函数
@param void *pData——要释放的数据
@return——无
*/
typedef void (*DESTROYFUNC) ( void *pData );
/** 通用类型数据的遍历执行函数
@param void *pData——要操作的数据指针
@return void——无
*/
typedef void (*TRAVERSEFUNC)( void *pData);
/** 通用类型数据的遍历执行函数
@param void *pData——要操作的数据指针
@return void——无
*/
typedef INT (*VISITFUNC)(void *pData);
/** 通用数据拷贝函数
@param void *pData——要拷贝的数据
@return void *——成功返回拷贝的数据,失败返回NULL
*/
typedef void *(*COPYFUNC)(void *pData);
/** 基数排序的获取关键字转换成序号的函数
@param void *pData——关键字指针
@param UINT *uKeyIndex——关键字的位数
@return UINT——关键字转换后的序号
*/
typedef UINT (*GETKEYFUNC)( void *pData,UINT uKeyIndex );
/** 计算哈希值的回调函数
@param void *pKey——要计算哈希值的关键词
@param UINT uBucketNum——哈希表中的bucket数组大小
@return UINT——返回计算出的哈希值,一般用作哈希表bucket数组下标
*/
typedef UINT (*HASHFUNC)(void *pKey,UINT uBucketNum)。