修改仅支持升序的插值搜索算法以适配降序排序数组
修改插值搜索算法以支持降序数组
没问题,我来帮你把这个只支持升序的插值搜索改成能处理降序数组的版本。原代码的核心逻辑是针对升序数组设计的,要适配降序,我们需要调整循环边界条件、插值位置计算公式和匹配后的指针移动规则这三个关键部分。
核心修改点拆解
- 循环边界条件:升序数组中,
array[low]是最小值,array[high]是最大值,所以key需要在[array[low], array[high]]区间内;但降序数组正好相反,array[low]是最大值,array[high]是最小值,所以key要满足[array[high], array[low]]。 - 插值位置计算:原公式是基于升序的差值比例,降序时需要反转分子分母的差值方向,避免计算出超出范围的pos值。
- 指针移动逻辑:升序中如果key大于
array[pos],说明目标在pos右侧;但降序中key大于array[pos]的话,目标应该在pos左侧,所以要调整low和high的移动方向。
修改后的完整代码
public static int Interpo(double[] array, double key, int order) { int low = 0, high = array.Length - 1; int pos = 0; int count = 0; while (low <= high) { count++; // 根据排序顺序调整插值位置计算 if (order == 0) { // 升序(假设0代表升序,1代表降序,可根据你的定义调整) // 原升序逻辑,先做边界检查 if (key < array[low] || key > array[high]) break; pos = Convert.ToInt32(low + (high - low) * (key - array[low]) / (array[high] - array[low])); // 调整指针 if (array[pos] == key) return pos; else if (array[pos] < key) low = pos + 1; else high = pos - 1; } else { // 降序 // 降序的边界检查:key不能大于array[low](最大值),也不能小于array[high](最小值) if (key > array[low] || key < array[high]) break; // 降序的插值公式:反转差值方向,保证pos计算正确 pos = Convert.ToInt32(low + (high - low) * (array[low] - key) / (array[low] - array[high])); // 降序的指针调整逻辑 if (array[pos] == key) return pos; // 降序中,key比当前pos值大,说明目标在pos左侧(因为左边元素更大) else if (array[pos] < key) high = pos - 1; // key比当前pos值小,目标在pos右侧 else low = pos + 1; } } // 未找到目标返回-1 return -1; }
关键细节说明
- 排序顺序标识:这里假设
order=0代表升序,order=1代表降序,你可以根据自己的需求修改这个标识规则。 - 边界检查的位置:把边界检查放到了分支内部,这样可以针对升序/降序分别做准确的判断,避免原代码中统一判断导致的降序场景错误。
- 插值公式的调整:降序时用
(array[low] - key)代替原升序的(key - array[low]),分母用(array[low] - array[high])(因为降序中array[low] > array[high],分母为正,保证比例计算正确)。 - 指针移动逻辑反转:降序场景下,当
array[pos] < key时,说明key比当前位置的值大,而数组是从左到右递减的,所以更大的值在pos左边,因此要把high移到pos-1;反之则移动low。
你可以用升序数组(比如[1.2,3.4,5.6,7.8])和降序数组(比如[7.8,5.6,3.4,1.2])分别测试,验证两种排序方向下都能正确找到目标值。
内容的提问来源于stack exchange,提问作者Craig
相关产品推荐
相关产品推荐

