基于链表法的Hash算法简易实现

因项目需要,为了查找更快,通过输入pt,port两个数字,读取与之对应的Cos。Hash算法的精髓在于hash函数的设计,在此,我只简单地设计实现了一下。同时针对传入不同值得到相同的key,通过链表法解决:

#include "nl_common.h"       //自己项目里的.h文件

typedef struct _node
{
    U8 pt;
    U16 port;
    U8 Cos;
    struct _node *next;
}node;

void hash_insert(U8 pt, U16 port, U8 Cos);
int find_key(U8 pt, U16 port);

char fname[] = "/home/root/classifier";

int node_num = 0;
int mod_num;
node * hashTab;

int flag = 0;



#define BigLittleSwap16(A)  ((((uint16)(A) & 0xff00) >> 8) | (((uint16)(A) & 0x00ff) << 8))



int checkCPUendian()

{

       union{

              unsigned long int i;

              unsigned char s[4];

       }c;



       c.i = 0x12345678;

       return (0x12 == c.s[0]);

}






unsigned short int HtoNs(unsigned short int h)

{



       return checkCPUendian() ? h : BigLittleSwap16(h);

}



int file_len()
{
    FILE *fp_port = NULL;
    char c;
    int j = 0;
    int len = 0;

    fp_port = fopen(fname, "r");
    if (NULL == fp_port)
    {
        EPT(stderr,"file: %s does't exist\n", fname);
        return -1;
    }
    else
    {
        while((c = fgetc(fp_port)) != EOF)
        {
            j = (int)(c);
            EPT(stderr,"@ j: '%d'\n",j);
            if(j == 255)
                break;
            EPT(stderr,"! read : '%c'\n", c);

            if(c == '\n')
            {
                len++;
            }
        }
        node_num = len * 2;
        EPT(stderr,"the size of file is %d\n", len);
        if(len == 0)
        {
            EPT(stderr,"file: %s does't have word\n", fname);
            return 0;
        }
        return 1;
    }
    fclose(fp_port);

}

void find_max_prime()
{
    int i;
    int x = node_num;
    while(x > 1)
    {
        for(i = 2; i < x; i++)
        {
            if(x % i == 0)
            {
                x --;
                break;
            }
        }
        if( i == x)
            break;
    }
    mod_num = x;
    EPT(stderr,"mode_num: %d\n", mod_num);
}

int read_file()
{
    int rval = 0;
    FILE *fp_port = NULL;



    fp_port = fopen(fname, "r");
    if (NULL == fp_port)
    {
        rval = 1;
        goto fexit;
    //  printf("~~~~~~does not exist file:%s\n",fname);

    }
    else
    {
        while(!feof(fp_port))
        {
            int pt;
            int port;
            int Cos;

            fscanf(fp_port, "%d %d %d", &pt, &port, &Cos);
            EPT(stderr,"%d %d %d (%hhu %hu %hhu)\n", pt, port, Cos, pt, port, Cos);

            if(!feof(fp_port))
        //  printf("%d, %d, %d\n", pt, port, Cos);
            {
                hash_insert((U8)pt, (U16)HtoNs(port), (U8)Cos);
            }

            rval = 2;

        }
    }
fexit:
    if (NULL != fp_port)
        fclose(fp_port);
    return rval;
}

void hash_insert(U8 pt, U16 port, U8 Cos)
{
    int key;
    key = find_key(pt, port);

    if(hashTab[key].Cos == 255)
    {
        EPT(stderr,"key:%d\n", key);

        hashTab[key].pt = pt;
        hashTab[key].port = port;
        hashTab[key].Cos = Cos;
    }
    else
    {
        node *temp;
        node *new_node = (node *)calloc(1, sizeof(node));

        new_node->pt = pt;
        new_node->port = port;
        new_node->Cos = Cos;
        new_node->next = NULL;

        temp = &hashTab[key];

        for(; temp->next != NULL; temp = temp->next)
            printf("   ");
        EPT(stderr,"key:%d\n", key);

        temp->next = new_node;
    }

}

int find_key(U8 pt, U16 port)
{
    int key;
    key = ( pt + (pt<<5) + port ) % mod_num;
    return key;
}

void init_hash()
{
    int i;
    for( i = 0; i < node_num; i++)
    {
        hashTab[i].pt = 0;
        hashTab[i].port = 0;
        hashTab[i].Cos = -1;
        hashTab[i].next = NULL;
    }
}

void show_hash()
{
    int i;


    for(i = 0; i < node_num; i++)
    {
        int num = 1,j;
        char str[] = "   ";

        EPT(stderr,"hashTab[%d] -> pt: %hhu, port: %hu, Cos: %hhu\n", i, 
            hashTab[i].pt, hashTab[i].port, hashTab[i].Cos);

        node * temp = &hashTab[i];
        while(temp->next != NULL)
        {
            temp = temp->next;


            for(j = num ; j > 0; j--)
            {
                printf("%s", str);
            }
            num++;
            EPT(stderr,"next -> pt: %hhu, port: %hu, Cos: %hhu\n",
             temp->pt, temp->port, temp->Cos);
        }
    }
}

U8 find_Cos(U8 pt, U16 port)
{
    int key;
    key = find_key(pt, port);

    EPT(stderr, "~ find key: %d(%hhu)(pt: %hhu ,port: %hu)\n", key, key, pt, port);

    if(flag)
        return -1;

    if(hashTab[key].Cos == 255)
    {
        return -1;
    }
    else
    {

        node *temp;

        temp = &hashTab[key];
        do
        {
            if( (temp->pt == pt) && (temp->port == port) )
                return (temp->Cos);
            temp = temp->next;
        }
        while(temp != NULL);
    }

}

int init_nl_hash()
{
    int rval;

    if( file_len() == 1)
    {
        find_max_prime();   

        hashTab = (node*)calloc(node_num, sizeof(node));

        init_hash();

        show_hash();
        read_file();

        show_hash();  
        return 1;   
    }
    flag = 1;
    return 0;


}


/*//for test
void main()
{
    int i;
    file_len();
    find_max_prime();   

    hashTab = (node*)calloc(node_num, sizeof(node));
    init_hash();

    show_hash();
    read_file();

    show_hash();

    int pt_temp, port_temp;

    for(i = 0; i < 5; i++)
    {
        fscanf(stdin, "%d %d", &pt_temp, &port_temp);
        printf("pt:%d, port:%d, Cos:%d\n", pt_temp,port_temp,find_Cos(pt_temp,HtoNs(port_temp)));
    }


    free(hashTab);  //这里只free(hashTab)肯定不行,还需要把next指针非NULL的也释放掉
                    //因为测试时候需要,项目中不需要了,就没完善。
}
*/


其中有一点需要注意:
在 file_len() 函数中,加入了:

            j = (int)(c);
            EPT(stderr,"@ j: '%d'\n",j);
            if(j == 255)
                break;

本来在电脑上模拟测试时候,通过EOF标识符可以判断文件结束,但是到板子上,通过ps命令发现该进程一直在执行,通过打印语句才发现原来while()语句一直在读,读出的数为255,

EOF 定义的为-1,转换为int为255,所以读出的为255可以解释。

但是为何通过EOF编制为来判断getchar()不行还未想通。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值