17 插值查找

1 插入排序法思想

插值查找算法类似于二分查找,不同的是插值查找每次从自适应 mid 处开始查找。将折半查找中的求 mid 索引的公式 , low 表示左边索引 left, high 表示右边索引 right.key 就是前面我们讲的 findVal.

int mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left])

公式的由来:http://www.voycn.com/article/chazhaosuanfa-chazhichazhao

2 插入排序法的代码实现

package search;

/**
 * @author Andy
 * @email andy.gsq@qq.com
 * @date 2023/2/17 22:19:29
 * @desc 插值查找
 */

public class InsertValueSearch {
    public static void main(String[] args) {
        int arr[] = {1, 8, 10, 89, 1000, 1000, 1234};
        int findVal = 8;

        int index = insertValueSearch(arr, 0, arr.length - 1, findVal);
        System.out.print("查询的数组为: ");
        show(arr);
        System.out.println("查询的数为: " + findVal);
        System.out.println("查询的位置为: " + index);
    }

    public static int insertValueSearch(int[] arr, int left, int right, int findVal) {
        if (left > right || findVal < arr[0] || findVal > arr[arr.length - 1]) {
            return -1;
        }

        int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]);
        int midVal = arr[mid];
        if (midVal > findVal) {
            return insertValueSearch(arr, left, mid - 1, findVal);
        } else if (midVal < findVal) {
            return insertValueSearch(arr, mid + 1, right, findVal);
        } else {
            return mid;
        }
    }

    public static void show(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
}

插值排序(Interpolation Sort)是一种基于插值查找思想的排序算法。它通过插值公式估计数据的位置,从而减少数据移动的次数,提高排序效率。插值排序特别适用于数据分布较为均匀的情况,能够在接近线性时间内完成排序。 ### 原理 插值排序的核心思想是将数据分布假设为均匀分布,通过插值公式计算出目标元素的估计位置。在排序过程中,算法会将当前元素插入到估计位置附近,从而减少比较和移动的次数。插值排序通常与桶排序结合使用,也可以单独作为一种排序策略。 插值公式如下: $$ \text{pos} = \text{low} + \frac{(key - arr[low]) \times (high - low)}{arr[high] - arr[low]} $$ 其中: - `key` 是当前元素的值; - `low` 和 `high` 是当前待插入区间的起始和结束索引; - `arr` 是待排序数组。 ### 实现 以下是一个基于插值查找排序实现,展示了如何将插值查找的思想应用于排序过程: ```cpp #include <iostream> using namespace std; int interpolationSearch(int arr[], int key, int size) { int low = 0; int high = size - 1; while (low <= high && key >= arr[low] && key <= arr[high]) { int mid = low + ((key - arr[low]) * (high - low)) / (arr[high] - arr[low]); if (arr[mid] == key) return mid; if (arr[mid] < key) low = mid + 1; else high = mid - 1; } return -1; } void interpolationSort(int arr[], int size) { int* temp = new int[size]; int minVal = arr[0], maxVal = arr[0]; for (int i = 1; i < size; i++) { if (arr[i] < minVal) minVal = arr[i]; if (arr[i] > maxVal) maxVal = arr[i]; } for (int i = 0; i < size; i++) { int pos = (arr[i] - minVal) * (size - 1) / (maxVal - minVal); while (temp[pos] != 0) { pos++; } temp[pos] = arr[i]; } int index = 0; for (int i = 0; i < size; i++) { if (temp[i] != 0) arr[index++] = temp[i]; } delete[] temp; } int main() { int arr[] = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 }; int size = sizeof(arr) / sizeof(arr[0]); int key = 13; int index = interpolationSearch(arr, key, size); if (index != -1) cout << "Element found at index " << index << endl; else cout << "Element not found" << endl; // 测试插值排序 int unsorted[] = { 5, 2, 8, 1, 4 }; int n = sizeof(unsorted) / sizeof(unsorted[0]); interpolationSort(unsorted, n); cout << "Sorted array: "; for (int i = 0; i < n; i++) { cout << unsorted[i] << " "; } cout << endl; return 0; } ``` ### 算法分析 1. **时间复杂度**: - 在数据分布均匀的情况下,插值排序的时间复杂度可以接近 $ O(n) $。 - 最坏情况下(数据分布不均匀),时间复杂度为 $ O(n^2) $。 2. **空间复杂度**: - 插值排序通常需要额外的空间来存储排序后的数据,因此空间复杂度为 $ O(n) $。 3. **适用场景**: - 插值排序适用于数据分布均匀且数据量较大的场景。 - 它在查找排序过程中利用插值公式估计位置,减少了不必要的比较和移动。 ### 优缺点 - **优点**: - 在数据分布均匀的情况下,效率较高。 - 减少了不必要的比较和移动操作。 - **缺点**: - 对数据分布敏感,若数据分布不均匀,性能会显著下降。 - 需要额外的空间来存储排序结果。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值