电子说
4、斐波那契查找
4.1、基本原理
斐波那契查找算法(Fibonacci Search Algorithm)是一种利用斐波那契数列长度的有序数组进行查找的算法。与二分查找不同,斐波那契查找每次的查找范围是斐波那契数列中的某一段,从而更加高效地进行查找。
具体来说,假设待查找的数组为arr,数组长度为n。斐波那契查找首先要确定一个斐波那契数列fib,满足fib[k] >= n,且fib[k-1] < n。然后根据当前查找范围的左右端点计算mid = left + fib[k-1],即查找范围中点的位置。如果arr[mid] == target,则查找成功;如果arr[mid] < target,则在mid的右侧继续查找;如果arr[mid] > target,则在mid的左侧继续查找。查找的过程类似于二分查找,只不过查找范围不是一半,而是根据斐波那契数列划分的一段。
斐波那契查找的优点是可以在O(log n)的时间内完成查找,比一般的线性查找O(n)和二分查找O(log n)更快。但是需要注意的是,斐波那契查找算法只适用于元素数量比较大、分布均匀的数组。对于元素数量较少或分布不均的数组,效率并不一定比其他算法高。
4.2、代码示例
方法一:
假设需要查找的元素为key,数组为arr,数组长度为n
#include
#include
// 斐波那契查找算法
int fib_search(int arr[], int n, int key) {
// 初始化斐波那契数列
int fib1 = 0;
int fib2 = 1;
int fibn = fib1 + fib2;
// 找到斐波那契数列中第一个大于等于n的数
while (fibn < n) {
fib1 = fib2;
fib2 = fibn;
fibn = fib1 + fib2;
}
// 对数组进行扩展,使其长度为斐波那契数列中的某个数
int *tmp = (int *)malloc(fibn * sizeof(int));
for (int i = 0; i < n; i++) {
tmp[i] = arr[i];
}
for (int i = n; i < fibn; i++) {
tmp[i] = arr[n - 1];
}
// 开始查找
int low = 0;
int high = fibn - 1;
int mid;
while (low <= high) {
// 计算当前中间位置
mid = low + fib1 - 1;
// 如果key比当前位置的值小,则在左侧继续查找
if (key < tmp[mid]) {
high = mid - 1;
fibn = fib1;
fib1 = fib2 - fib1;
fib2 = fibn - fib1;
}
// 如果key比当前位置的值大,则在右侧继续查找
else if (key > tmp[mid]) {
low = mid + 1;
fibn = fib2;
fib1 = fib1 - fib2;
fib2 = fibn - fib1;
}
// 找到了key
else {
// 如果当前位置小于n,则返回该位置,否则返回n-1
if (mid < n) {
return mid;
} else {
return n - 1;
}
}
}
// 没有找到key
free(tmp);
return -1;
}
// 测试代码
int main() {
int arr[] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
int n = sizeof(arr) / sizeof(arr[0]);
int key = 7;
int index = fib_search(arr, n, key);
if (index == -1) {
printf("The key %d is not found.\\n", key);
} else {
printf("The key %d is found at index %d.\\n", key, index);
}
return 0;
}
注意:上述代码假设数组中的元素是按照从小到大的顺序排列的。如果数组中的元素是无序的,则需要先对数组进行排序,然后再进行斐波那契查找。
方法二:
#include
// 获取斐波那契数列,n表示数列中第n个元素的值
int getFibonacci(int n) {
if (n <= 0) return 0;
if (n == 1) return 1;
return getFibonacci(n-1) + getFibonacci(n-2);
}
// 斐波那契查找算法,a为有序数组,n为数组长度,key为要查找的元素
int fibonacciSearch(int a[], int n, int key) {
int low = 0, high = n-1, k = 0, mid = 0;
// 计算斐波那契数列中第k个数刚好大于n
while (n > getFibonacci(k)-1) {
k++;
}
// 将数组扩展到斐波那契数列中第k个数的长度
int *temp = new int[getFibonacci(k)];
for (int i = 0; i < n; i++) {
temp[i] = a[i];
}
for (int i = n; i < getFibonacci(k); i++) {
temp[i] = a[n-1];
}
// 二分查找
while (low <= high) {
mid = low + getFibonacci(k-1) - 1;
if (key < temp[mid]) {
high = mid - 1;
k--;
} else if (key > temp[mid]) {
low = mid + 1;
k -= 2;
} else {
if (mid < n) {
return mid;
} else {
return n - 1;
}
}
}
delete [] temp;
return -1;
}
int main() {
int a[] = {1, 3, 5, 7, 9, 11, 13};
int n = sizeof(a) / sizeof(a[0]);
int key = 11;
int pos = fibonacciSearch(a, n, key);
if (pos >= 0) {
printf("元素 %d 在数组中的位置为 %d\\n", key, pos);
} else {
printf("元素 %d 在数组中不存在\\n", key);
}
return 0;
}
在这段代码中,我们首先使用 getFibonacci
函数获取斐波那契数列中第k个数,然后将数组 a
扩展到斐波那契数列中第k个数的长度,这样做是为了保证数组长度大于等于斐波那契数列中第k个数,从而可以用斐波那契数列中的数作为分割点进行查找。最后,我们使用二分查找的方式进行查找,最终返回查找结果的下标或者-1表示查找失败。
5、哈希查找
5.1、基本原理
哈希查找是一种常用的查找算法,它的基本思想是将数据元素映射到一个固定的存储位置,从而实现快速的查找。哈希查找的基本原理是利用哈希函数将关键字映射到存储位置,当需要查找一个元素时,先通过哈希函数计算出该元素对应的存储位置,然后在该位置进行查找。
哈希函数是哈希查找的关键,它将关键字映射到一个存储位置。哈希函数应该具有良好的映射性能,能够均匀地将关键字分布到不同的存储位置上,这样可以避免冲突。冲突是指多个关键字映射到同一个存储位置上,这种情况下需要解决冲突。
哈希查找的注意事项包括以下几点:
5.2、代码示例
下面是一个简单的哈希查找算法的代码示例,使用了线性探测法解决冲突。
#include
#include
#define TABLE_SIZE 13
typedef struct HashNode {
int key;
int value;
} HashNode;
typedef struct HashTable {
HashNode *table[TABLE_SIZE];
} HashTable;
int hash(int key) {
return key % TABLE_SIZE;
}
HashTable* createHashTable() {
HashTable *hashTable = (HashTable*)malloc(sizeof(HashTable));
for (int i = 0; i < TABLE_SIZE; i++) {
hashTable->table[i] = NULL;
}
return hashTable;
}
void insert(HashTable *hashTable, int key, int value) {
HashNode *node = (HashNode*)malloc(sizeof(HashNode));
node->key = key;
node->value = value;
int index = hash(key);
while (hashTable->table[index] != NULL) {
index = (index + 1) % TABLE_SIZE;
}
hashTable->table[index] = node;
}
int search(HashTable *hashTable, int key) {
int index = hash(key);
while (hashTable->table[index] != NULL && hashTable->table[index]->key != key) {
index = (index + 1) % TABLE_SIZE;
}
if (hashTable->table[index] == NULL) {
return -1;
} else {
return hashTable->table[index]->value;
}
}
void delete(HashTable *hashTable, int key) {
int index = hash(key);
while (hashTable->table[index] != NULL && hashTable->table[index]->key != key) {
index = (index + 1) % TABLE_SIZE;
}
if (hashTable->table[index] != NULL) {
free(hashTable->table[index]);
hashTable->table[index] = NULL;
}
}
int main() {
HashTable *hashTable = createHashTable();
insert(hashTable, 3, 100);
insert(hashTable, 9, 200);
insert(hashTable, 6, 300);
insert(hashTable, 12, 400);
int value = search(hashTable, 9);
printf("Value: %d\\n", value);
delete(hashTable, 9);
value = search(hashTable, 9);
printf("Value: %d\\n", value);
return 0;
}
该代码实现了一个基于线性探测法的哈希查找算法,其中 HashTable
表示哈希表,HashNode
表示哈希表中的一个节点,包括键 key
和值 value
,hash
函数用于计算哈希值,createHashTable
函数用于创建一个新的哈希表,insert
函数用于在哈希表中插入一个节点,search
函数用于在哈希表中查找指定的键,并返回对应的值,delete
函数用于从哈希表中删除指定的键。
全部0条评论
快来发表一下你的评论吧 !