鱼C论坛

 找回密码
 立即注册
查看: 19350|回复: 32

[技术交流] 折半查找法(迭代实现)

[复制链接]
发表于 2013-2-23 04:22:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
如果从文件中读取的数据记录的关键字是有序排列的,则可以用一种效率比较高的查找方法来查找文件的记录,这就是折半查找法,又称为二分法搜索。


折半查找的基本思想是:减小查找序列的长度,分而治之地进行关键字的查找。

折半查找的实现过程是:先确定待查找记录的所在范围,然后逐渐缩小这个范围,直到找到该记录或查找失败(查无该记录)为止。

例如有序列:1 1 2 3 5 8 13 21 34 55 89(该序列包含 11 个元素,而且关键字单调递增。),现要求查找关键字 key 为 55 的记录。

我们可以设指针 low 和 high 分别指向关键字序列的上界和下界,指针 mid 指向序列的中间位置,即 mid = (low+high)/2。


No pic you say a J8 之图1:

1.jpg

首先将 mid 所指向的元素与 key 进行比较,因为我们这里 key = 55,大于 8,这就说明待查找的关键字一定位于 mid 和 high 之间。于是我们执行 low = mid+1; mid = (low+high)/2;


No pic you say a J8 之图2:

2.jpg

然后再将 mid 所指的 34 与 key 进行比较,仍然 mid < key,所以继续执行 low = mid+1; mid = (low+high)/2;


No pic you say a J8 之图3:

3.jpg

接下来仍然将 mid 所指的元素与 key 进行比较,结果相等,查找成功,可喜可贺,可口可乐!

返回 mid 的指针值,程序结束!


假设我们要查找的关键字 key = 88,那么上述的查找还要继续进行下去 low = mid+1; mid = (low+high)/2;


No pic you say a J8 之图4:

4.jpg



完整实现代码如下:

  1. // ********************************
  2. // By 小甲鱼,http://www.fishc.com
  3. // ********************************
  4. #include <stdio.h>

  5. int bin_search( int str[], int n, int key )
  6. {
  7.         int low, high, mid;
  8.         
  9.         low = 0;
  10.         high = n-1;

  11.         while( low <= high )
  12.         {
  13.                 mid = (low+high)/2;
  14.                 if( str[mid] == key )
  15.                 {
  16.                         return mid;                // 查找成功
  17.                 }
  18.                 if( str[mid] < key )
  19.                 {
  20.                         low = mid + 1;        // 在后半序列中查找
  21.                 }
  22.                 if( str[mid] > key )
  23.                 {
  24.                         high = mid - 1;        // 在前半序列中查找
  25.                 }
  26.         }

  27.         return -1;                                // 查找失败
  28. }

  29. int main()
  30. {
  31.         int str[11] = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89};
  32.         int n, addr;

  33.         printf("请输入待查找的关键字: ");
  34.         scanf("%d", &n);

  35.         addr = bin_search(str, 11, n);
  36.         if( -1 != addr )
  37.         {
  38.                 printf("查找成功,可喜可贺,可口可乐! 关键字 %d 所在的位置是: %d\n", n, addr);
  39.         }
  40.         else
  41.         {
  42.                 printf("查找失败!\n");
  43.         }

  44.         return 0;
  45. }
复制代码



评分

参与人数 1荣誉 +1 鱼币 +1 收起 理由
苏安酸 + 1 + 1 鱼C有你更精彩^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2013-2-23 09:06:15 | 显示全部楼层
这个好,强大的算法
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2013-2-26 19:48:59 | 显示全部楼层
写了个递归的:
  1. #include<stdio.h>
  2. #define SIZE 10
  3. typedef int ElemType;
  4. int refind(ElemType *data,int begin,int end,ElemType num);
  5. int main(void){
  6.             ElemType data[SIZE]={10,20,30,40,50,60,70,80,90,100};
  7.             ElemType num;
  8.             for(int i = 0;i<SIZE;i++)
  9.                     printf("%d ",data[i]);
  10.             printf("\n请输入要查找的数据:\n");
  11.             scanf("%d",&num);
  12.             int flag = refind(data,0,SIZE,num);
  13.             printf("位置为:%d\n",flag);
  14.             return 0;
  15. }
  16. /
  17. //递归
  18. int refind(ElemType *data,int begin,int end,ElemType num)
  19. {
  20.             if(begin > end)
  21.             {
  22.                       printf("没找到\n");
  23.                       return -1;
  24.              }

  25.              int mid = (begin+end)/2;

  26.              if(data[mid] == num)
  27.             {
  28.                       return mid;
  29.              }else if(data[mid] <= num)
  30.                       return refind(data,mid+1,end,num);
  31.              else
  32.                       return refind(data,begin,mid-1,num);
  33. }
复制代码

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 5 反对 0

使用道具 举报

发表于 2013-2-27 12:56:43 | 显示全部楼层
我有个问题,如果mid的值不是整数怎么弄啊?比如LOW = 0 High = 9,MID =4.5 这个时候怎么办啊?str[4.5]不可以啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2013-2-27 14:53:56 | 显示全部楼层

