赞
踩
@C语言实现各大查找算法(一)
直 奔 主 题 !!!
今天用c语言实现数据结构中的查找算法,我们先实现顺序查找、折半查找(二分查找)、插值查找算法,后续我们会实现其他的查找算法。(主要是咱也还不会啊…)
先附上题目,有如下数组,我们随便给个值,查找一下里面有没有和这个值相同的,如果有,输出它的下标,也就是位置。(我们假定数组是从小到大排序的,且只有一个答案,此外,数组元素、数组长度、查找的key值,都可以从控制台输入,没啥大问题)
num = 30;
顺序查找(linear search)
顺序查找比较简单,从数组下标 0 到 数组长度-1 一一遍历过去,找到就输出下标,不然就一直遍历,直到数组遍历结束,它的时间复杂度为 O(n) 。过程如下图:
代码实现如下:
1 int linearSearch(int arr[],int len,int num) {
2 int i = 0;
3 for(i = 0;i < len;i++) {
4 if(arr[i] == num) {
5 return i;
6 }
7 }
8 return 0;
9 }
由于简单,没有什么特别需要注释的,看懂就好,虽然也没啥人看,我好难啊…
折半查找(二分查找 binary search)
对于一些数组长度较长的数组,顺序查找显然不适用了,要是重复的数在最后一位,啧啧,电脑哭了,对此我们有一种新的查找算法:折半查找,具体思想如下图:
这就是二分查找的算法思想,它循环一次可以为我们略去一半的无用数据,假如要查找的数就在mid的位置,我们的效率就会大大提高。什么?在第一个顺序查找快?呵呵…杠精必死
二分查找算法的时间复杂度为 O (log2n) ;代码实现也比较容易,我也放在下面了:
1 int binarySearch(int arr[],int len,int num) {
2 int left = 0;
3 int right = len -1; //数组长度-1
4 if(left > right) {
5 printf("ERROR!\n");
6 return 0;
7 }
8 while(left <= right) {
9 int mid = (left + right)/2; //每次循环mid的值都需要重新计算
10 if(arr[mid] == num) {
11 return mid;
12 }
13 if(arr[mid] < num) {
14 left = mid;
15 }else{
16 right = mid;
17 }
18 }
19 }
插值查找(interpolation search)
插值算法其实就是在二分查找算法上做了一些优化,在介绍它之前先思考两个问题
第一,为什么要先去中间找而不是除以4,乘以 3/4,去前面或后面找?
第二,你在翻一本书时,已知它有300页左右,要翻到30页,或者250页,你会先去往中间翻么?
插值查找就是这个意思,我要从更贴近答案的地方开始找,而不是固定往中间开始找。
那问题来了,我们怎么去找这个更贴近的位置呢?嗯…先来看看二分查找吧
在二分查找,我们找中间位置 是让 mid = (left + right)/ 2 = left + 1/2(right - left)
通过类比的思想,我们可以把这里的1/2 类比为 (num - left)/ (arr[right] - arr[left])
也很好理解,想象一把20cm的绳子,我要找5cm长的地方,是不是就要去 (5 - 0) / (20 - 0) = 1/4的地方找,就更靠近 ,两个差不多一个意思
算法 代码 其实也差不多 直接给你们附上:
补充一下:插值算法的算法复杂度是O(log2(log2n)),最坏也会达到O(n),因为数组里面的数值我们不知道,在它跨度很大的情况下,算法时间复杂度就会变高,我们做的只是尽量去贴近我们要查找的值。
代码块:
1 int interpolationSearch(int arr[],int len,int num) {
2 int left = 0;
3 int right = len -1; //数组长度-1
4 if(left > right) {
5 printf("ERROR!\n");
6 return 0;
7 }
8
9 while(left <= right) {
10 int mid = left + (num - arr[left])/(arr[right] - arr[left]) * (right - left);
11 // (num - arr[left])/(arr[right] - arr[left])就是所谓的插值
12 if(arr[mid] == num) {
13 return mid;
14 }
15 if(arr[mid] < num) {
16 left = mid;
17 }else{
18 right = mid;
19 }
20 }
21 }
最后再说一下吧,二分查找和插值查找都属于有序查找,有一定局限性,但好用啊,对吧。然后这两个都可以用函数递归来写,但咱还没学,后面有机会再补充,有错误的地方如果有人看,这很重要,麻烦帮忙指出哈,大家一起学习嘛,自己也就是个渣渣,不谈了不谈了,溜了溜了。后面还有查找算法没讲,后面学了会再写。
@xiaolv
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。