免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 6938 | 回复: 9
打印 上一主题 下一主题

[C] 有序数组有重复数,二分法怎么返回数组中所有的要查找的数的下标 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-05-16 16:14 |只看该作者 |倒序浏览
比如  int  a[10]={2,3,5,6,6,6,6,6,8,9}

用二分法,把所有6的下标得到,能实现吗?或者有其他算法 求指教

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
2 [报告]
发表于 2013-05-16 16:30 |只看该作者
lower_bound+upper_bound,实现这两种二分查找。

论坛徽章:
0
3 [报告]
发表于 2013-05-16 16:31 |只看该作者
本帖最后由 leejqy 于 2013-05-16 16:34 编辑

int lowerBound (const int*pIArr, int start, int end, int val)
{
    int middle;
    while (start < end) {
        middle = (start + end) >> 1;
       if (!middle || (val == pIArr[middle] && pIArr[middle - 1] < val) return middle;
       else if (pIArr[middle] > val) end = middle - 1;
       else start = middle + 1;
    }
    return -1;//不存在
}
int upBound (const int *pIArr, int start, int end, int val)
{
    int middle;
    while (start < end) {
        middle = (start + end) >> 1;
       if (middle == end || (val == pIArr[middle] && pIArr[middle + 1] > val) return middle;
       else if (pIArr[middle] > val) end = middle - 1;
       else start = middle + 1;
    }
    return -1;//不存在
}

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
4 [报告]
发表于 2013-05-16 16:41 |只看该作者
现用正常的二分找到一个,然后往两头找

论坛徽章:
0
5 [报告]
发表于 2013-05-16 16:43 |只看该作者
这样做可能蜕化成线性查找
回复 4# hellioncu


   

论坛徽章:
89
水瓶座
日期:2014-04-01 08:53:31天蝎座
日期:2014-04-01 08:53:53天秤座
日期:2014-04-01 08:54:02射手座
日期:2014-04-01 08:54:15子鼠
日期:2014-04-01 08:55:35辰龙
日期:2014-04-01 08:56:36未羊
日期:2014-04-01 08:56:27戌狗
日期:2014-04-01 08:56:13亥猪
日期:2014-04-01 08:56:02亥猪
日期:2014-04-08 08:38:58程序设计版块每日发帖之星
日期:2016-01-05 06:20:00程序设计版块每日发帖之星
日期:2016-01-07 06:20:00
6 [报告]
发表于 2013-05-17 08:26 |只看该作者
这个要看重复的次数多少了,如果重复的很少,那就找到一个然后往两边跑。

如果比较多,那就上最上面的和最下面的。

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
7 [报告]
发表于 2013-05-17 09:20 |只看该作者
本帖最后由 bruceteen 于 2013-05-17 09:21 编辑

#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
    ///////////// 0 1 2 3 4 5 6 7 8 9
    int a[10] = { 2,3,5,6,6,6,6,6,8,9 };

    std::pair<int*,int*> r = std::equal_range( a+0, a+10, 6 );
    cout << '[' << (r.first-a) << ',' << (r.second-a) << ')' << endl; // output: [3,8)

    return 0;
}

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
8 [报告]
发表于 2013-06-14 15:45 |只看该作者

mark ----
leejqy 发表于 2013-05-16 16:31
int lowerBound (const int*pIArr, int start, int end, int val)
{
    int middle;

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
9 [报告]
发表于 2013-06-18 12:30 |只看该作者
本帖最后由 yulihua49 于 2013-06-19 14:44 编辑
yulihua49 发表于 2013-06-14 15:45
mark ----

做了一个实用化的,可以是任意结构数组,自定义key:
  1. #include <Binary_search.h>

  2. #include <Binary_search.h>

  3. int lowerBound(void *key,void *data,int data_count,int (*compare)(void *key,void *data,int n))
  4. {
  5. int middle,start=0,end=data_count-1,val;
  6.     while (start <= end) {
  7.         middle = (start + end) >> 1;
  8. //printf("lower:start=%d,end=%d,middle=%d\n",start,end,middle);
  9.         val=compare(key,data,middle); //data - key
  10.        if (!val && (!middle||compare(key,data,middle - 1) < 0)) return middle;
  11.        else if (val>=0) end = middle - 1;
  12.        else start = middle + 1;
  13.     }
  14.     return -1;//不存在
  15. }

  16. int upperBound(void *key,void *data,int data_count,int (*compare)(void *key,void *data,int n))
  17. {
  18. int middle,start=0,end=data_count-1,val;
  19. int result=-1;

  20.         if(!key||!data) return -1;
  21.         while(start <= end) {
  22.                 middle=(start+end+1)>>1;
  23. //printf("upper:start=%d,end=%d,middle=%d,result=%d\n",start,end,middle,result);
  24.                 val=compare(key,data,middle);
  25.                 if(val>0)  {
  26.                         if(!middle||compare(key,data,middle - 1) <= 0)
  27.                                 result=middle;
  28.                         end=middle-1;
  29.                 } else {
  30.                         start=middle+1;
  31.                 }
  32.         };
  33.         return result;
  34. }
  35. /* UP=KEY
  36. {
  37. int middle,start=0,end=data_count-1,val;
  38.     while (start <= end) {
  39.         middle = (start + end+1) >> 1;
  40. //printf("start=%d,end=%d,middle=%d\n",start,end,middle);
  41.         val=compare(key,data,middle);//data - key
  42.        if (!val &&  (middle==data_count-1||compare(key,data,middle + 1) > 0)) return middle;
  43.        else if (val>0) end = middle ;
  44.        else start = middle + 1;
  45.     }
  46.     return -1;//不存在
  47. }
  48. */
复制代码
upperBound()进行了一点小调整,否则会有疏漏。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
10 [报告]
发表于 2013-06-18 12:33 |只看该作者
yulihua49 发表于 2013-06-18 12:30
做了一个实用化的,可以是任意结构数组,自定义key:upperBound()进行了一点小调整,否则会有疏漏。

例子:
  1. #include <stdio.h>
  2. #include <Binary_search.h>

  3. static int tab[]={-1,-1,0,1,1,1,1,2,2,2,2,3,3,4,5,5,5,5,5,5,6,6,6,7};
  4. #define COUNT sizeof(tab)/sizeof(int)

  5. static int int_cmp(void *key,void *data,int n)
  6. {
  7. int *d=(int *)data+n;
  8.         return *d-*(int*)key;
  9. }

  10. int main(int argc,char *argv[])
  11. {
  12. int ret,low,up,key;

  13.         key=7;
  14.         low=lowerBound(&key,tab,COUNT,int_cmp);
  15.         up=upperBound(&key,tab,COUNT,int_cmp);
  16.         
  17.         printf("key=%d,low=%d,up=%d\n",key,low,up);
  18.         return 0;
  19. }
复制代码
结果:
-bash-3.00$ ./tbound
key=7,low=23,up=23
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP