• 二分法检索(binary search)(又名二进制搜索)


    定义:

      二分法检索的基本思想是设字典中的元素从小到大有序地存放在数组(array)中。首先将给定值key与字典中间位置上元素的关键码(key)比较,如果相等,则检索成功;否则,若key小,则在字典前半部分中继续进行二分法检索;若key大,则在字典后半部分中继续进行二分法检索。这样,经过一次比较就缩小一半的检索区间,如此进行下去,直到检索成功或检索失败。偶数个取中间2个其中任何一个作为中间元素。二分法检索是一种效率较高的检索方法,要求字典在顺序表中按关键码排序。

    例题:

    大意为:

      给定一个双调数组(数组中数字先递增后递减),例如1,3,5,7,6,4,2,0,-2,-4,-6,-10。另外给定一个数字X。

      设计一个算法,找出X是否在数组中。当此数组的数字总量n为很大的一个数值时,寻找X时,程序最多运行大约2lgN次。lg为底数为2的对数,lg4=2;lg8=3。

    解答:

      解题思路:首先,直接遍历是肯定不行的,因为当n很大时,如果X是数组的最后一个数字,则程序要运行N次才能找到。例如:

       int x;
    //如果x==RawArray[RawArray.Num()-1],则这个要遍历所有数字,运行了N次
        for (int i=0;i<RawArray.Num();++i)
        {
            if (RawArray[i] == x) return;
        }

      然后,解题方法为:利用二分法检索来检索。先用二分法检索找到递增区域和递减区域的共同数字(上述例子中的7);然后分别在递增区域和递减区域中用二分法检索来寻找X。

      具体实现:

    .h:
    
    UCLASS()
    class ALGORITHM_API AAnalysisExerciseOne : public AActor
    {
        GENERATED_BODY()
        
    public:    
        // Sets default values for this actor's properties
        AAnalysisExerciseOne();
    
        //在数组中寻找X,如果找到,返回True;反之,返回false;
        bool FindIntX(TArray<int> TargetArray, int X);
        //二叉法找Int
        bool XInArray(TArray<int> TargetArray, int LeftIndex, int RightIndex, int X, bool IncreaseSide);
    
    protected:
        // Called when the game starts or when spawned
        virtual void BeginPlay() override;
    
    public:    
        // Called every frame
        virtual void Tick(float DeltaTime) override;
    
    private:
    
        TArray<int> RawArray;
        
    };
    
    .cpp:
    
    // Sets default values
    AAnalysisExerciseOne::AAnalysisExerciseOne()
    {
         // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
        PrimaryActorTick.bCanEverTick = true;
    }
    
    //在数组中寻找X,如果找到,返回True;反之,返回false;
    bool AAnalysisExerciseOne::FindIntX(TArray<int> TargetArray, int X)
    {
        //利用二叉法,寻找递增数组和递减数组的共用元素
        //左右两个点
        int Left(0);
        int Right(TargetArray.Num());
        //这个是要找的元素的index
        int TargetInt(0);
        //开始寻找
        while (Left <= Right)
        {
            //找中间点,如果有小数点,舍弃,取整
            int Mid = Left + (Right - Left) / 2;
            if (TargetArray[Mid - 1] < TargetArray[Mid] && TargetArray[Mid]>TargetArray[Mid + 1])
            {
                //找到了,结束While
                TargetInt = Mid;
                break;
            }
            else if (TargetArray[Mid - 1] < TargetArray[Mid]) { Left = Mid + 1; }
            else if (TargetArray[Mid] > TargetArray[Mid + 1]) { Right = Mid - 1; }
            //在双调数组中,TargetArray[Mid - 1] > TargetArray[Mid] && TargetArray[Mid] < TargetArray[Mid + 1]的情况不存在
            else break;
        }
        //等于0说明没找到,出问题了,返回
        if (TargetInt == 0) return false;
        //X比数组中所有数字都大,X不在数组中
        if (X > TargetArray[TargetInt]) return false;
        if (X == TargetArray[TargetInt]) return true;
        //先在增长数组中找
        if (XInArray(TargetArray, 0, TargetInt - 1, X, true))
        {
            UKismetSystemLibrary::PrintString(this, "Find in increase side!");
            return true;
        }
        //如果在增长数组中找不到,则去减少数组中找
        else
        {
            if (XInArray(TargetArray, TargetInt + 1, TargetArray.Num() - 1, X, false))
            {
                UKismetSystemLibrary::PrintString(this, "Find in Decrease side!");
                return true;
            }
            //都找不到,说明没有
            else
            {
                UKismetSystemLibrary::PrintString(this, "Don't Find it!");
                return false;
            }
        }
    }
    
    bool AAnalysisExerciseOne::XInArray(TArray<int> TargetArray, int LeftIndex, int RightIndex, int X, bool IncreaseSide)
    {
        int Left(LeftIndex);
        int Right(RightIndex);
        //开始寻找
        if (IncreaseSide)
        {
            //在递增区域中寻找
            while (Left <= Right)
            {
                //找中间点,如果有小数点,舍弃,取整
                int Mid = Left + (Right - Left) / 2;
                if (X < TargetArray[Mid]) { Right = Mid - 1; }
                else if (X > TargetArray[Mid]) { Left = Mid + 1; }
                else return true;
            }
            return false;
        }
        //在递减区域中寻找
        else
        {
            while (Left <= Right)
            {
                //找中间点,如果有小数点,舍弃,取整
                int Mid = Left + (Right - Left) / 2;
                if (X > TargetArray[Mid]) { Right = Mid - 1; }
                else if (X < TargetArray[Mid]) { Left = Mid + 1; }
                else return true;
            }
            return false;
        }
    }
    
    // Called when the game starts or when spawned
    void AAnalysisExerciseOne::BeginPlay()
    {
        Super::BeginPlay();
       //测试
    //给定一个初始数组 RawArray.Add(1); RawArray.Add(3); RawArray.Add(5); RawArray.Add(7); RawArray.Add(6); RawArray.Add(4); RawArray.Add(2); RawArray.Add(0); RawArray.Add(-2); RawArray.Add(-4); RawArray.Add(-6); RawArray.Add(-10); if (FindIntX(RawArray, -10)) { UKismetSystemLibrary::PrintString(this, "Find it!"); } else { UKismetSystemLibrary::PrintString(this, "Don't Find it!"); } } // Called every frame void AAnalysisExerciseOne::Tick(float DeltaTime) { Super::Tick(DeltaTime); }
  • 相关阅读:
    17.1.1.2 Setting the Replication Slave Configuration
    17.1.1 How to Set Up Replication
    ffmpeg结构体以及函数介绍(二) 分类: ffmpeg-SDL-VLC-Live555 2013-08-22 18:03 451人阅读 评论(0) 收藏
    ffmpeg结构体以及函数介绍(一) 分类: ffmpeg-SDL-VLC-Live555 2013-08-22 18:01 543人阅读 评论(0) 收藏
    ffmpeg入门之 Tutorial01 分类: ffmpeg-SDL-VLC-Live555 2013-08-22 17:54 495人阅读 评论(0) 收藏
    uclibc和glibc的差别 分类: arm-linux-Ubuntu 2013-08-21 17:42 499人阅读 评论(0) 收藏
    Cramfs、JFFS2、YAFFS2全面对比 分类: arm-linux-Ubuntu 2013-08-21 10:42 904人阅读 评论(0) 收藏
    Hi3531 SDK v2.0.8.0 安装 分类: HI3531 2013-08-21 10:25 2748人阅读 评论(1) 收藏
    arm-linux-gcc: Command not found 问题解析 . 分类: arm-linux-Ubuntu 2013-08-21 08:43 855人阅读 评论(0) 收藏
    Hi3531 SDK 安装以及升级使用说明 分类: HI3531 2013-08-20 17:26 2657人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/mcomco/p/10032688.html
Copyright © 2020-2023  润新知