Algorithm4——有序向量查找
来源:互联网 发布:网络高清硬盘播放机 编辑:程序博客网 时间:2024/05/16 09:16
本系列算法实现都是在学习数据结构(C++语言版),清华大学邓俊辉教授编,听邓老师edX网课过程中自己实现的例子。
问题: 对有序向量中某一个元素的查找,并返回其位置?
解决: 用三种算法实现
- 二分查找
- Fibonacci查找
- 插值查找
1 二分查找
二分查找的原理很简单,分治的思想,此处用迭代和递归两种方法
算法复杂度为O(1.5logN)
1.1 迭代版本
//! array is already sorted by <//! [low, high)//! o(1.5*logn) 查找过程并不平衡,因为向左、向右两个分支所需要的比较次数不相等template <typename T, typename V>int search_binary(T array, int low, int high , V const& elem){ int mid; while (low < high) { mid = (low + high) >> 1;//divided分治 if (array[mid] > elem) //compare 1 high = mid; else if (array[mid] < elem)//compare 2 low = mid + 1; else return mid;//compare 3 } return -1;}
1.2 递归版本
//! array is already sorted by <//! [low, high)//! o(1.5*logn) 查找过程并不平衡,因为向左、向右两个分支所需要的比较次数不相等template <typename T, typename V>int search_binary_recursion(T array, int low, int high , V const& elem){ int mid; while (low < high) { mid = (low + high) >> 1; if (array[mid] > elem) //compare 1 return search_binary_recursion(array, low, mid, elem); else if (array[mid] < elem) //compare 2 return search_binary_recursion(array, mid + 1, high, elem); else return mid;//compare 3 } return -1;}
2 Fibonacci查找
Fibonacci查找相比二分查找在算法复杂度的常系数上进行了优化。
Fibonacci查找算法复杂度推导过程如下图,字写得乱,海涵……
具体推导请看第二章 向量(下(d3)有序向量:Fibonacci查找 02D3-4: 最优性
算法复杂度为O(1.44logN)
二者区别是选取轴点mid的方式不同。
二分查找
mid = (low + high) >> 1;
Fibonacci查找
mid = low + fib.get_cur() - 1; //确定形如fib(k) - 1的轴点
代码实现如下,其中用到的Fibonacci类实现在文章Algorithm2——斐波那契数列的最下面。
//! array is already sorted by <//! [low, high)//! o(1.44*logn)//! search_fibonacci()与search_binary()区别二者选取轴点mid的方式不同template <typename T, typename V>int search_fibonacci(T array, int low, int high , V const& elem){ int mid; Fibonacci fib(high - low); while (low < high) { while ( high - low < fib.get_cur()) fib.get_pre(); //通过向前顺序查找 mid = low + fib.get_cur() - 1; //确定形如fib(k) - 1的轴点 if (array[mid] > elem) //compare 1 high = mid; else if (array[mid] < elem)//compare 2 low = mid + 1; else return mid;//compare 3 } return -1;}
3 插值查找
插值查找的核心是根据元素增长分布的特性使得能够更快的找到mid位置,此算法的复杂度为O(loglogN)
公式如下
其中在数组A[low, high),查找的元素值为elem,mid是插值后计算得到的中间值。
写成C++代码就是
mid = (1.0f * (elem - array[low]) / (array[high - 1] - array[low]) * (high - 1 - low) + low);
代码实现如下
//! array is already sorted by <//! [low, high)//! O(loglogN)template <typename T, typename V>int search_interpolation(T array, int low, int high , V const& elem){ int mid; while (low < high) { std::cout << "+ "; mid = (1.0f * (elem - array[low]) / (array[high - 1] - array[low]) * (high - 1 - low) + low); if (array[mid] > elem) //compare 1 high = mid; else if (array[mid] < elem)//compare 2 low = mid + 1; else return mid;//compare 3 } return -1;}
测试代码为
cout << "----- search array -----" << endl; int a[6] = {0, 1, 2, 3, 4, 5}; int len = sizeof(a) / sizeof(a[0]); for (int i = 0; i < len; ++i) { cout << "interpolation " ; cout << search_interpolation(a, 0, len, a[i]) << endl; cout << "binary_recursion "; cout << search_binary_recursion(a, 0, len, a[i]) << endl; cout << endl << endl; }
运行结果如下。
‘+’符号的个数表示查找成功时已经在while循环运行的次数,可见插值查找确实比二分查找在元素均匀分布时更有优势。
----- search array -----interpolation + 0binary_recursion + + + 0interpolation + 1binary_recursion + + 1interpolation + 2binary_recursion + + + 2interpolation + 3binary_recursion + 3interpolation + 4binary_recursion + + + 4interpolation + 5binary_recursion + + 5
阅读全文
0 0
- Algorithm4——有序向量查找
- 有序向量的查找
- 有序表查找——折半查找
- 有序向量
- 有序表——折半查找
- 二分查找—有序顺序表
- Java代码实现有序向量的二分查找
- 有序表查找——折半查找,又为二分法
- 数据结构之查找(三)——有序表查找
- 有序向量:二分查找&斐波那契查找&插值查找
- 几种查找算法总结与比较—顺序查找、有序查找、散列表查找
- 二分查找进阶——循环有序数组查找再进阶——循环有序重复数组查找
- 数据结构学习6——有序表查找(折半查找与斐波那契查找)
- java最优有序查找——红黑树(RBT)算法
- 数据结构——数组-有序矩阵查找算法
- 查找——两个有序序列的中位数
- 大话数据结构—顺序表、有序表、线性索引查找
- 楚楚街—面试题 --有序数组查找
- Divide Two Integers
- PHP字符的显示
- HTML学习之路-2 HTML常用标签
- 在微信浏览器,<intput type="file"> 无法调用手机魅族6pro打开摄像机录视频
- Spring Security(18)——Jsp标签
- Algorithm4——有序向量查找
- 论王者荣耀英雄花木兰
- Kali linux渗透测试(五)
- MQL5-字符串数据
- LeetCode 0009
- Spring Security(17)——基于方法的权限控制
- linux安转jdk1.8
- this指向,改变this指向
- luoguP2024 食物链 题解