二分查找的变形应用

本文介绍了一种使用二分查找算法来高效地在数组中寻找第一个空闲块的方法。针对全0、全1及混合情况进行了特殊处理,并通过两种优化版本的二分查找实现,减少数组访问次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法理解

获取数组中第一个空闲的块

比如 array 1111111…111000000…0

问题就变成 寻找array中第一个出现的0

算法一:遍历数组找到第一个0 O(n)

算法二:二分查找

二分查找 伪码 

二分查找成功条件:array[i]=t; 失败条件:l>u

对于本问题来说,成功条件则是array[i]=0 array[i-1]=1,失败条件要提前测试 1的情况

static int _GetBlockFfp()

{

         int ret = 0;

         byte nPage = 0;

         int nMaxUsed = 0;

         int nMinFree = SIZE-1;

         byte nCase = SIZE;

         int array[SIZE]={0};

    int i,j;

   for(j=0;j<=SIZE;j++)

   {

           printf("j %d/n",j);

    for(i=0;i<SIZE;i++)

    {

      array[i]=0;

    }

    for(i=0;i<j;i++)

        array[i]=1;

    //读第0

   if(array[0]==0)

    {

         printf("find ffp %d/n",0);

        //return 0;

        continue;

    }

    else

    {

       nMaxUsed=0;

    }

    //读最后一页

    if(array[SIZE-1]==1)

    {

           printf("find ffp %d/n",SIZE);   

          // return 0;  

          continue;     

    }

    else

    {

      nMinFree=SIZE-1;

    }

    //以上处理了 全空 全满,不存在First free page的情况 

    //以下则是 0 最后一页 肯定存在 First free page的情况 

    while(1)

    {

       nPage=(nMinFree+nMaxUsed)/2;

      /* if(array[nPage]==0)

       {

          nMinFree=nPage;

       }

       else

       {

           nMaxUsed=nPage;

       }

       */

       if(array[nPage]==0)

       {

            if(array[nPage-1]==1)

            {

                printf("find ffp %d/n",nPage);  

                break;

            }

          

              nMinFree=nPage-1;        

       }

       else

       {

              if(array[nPage+1]==0)

            {

                printf("find ffp %d/n",nPage+1);  

                break;

            } 

          

              nMaxUsed=nPage+1;

       }

      /* if( (nMinFree == (nMaxUsed+1 )))

       {

           printf("find ffp %d/n",nMinFree);  

          // return 0;

          break;

       }*/

    }

}

}

算法三:

二分查找的变形,每次循环少一次 访问数组

利用两个变量 nMinFree nMaxUsed ,算法成功条件 nMinFree== nMaxUsed+1

Version 1:逻辑清晰版

#define SIZE 64

static int _GetBlockFfp()

{

         int ret = 0;

         byte nPage = 0;

         int nMaxUsed = -1;

         int nMinFree = SIZE;

         byte nCase = SIZE;

         int array[SIZE]={0};

    int i,j;

 

    for(i=0;i<56;i++)

        array[i]=1;

    //读第0

    if(array[0]==0)

    {

         printf("find ffp %d/n",0);

        //return 0;

        continue;

    }

    else

    {

       nMaxUsed=0;

    }

    //读最后一页

    if(array[SIZE-1]==1)

    {

           printf("find ffp %d/n",SIZE);   

          // return 0;  

          continue;     

    }

    else

    {

      nMinFree=SIZE-1;

    }

    //以上处理了 全空 全满,不存在First free page的情况 

    //以下则是 0 最后一页 肯定存在 First free page的情况 

    while(1)

    {

       nPage=(nMinFree+nMaxUsed)/2;

       if(array[nPage]==0)

       {

          nMinFree=nPage;

       }

       else

       {

           nMaxUsed=nPage;

       }

      

       if( (nMinFree == (nMaxUsed+1 )))

       {

           printf("find ffp %d/n",nMinFree);  

          // return 0;

          break;

       }

    }

 

}

Version 2:更加优化版

 

#include <stdio.h>

#include <stdlib.h>

#define SIZE 64

typedef unsigned char byte;

static int _GetBlockFfp()

{

    int ret = 0;

    byte nPage = 0;

    int nMaxUsed = -1;

    int nMinFree = SIZE;

    byte nCase = SIZE;

    int array[SIZE]={0};

    int i,j;

    int l,u;

    l=0;

    u=SIZE-1;

    for(i=0;i<56;i++)

        array[i]=1;

    while(1)

    {

        printf("npage:%d/n",nPage);

        if(array[nPage]==0)

        {/*自由块-------------------------------------------------------------*/

            nMinFree = nPage;

            if (nMinFree == (nMaxUsed + 1))

            {   printf("find ffp %d/n",nMinFree);

                              return 0;

            }

                 

            /*未确定,重新定位,先算case减半*/

            nPage = (byte)((nMinFree + nMaxUsed) >> 1);

           

            printf("free blk/n");

            printf("nMinFree : %d,nMaxUsed : %d/n",nMinFree,nMaxUsed);

            printf("nCase : %d,newnPage : %d/n",nCase,nPage);

            printf("/n");

       

        }

        else

        {/*在用块-------------------------------------------------------------*/

            nMaxUsed = nPage;

            if (nMinFree == (nMaxUsed + 1))

            {/*已确定*/

                printf("find ffp %d/n",nMinFree);

                 return 0;

            }

            /*未确定,重新定位,减半*/

        if(0==nPage)

            {/*第一次,在用,专门优化直接读最末页*/

                nPage = (byte)(nCase - 1);

            }

            else

            {/*其它,先算case后定位*/

                 nPage = (byte)((nMinFree + nMaxUsed) >> 1);

           

                printf("used blk/n");

            printf("nMinFree : %d,nMaxUsed : %d/n",nMinFree,nMaxUsed);

                printf("nCase : %d,newnPage : %d/n",nCase,nPage);

                    printf("/n");

               

            }

        }

    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值