基本查找算法

本文介绍了三种常用的数据查找算法:顺序查找、二分查找和哈希表查找。顺序查找适用于无序数据,时间复杂度为O(n);二分查找适用于有序数据,时间复杂度为O(logn);哈希表查找通过哈希函数实现快速查找,平均时间复杂度为O(1),并讨论了哈希冲突的解决方法。示例代码展示了哈希表的创建、插入和查找操作。
摘要由CSDN通过智能技术生成

一、顺序查找

适用于查找无序数据,时间复杂度为O(n).

算法过程:从一端开始逐元素与给定的key值比较。

1、 无哨兵的算法

int SeqSearch(int *arr, int length, int key)
{
    for(int i=0; i<length; --i)
    {
        if(arr[i] == key)
        {
            return i;
        }        
    }
    return -1; //查找失败则返回-1
}

2、有哨兵的算法

int SeqSearch(int *arr, int length, int key)
{
    arr[0] = key; //0号位置不保存数据,作为哨兵使用
    int i;
    for(i=length; arr[i] != key; --i)
    {
        ;
    }
    return i; //返回查找结果,查找失败则返回0
}

有哨兵的算法的优势:在每次循环中都要少一次对下标是否越界的判断,时间效率有所提高。

二、二分查找

适用于有序排列,时间复杂度为O(logn).

算法过程:先取位于序列中间的元素,将其与查找键key比较。如果它们的值相等,则找到。否则将查找区间缩小一半。

假定数据按升序排列:

int BinarySearch(int *arr, int length, int key)
{
    int left=0, right=length-1, mid;
    while(left <= right)
    {
        mid = left + (right - left)/2;
        if( key == arr[mid])
        {
            return mid;
        }
        else if(key < arr[mid])
        {
            right = mid - 1;
        }
        else
        {
            left = mid + 1;
        }
    } // end of while
    return -1; //查找失败返回-1
}

注:在计算mid时,使用mid = left + (right - left)/2,而不用mid = (left + right)/2。因为left与right之和可能超过int极限值,发生数值溢出,所以使用减法代替加法。

三、哈希表查找

哈希表实际上是一个具有固定大小的数组,其中每条记录的存储位置和它的关键字之间有一个确定的映射关系(哈希函数)。哈希表查找、插入、删除的平均时间复杂度为O(1)。

哈希冲突:不同的关键字经过哈希函数映射后得到相同哈希地址的现象。产生原因:关键字的取值范围大于表长。

1、哈希函数

采用最简单最常用的除数取余法。

int hash(int key)
{
    return key % HASHTABLESIZE;
}

2、解决哈希冲突

以链地址法为例。哈希表中存放的是产生冲突的所有关键字构成的单链表的表头。

(1)、哈希表结构

#include<stdio.h>
#include<stdlib.h>
#define HASHTABLESIZE 11

typedef struct tagHashNode
{
    int data;
    struct tagHashNode *next;

} HashNode, *HashTable;

HashTable hashTable[HASHTABLESIZE];

(2)、哈希表初始化

void initHashTable(HashTable *hashTable)
{
    for(int i=0; i<HASHTABLESIZE; ++i)
    {
        hashTable[i] = NULL;
    }
}

(3)、哈希表插入

算法过程:根据哈希函数求出关键字key的哈希地址。若该地址为空,则直接插入该节点。否则,遍历单链表到尾节点,再插入。

int insertHashTable(HashTable *hashTable, int key)
{
    int index = hash(key);

    HashNode *newNode = (HashNode *)malloc(sizeof(HashNode));
    if(newNode == NULL)
    {
        return -1;//内存申请失败
    }
    newNode->data = key;
    newNode->next = NULL;

    if(hashTable[index] == NULL)
    {
        hashTable[index] = newNode;
    }
    else
    {
        HashNode *pTempNode = hashTable[index];
        while( pTempNode->next != NULL)
        {
            pTempNode = pTempNode->next;
        }
        pTempNode->next = newNode;
    }
    return 0;
}

(4)、哈希表查找

算法过程:根据哈希函数求得关键key对应的哈希地址。若该地址为空,则查找失败。否则,遍历单链表并比较key与节点中的值。若找到则将数据用node取回。

int searchHashTable(const HashTable *hashTable, int key, HashNode *node)
{
    int index = hash(key);

    HashNode *pTempNode = hashTable[index];

    while(pTempNode != NULL )
    {
        if(pTempNode->data == key)
        {
            *node = *pTempNode;
            return 0;
        }
        pTempNode = pTempNode->next;
    }

    return -1;//查找失败
}

完整代码如下:

#include<stdio.h>
#include<stdlib.h>
#define HASHTABLESIZE 11
typedef struct tagHashNode
{
    int data;
    struct tagHashNode *next;

} HashNode, *HashTable;


int hash(int key)
{
    return key % HASHTABLESIZE;
}

void initHashTable(HashTable *hashTable)
{
    for(int i=0; i<HASHTABLESIZE; ++i)
    {
        hashTable[i] = NULL;
    }
}


int insertHashTable(HashTable *hashTable, int key)
{
    int index = hash(key);

    HashNode *newNode = (HashNode *)malloc(sizeof(HashNode));
    if(newNode == NULL)
    {
        return -1;//内存申请失败
    }
    newNode->data = key;
    newNode->next = NULL;

    if(hashTable[index] == NULL)
    {
        hashTable[index] = newNode;
    }
    else
    {
        HashNode *pTempNode = hashTable[index];
        while( pTempNode->next != NULL)
        {
            pTempNode = pTempNode->next;
        }
        pTempNode->next = newNode;
    }
    return 0;
}


void showHashTable(HashTable *hashTable)
{
    HashNode *pTempNode = NULL;
    for(int i=0; i<HASHTABLESIZE; ++i)
    {
        printf("index: %d\n",i);

        pTempNode = hashTable[i];

        if(pTempNode == NULL)
        {
            printf("NULL\n\n");
            continue;
        }

        while(pTempNode != NULL )
        {
            printf("%d ", pTempNode->data);
            pTempNode = pTempNode->next;
        }
        printf("\n\n");

    }// end of for
}

int searchHashTable(const HashTable *hashTable, int key, HashNode *node)
{
    int index = hash(key);

    HashNode *pTempNode = hashTable[index];

    while(pTempNode != NULL )
    {
        if(pTempNode->data == key)
        {
            *node = *pTempNode;
            return 0;
        }
        pTempNode = pTempNode->next;
    }

    return -1;//查找失败
}

void test()
{
    /* code */
    int arr[10] = {0,1,4,9,16,25,36,49,64,81};
    HashTable hashTable[HASHTABLESIZE];
    initHashTable(hashTable);
    for(int i=0; i<10; i++)
    {
        insertHashTable(hashTable, arr[i]);
    }

    showHashTable(hashTable);

    HashNode node;
    int status;
    int key = 3;
    status = searchHashTable(hashTable, key, &node);
    printf("Try to find the key:%d, ", key);
    if(status == 0)
    {
        printf("and successful!\n", node.data);
    }
    else{
        printf("but failed!\n");
    }

    key = 49;
    status = searchHashTable(hashTable, key, &node);
    printf("Try to find the key:%d, ", key);
    if(status == 0)
    {
        printf("and successful!\n", node.data);
    }
    else{
        printf("but failed!\n");
    }

}
int main(int argc, char const *argv[])
{
    test();
    return 0;
}

运行结果:

index: 0
0 

index: 1
1 

index: 2
NULL

index: 3
25 36 

index: 4
4 81 

index: 5
16 49 

index: 6
NULL

index: 7
NULL

index: 8
NULL

index: 9
9 64 

index: 10
NULL

Try to find the key:3, but failed!
Try to find the key:49, and successful!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值