目录
本文章只介绍了折半查找、插值查找和斐波那契查找
一、折半查找
折半查找,也叫二分查找,是一种针对有序数组的查找算法。它的基本思想是,将有序数组分成两部分,取中间位置的元素与目标元素进行比较,如果相等则返回中间位置的下标,如果中间元素小于目标元素,则在右半部分继续查找,如果中间元素大于目标元素,则在左半部分继续查找,直到找到目标元素或者整个数组被查找完毕。
折半查找的时间复杂度为 O(log n),其中 n 表示数组的长度。它的效率比线性查找高很多,适用于数据量比较大的有序数组中查找某个元素的位置。折半查找的缺点是需要先对数组进行排序,而排序本身的时间复杂度可能比查找更高,因此如果需要多次查找同一个数组中的元素,建议先进行排序,然后使用折半查找来提高效率。
// 折半查找函数,返回目标元素在有序数组中的下标,若未找到则返回 -1
int binarySearch(int arr[], int n, int target) {
int left = 0; // 左边界
int right = n - 1; // 右边界
while (left <= right) { // 只要左右边界没有相遇
int mid = left + (right - left) / 2; // 计算中间位置的下标
if (arr[mid] == target) { // 中间元素等于目标元素
return mid; // 返回中间元素的下标
} else if (arr[mid] < target) { // 中间元素小于目标元素
left = mid + 1; // 缩小左边界
} else { // 中间元素大于目标元素
right = mid - 1; // 缩小右边界
}
}
return -1; // 没有找到目标元素,返回 -1
}
二、插入查找
插值查找是一种针对有序数组的查找算法,它是基于二分查找的改进版。插值查找的原理是,根据目标元素在有序数组中的位置,通过插值公式计算出目标元素的大致位置,然后在计算得到的位置处进行查找。插值公式如下:
其中,left 表示左边界,right 表示右边界,target 表示目标元素,arr 表示有序数组,pos 表示插值位置。
插值查找的时间复杂度为 O(log(log n)),其中 n 表示数组的长度。它的效率比二分查找高,尤其是在数据分布比较均匀的情况下。但是,如果数据分布不均匀,插值查找的效率可能会比较低,甚至比二分查找还慢。适用于比较均匀的查找表。
// 插值查找函数,返回目标元素在有序数组中的下标,若未找到则返回 -1
int interpolationSearch(int arr[], int n, int target) {
int left = 0; // 左边界
int right = n - 1; // 右边界
while (left <= right && arr[left] <= target && arr[right] >= target) {
// 计算插值
int pos = left + (target - arr[left]) * (right - left) / (arr[right] - arr[left]);
if (arr[pos] == target) { // 中间元素等于目标元素
return pos; // 返回中间元素的下标
} else if (arr[pos] < target) { // 中间元素小于目标元素
left = pos + 1; // 缩小左边界
} else { // 中间元素大于目标元素
right = pos - 1; // 缩小右边界
}
}
return -1; // 没有找到目标元素,返回 -1
}
三、斐波那契查找
斐波那契查找是一种针对有序数组的查找算法,它是在二分查找的基础上进行改进,利用斐波那契数列来确定查找区间的位置。
斐波那契数列是指这样一个数列:0、1、1、2、3、5、8、13、21、34、……,这个数列从第三项开始,每一项都是前两项之和。斐波那契数列的特点是,在数列中的每一个数,都等于前面两个数的和。
斐波那契查找的基本思想是:将查找区间划分为两个长度为斐波那契数列中相邻的两个数的子区间,然后利用斐波那契数列中的值来确定中间位置的下标,将数组分成左右两个部分。如果待查找的元素小于中间位置的元素,则在左部分继续查找;如果大于中间位置的元素,则在右部分继续查找;否则,中间位置的元素就是要查找的元素。
与二分查找不同的是,斐波那契查找的划分点不是中间点,而是根据斐波那契数列中的值来确定的。在斐波那契数列中,相邻两个数之间的比值越来越接近黄金分割数值(约为1.618),因此使用斐波那契数列来划分查找区间可以更加高效地找到目标元素。
斐波那契查找的时间复杂度为 O(log n),效率较高。但需要注意的是,斐波那契查找要求查找的数组必须是有序的,并且要求数组长度为斐波那契数列中的某个值。如果不满足这些条件,则需要将数组扩展到满足条件的长度,这会增加算法的时间和空间复杂度。
//斐波那契查找,利用黄金分割原理
int Fiboanacci_Search(int* a, int n, int key)
{
int low, high, mid;
int k;
int F[10]; //暂存10个斐波那契数
F[0] = 0;
F[1] = 1;
for (int i = 2; i < 10; i++) //斐波那契数组
F[i] = F[i - 1] + F[i - 2];
k = 0;
while (n > F[k]) //求斐波那契数组中与n最接近的略大于n的数
k++;
for (int i = n - 1; i < F[k] - 1; i++) //补全查找序列
a[i] = a[n-1];
low = 0;
high = n - 1;
while (low <= high)
{
mid = low + F[k - 1] - 1;
if (key < a[mid])
{
high = mid - 1;
k = k - 1;
}
else if (key > a[mid])
{
low = mid + 1;
k = k - 2;
}
else
{
if (mid < n - 1)
return mid;
else
return n - 1;
}
}
return -1;
}
总结
以上为排序的简单算法,本人小白,主要用来记录,如有错误,欢迎大佬们指点出来。