易码技术论坛

 找回密码
 加入易码
搜索
查看: 463|回复: 9

对择半查找法的改进-----------摇摆查找法

[复制链接]
发表于 2010-2-8 20:38:46 | 显示全部楼层 |阅读模式
  1. // Rock_Search.cpp : Defines the entry point for the console application.
  2. //

  3. #include "stdafx.h"

  4. int Rock_Search(int p[],int n,int key,int step);
  5. int Mid_Search(int p[],int n,int key);

  6. #define NUM 100
  7. #define SEARCH1 97
  8. #define SEARCH2 NUM/2
  9. #define SEARCH3 NUM-2

  10. int main(int argc, char* argv[])
  11. {
  12.         int data[NUM];
  13.         int i;
  14.         int result;

  15.         for (i=0;i<NUM;i++)
  16.         {
  17.                 data[i] = i;
  18.         }

  19.         Mid_Search(data,NUM,SEARCH1);
  20.         Mid_Search(data,NUM,SEARCH2);
  21.         Mid_Search(data,NUM,SEARCH3);
  22.         Rock_Search(data,NUM,SEARCH1,10);
  23.         Rock_Search(data,NUM,SEARCH2,10);
  24.         Rock_Search(data,NUM,SEARCH3,10);
  25.         getchar();
  26.         return (0);
  27. }

  28. /*
  29. 摇摆搜索算法(Rock_Search)【此算法由 涂洋 写于 2010年2月5号】

  30. P[]:待搜索数组(需要按照从小到大排序,不能不排序或倒序)
  31. n:待搜搜数组的大小
  32. key:待搜索的数据
  33. step:定分点,每次舍弃数组大小的STEP-1/STEP(也就是只保留1/STEP),理论上值越大搜索越快,但也要根据实际情况而定,可先测试
  34. 一般搜索的值位于两端时,值越大越好
  35. 搜索值位于中间时,值取 N/20 最好

  36. 算法说明:
  37. 择半搜索法有一个缺陷,对于位于所搜数组两端的数据,搜索的时候效率较低
  38. 需要择半到最后一次
  39. 并且每次舍弃一半的数据也不算很多

  40. 而摇摆算法则完全屏蔽了这个缺点
  41. 采用定分点手法取舍,例如
  42. 对于 P[0]=0 P[1]=1 ....P[100]=100 这个数组来说,假如要找97这个数据
  43. STEP取10,每次舍弃数组大小的1/10
  44. 对于位于两端的数据,舍弃幅度最大
  45. 但是位于中间的数据就会应为左右摇摆不定而花费大量时间
  46. 所以每次循环的时候检测 odir 和 dir 是否相等,不相等就说明左右摇摆,数据在中间
  47. 那么进行一次择半
  48. 比如对于1-100这个数据说,49相当靠近中间,所以进行一次择半
  49. 那么新的数据就是1-50,这样49对已新数组来说就是极端了,这样对于摇摆算法来说非常有利
  50. */
  51. int Rock_Search(int p[],int n,int key,int step)
  52. {
  53.         int low = 0,high = n-1;
  54.         int index = 0;
  55.         int dir,odir;
  56.         const int right = 1;
  57.         const int left = 2;

  58.         int n_count = 0;
  59.        
  60.         dir = left;
  61.         odir = dir;
  62.        
  63.         if (step > (n/2))
  64.         {
  65.                 return (-2);
  66.         }

  67.         while (low <= high)
  68.         {
  69.                 n_count++;
  70.                 if (dir == left)
  71.                 {
  72.                         index = low + (high - low + 1)/step;

  73.                         if (p[index] == key)
  74.                         {
  75.                                 printf("n_count=%d\n",n_count);
  76.                                 return (index);
  77.                         }

  78.                         if (p[index] < key)
  79.                         {
  80.                                 low = index + 1;
  81.                                 odir = dir;
  82.                                 dir = right;
  83.                         }

  84.                         if (p[index] > key)
  85.                         {
  86.                                 high = index - 1;
  87.                                 odir = dir;
  88.                                 dir = left;
  89.                         }
  90.                 }

  91.                 else if(dir == right)
  92.                 {
  93.                         index = high - (high - low + 1)/step;

  94.                         if (p[index] == key)
  95.                         {
  96.                                 printf("n_count=%d\n",n_count);
  97.                                 return (index);
  98.                         }

  99.                         if (p[index] < key)
  100.                         {
  101.                                 low = index + 1;
  102.                                 odir = dir;
  103.                                 dir = right;
  104.                         }

  105.                         if (p[index] > key)
  106.                         {
  107.                                 high = index - 1;
  108.                                 odir = dir;
  109.                                 dir = left;
  110.                         }
  111.                 }

  112.                 if (dir != odir)
  113.                 {
  114.                         index = (low + high)>>1;
  115.                        
  116.                         if (p[index] == key)
  117.                         {
  118.                                 printf("n_count=%d\n",n_count);
  119.                                 return (index);
  120.                         }

  121.                         if (p[index] < key)
  122.                         {
  123.                                 low = index + 1;
  124.                         }

  125.                         if (p[index] > key)
  126.                         {
  127.                                 high = index - 1;
  128.                         }
  129.                 }
  130.         }
  131.         printf("Not Find\n");
  132.         return (-1);
  133. }

  134. int Mid_Search(int p[],int n,int key) // 择半搜索法
  135. {
  136.         int index,low,high,i;

  137.         low = 0;
  138.         high = n-1;
  139.        
  140.         int n_count = 0;

  141.         while (low<=high)
  142.         {
  143.                 n_count++;
  144.                 index = (low + high)>>1;

  145.                 if (p[index] == key)
  146.                 {
  147.                         printf("n_count=%d\n",n_count);
  148.                         return (index);
  149.                 }

  150.                 if (p[index] < key)
  151.                 {
  152.                         low = index + 1;
  153.                 }

  154.                 if (p[index] > key)
  155.                 {
  156.                         high = index - 1;
  157.                 }
  158.         }
  159.         printf("Not Find\n");
  160.         return (-1);
  161. }
复制代码

Rock_Search.rar

739.06 KB, 下载次数: 168

评分

参与人数 1小红花 +1 收起 理由
lhhlhh + 1 noip对待不良测试点的方法就是在二分的时候 ...

查看全部评分

发表于 2010-2-8 23:39:00 | 显示全部楼层
纯支持一下!
发表于 2010-2-9 10:44:23 | 显示全部楼层
/roll 1-100
你roll出了49点

天啊!正好这是你要查找的数字
 楼主| 发表于 2010-2-9 11:44:13 | 显示全部楼层
汗,怎么和ROLL点联系起来了……
发表于 2010-2-9 13:29:32 | 显示全部楼层
/roll
2499 (!?)
发表于 2010-2-9 18:34:45 | 显示全部楼层
随机查找法
 楼主| 发表于 2010-2-11 15:01:25 | 显示全部楼层
也可以这么说
发表于 2010-2-15 14:13:24 | 显示全部楼层
顶一下   好久没见程序讨论帖...
发表于 2010-2-16 03:43:03 | 显示全部楼层
理论上讲最快的方法是取黄金分割点查找也就是0.618
 楼主| 发表于 2010-2-16 14:38:54 | 显示全部楼层
发现黄金分割的用处很大,用途很广
您需要登录后才可以回帖 登录 | 加入易码

本版积分规则

Archiver|手机版|小黑屋|EMAX Studio

GMT+8, 2024-4-28 03:10 , Processed in 0.016722 second(s), 25 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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