这里的MID是向下取整└MID┘
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2013-3-14 22:25:22 | 显示全部楼层
()冒充下高手()'“/"是求整不是除法哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2013-8-11 20:38:12 | 显示全部楼层
不错学习下。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-9-18 16:21:45 | 显示全部楼层
顶起,不错呀
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-9-28 09:31:27 | 显示全部楼层
谢谢小甲鱼!存钱买视频!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-10-8 11:31:59 | 显示全部楼层
强烈支持楼主ing……楼下的听好了……
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-10-9 05:43:04 | 显示全部楼层
数组元素再加一个就挂了??:curse:
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-4-7 15:01:07 | 显示全部楼层
int binsearch_recursion(int a[], int low, int high, int key)
{
        if(low > high)
        {
                return -1;
        }
        int mid = (low + high)/2;
        if(a[mid] > key)
        {
                return binsearch_recursion(a, low, mid-1, key);
        }
        else if(a[mid] < key)
        {
                return binsearch_recursion(a, mid+1, high, key);
        }
        else
        {
                return mid;
        }
       
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2014-7-25 20:37:40 | 显示全部楼层
# include <stdio.h>

int bin_search(int *, int, int);

int main(void)
{
        int a[11] = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89};

        printf("%d\n", bin_search(a, 11, 21));

        return 0;
}

int bin_search(int * a, int n, int val)
{
        int pos, low, hig, mid;
       
        for (low=0, hig=n-1, mid=(low+hig) / 2; low <= hig; mid=(low+hig) / 2) {
                if ( val == a[mid] )
                        return mid + 1;
                else if ( a[mid] > val )
                        hig = mid - 1;
                else
                        low = mid + 1;
        }

        return -1;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 2 反对 0

使用道具 举报

发表于 2015-1-3 17:02:19 | 显示全部楼层
这个学习对我帮助很大啊   好好学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2015-1-19 10:29:02 | 显示全部楼层
现在才学习,附上我的代码:
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. int find(int num[],int low,int high,int a)
  4. {
  5.     int mid=(low+high)/2;
  6.     if(low<=high)
  7.     {
  8.         if(num[mid]==a)
  9.         {
  10.             return mid;
  11.         }
  12.         if(num[mid]>a)
  13.         {
  14.             return find(num,low,mid-1,a);
  15.         }
  16.         if(num[mid]<a)
  17.         {
  18.             return find(num,mid+1,high,a);
  19.         }
  20.     }else
  21.     {
  22.         return -1;
  23.     }
  24. }
  25. void main()
  26. {
  27.     int num[]={1,1,2,3,5,8,13,21,34,55,89};
  28.     int n,result;
  29.     printf("请输入你要查找的数:");
  30.     scanf("%d",&n);
  31.     result=find(num,0,10,n);
  32.     if(result==-1)
  33.     {
  34.         printf("不存在此数");
  35.     }else
  36.     {
  37.         printf("你要找的数在第%d个位置。",result+1);
  38.     }
  39. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2015-3-15 11:29:07 | 显示全部楼层
感谢小甲鱼
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-3-17 22:26:14 | 显示全部楼层

RE: 折半查找法(迭代实现)

强烈支持楼主ing……
用迭代实现了一下:
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. int bin_serach(int str[], int n, int key)
  4. {
  5.     int low, mid, high;

  6.     low = 0;
  7.     high = n - 1;

  8.     while(low <= high)
  9.     {
  10.         mid = (low + high)/2;
  11.         if (str[mid] == key)
  12.         {
  13.             return mid;
  14.         }
  15.         else if (str[mid] < key)
  16.         {
  17.             low = mid + 1;
  18.         }
  19.         else {
  20.             high = mid - 1;
  21.         }
  22.     }
  23.     return -1;
  24. }

  25. int getAddr(int str[], int key, int low, int high)
  26. {
  27.     if (low > high)
  28.         return -1;

  29.     int mid = (low + high) / 2;

  30.     if (key == str[mid])
  31.         return mid;

  32.     if (str[mid] < key)
  33.     {
  34.         low = mid + 1;
  35.     }
  36.     else if (str[mid] > key)
  37.     {
  38.         high = mid - 1;
  39.     }

  40.     return getAddr(str, key, low, high);
  41. }

  42. int main()
  43. {
  44.     int str[11] = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89};
  45.     int n, addr;

  46.     printf("请输入要查询的数字:");
  47.     scanf("%d", &n);

  48.     //addr = bin_serach(str, 11, n);
  49.     addr = getAddr(str, n, 0, 11);

  50.     if (-1 != addr)
  51.     {
  52.         printf("查找成功,查询数字%d所在的位置是:%d\n", n, addr);
  53.     }
  54.     else
  55.     {
  56.         printf("查找失败");
  57.     }

  58.     return 0;
  59. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-5-14 21:19:19 | 显示全部楼层
{:1_1:}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-9-14 21:51:51 | 显示全部楼层
//做作业

  1. #include<stdio.h>

  2. int bin_search(int arr[], int low, int high, int key);

  3. void main()
  4. {
  5.     int arr[10]={10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
  6.     int key;
  7.     printf("\n请输入要查找的数据:\n");
  8.     scanf("%d", &key);
  9.     int addr = bin_search(arr, 0, 9, key);
  10.     if(addr != -1)
  11.     {
  12.             printf("key: %d, address: %d\n", key, addr);
  13.         }
  14.     else
  15.         {
  16.                 printf("输入错误");
  17.         }
  18. }


  19. int bin_search(int arr[], int low, int high, int key)
  20. {
  21.         int mid = (low + high)/2;
  22.         if(key == arr[mid])
  23.         {
  24.                 return mid;
  25.         }
  26.        
  27.         if(key <= arr[mid])
  28.         {
  29.                 high = mid - 1;
  30.                 bin_search(arr, low, high, key);       
  31.         }
  32.        
  33.         if(key >= arr[mid])
  34.         {
  35.                 low = mid + 1;
  36.                 bin_search(arr, low, high, key);       
  37.         }

  38.         else
  39.         {
  40.                 return -1;
  41.         }
  42. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-10-11 14:22:11 | 显示全部楼层
这个算法貌似就是那个所谓的“二分法”吧!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-4 18:36

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表