#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//键索引计数法
#define KEY_BASE 5
typedef struct
{
char *pString; //条目字符串内容
int key; //条目的归类键值,比如张三属于1类等
} S_ELEMENT;
//键索引计数法关键流程
//1、频率统计
//2、将频率转换为索引
//3、数据分类
//4、回写
void keyIndex(S_ELEMENT array[], int arrayCount, int keyBase)
{
int i = 0;
int *pCount = NULL;
S_ELEMENT *pAux = NULL;
//分配计数资源
//keyBase是键值基数,比如当前测试程序的分类键值范围是0~4,则是键键基数为5
//这里在分配资源时会加1,主要为第2步算法做准备,细节在下面说明。
pCount = (int *)malloc(sizeof(int) * (keyBase + 1));
if ( pCount == NULL )
{
goto KEY_INDEX_EXIT;
}
memset(pCount, 0, sizeof(int) * (keyBase + 1));
//分配辅助数据资源
pAux = (S_ELEMENT *)malloc(sizeof(S_ELEMENT) * arrayCount);
if ( pAux == NULL )
{
goto KEY_INDEX_EXIT;
}
memset(pAux, 0, sizeof(S_ELEMENT) * arrayCount);
//1、频率统计,即统计同分类键的条目数
//这里不使用数组索引0,而是从索引1开始,即分类键0的统计放在数组索引1处,
//分类键1的统计放在数组索引2处,主要为第2步算法做准备,细节在下面说明。
for ( i = 0; i < arrayCount; i++ )
{
pCount[array[i].key + 1]++;
}
//2、将频率转换为索引,其作用就是根据不同分类键的个数,依次得到不同分
//类键的起始索引。
//比如第0分类的条目数为6个,第1分类的条目数为8个,则pCount[0]最终值为0,
//pCount[1]最终值为6,pCount[2]最终值为14
//
//000000111111112...
//^ ^ ^
//| | |
//p[0] p[1] p[2]
//
//之前在上面分配资源及进行统计时都从索引1开始进行处理,主要是用于方便这
//一步算法流程,因为第0分类的起始索引一定为0,所以在这一步算法中直接从
//分类1开始处理,比如当前i为0,pCount[0]记载了分类0的起始索引,pCount[1]
//原值记载了分类0的条目数,pCount[1] = pCount[1] + pCount[0]则表示了此
//时分类1的起始索引就是分类0的起始索引加上分类0的条目数。
for ( i = 0; i < keyBase; i++ )
{
pCount[i+1] += pCount[i];
}
//3、数据分类,根据第2步pCount记载的统计排序后每个分类的起始索引位置,将
//原始数据依次存储到临时数组正确的位置。
for ( i = 0; i < arrayCount; i++ )
{
int index = pCount[array[i].key]++;
memcpy(&pAux[index], &array[i], sizeof(S_ELEMENT));
}
//4、回写,最终将排序好的临时数组在写入原数组中。
memcpy(array, pAux, sizeof(S_ELEMENT) * arrayCount);
KEY_INDEX_EXIT:
if ( pCount != NULL )
{
free(pCount);
}
if ( pAux != NULL )
{
free(pAux);
}
}
void dumpArray(S_ELEMENT array[], int arrayCount)
{
int i = 0;
for ( i = 0; i < arrayCount; i++ )
{
printf("[%03d] string %-10s, key %d\r\n", \
i, array[i].pString, array[i].key);
}
}
int main()
{
S_ELEMENT array[] = {
{ "Anderson", 2},
{ "Brown", 3},
{ "Davis", 3},
{ "Garcia", 4},
{ "Harris", 1},
{ "Jacksn", 3},
{ "Jones", 4},
{ "Martin", 3},
{ "Martinez", 1},
{ "Miller", 2},
{ "Moore", 0}
};
int arrayCount = sizeof(array) / sizeof(array[0]);
keyIndex(array, arrayCount, KEY_BASE);
dumpArray(array, arrayCount);
return 0;
}
键索引计数法
最新推荐文章于 2023-08-15 20:36:35 发布