【问题标题】:How to do in-memory binary search in Bash? [duplicate]如何在 Bash 中进行内存二分搜索? [复制]
【发布时间】:2014-03-30 04:39:28
【问题描述】:

编写一个 bash 脚本来进行二分搜索。将文件中的学生姓名和成绩读入数组。提示用户输入学生姓名。在数组中查找名称并显示成绩。文件中的数据如下:

Ann:A
Bob:C
Cindy:B
Dean:F
Emily:A
Frank:C
Ginger:D
Hal:B
Ivy:A
Justin:F
Karen:D

我已经完成了以下操作,但我不知道下一步该做什么

#!/bin/bash
 echo "please enter students Name: "
 read student
 echo "$student + $Grade"
 ((i=0))
 while read students[$i] ; do
 ((i++))

 done < students.dat
 first=0
 last=$(students[@])


 ((mid=0))
 Name=`echo ${students[$mid]} | cut -d: -f1`
 Grade=`echo ${students[$mid]} | cut -d: -f2`
 echo $Name
 echo $Grade

【问题讨论】:

  • 鉴于 Bash 具有关联数组,您通常会使用包含相应等级的名称索引的数组来执行此操作。这不需要二进制搜索。鉴于您需要进行二进制搜索,一种方法是创建按数字索引的并行数组,一个用于名称,另一个用于匹配等级。然后在 names 数组中对名称进行二分搜索,记录找到该名称的索引;您使用该索引来查找等级。请记住,Alice、Evelyn 和 Mallory 不在列表中,因此您必须处理缺失的姓名。
  • 有很多地方可以找到二进制搜索算法来搜索索引范围为 0..N-1 的名称数组(对于数组中的 N 个名称)。

标签: linux bash search binary


【解决方案1】:

这里的每个人都希望你学习这些东西而不是为你做作业,所以我故意有点迟钝。

请记住,这里提出的任何解决方案都是一个程序员会如何做的,不一定是唯一正确的方法。

您需要首先将您的成绩纳入您的计划 - 从那开始。 文件中的每一行都是一个学生姓名,与成绩之间用“:”分隔。 您想将它们读入两个并行数组(正如 Jonathan 指出的那样)。

如果您在 google 上搜索“bash split string”,您会发现 很多 有用的建议来说明如何执行此操作。 我这样做是为了得到两个数组,一个保存学生姓名,另一个保存成绩。

((i=0))
while IFS=":" read -a fields ;
do
    students[$i]=${fields[0]}
    grades[$i]=${fields[1]}

    ((i++))
done < students.dat
echo ${students[@]}
echo ${grades[@]}

酷!现在你需要稍微研究一下二分搜索算法。请记住,您可以使用${#ArrayName[@]} 获取数组的长度

由于列表显然已经排序,您不必自己这样做,因此您可以将您想要的姓名与数组中点的学生姓名进行比较。如果您要查找的学生姓名大于中点的学生姓名,那么您就知道您要的那个在数组的后半部分,反之亦然。最终,中点的学生姓名将正是您要查找的那个。

【讨论】:

    【解决方案2】:

    如果它不必在bash 中,那么您可以使用awkbash 仅在版本 4 中启动了关联数组,因此您可能需要考虑可移植性。

    如果awk 不是您可用的选项,请忽略解决方案:

    $ awk -F: '{
        student[$1] = $2
    }
    END {
        printf "Enter Student Name: "; 
        getline name < "-"; 
        print "Grade for student "name" is "student[name]
    }' inputFile
    

    测试:

    $ cat inputFile
    Ann:A
    Bob:C
    Cindy:B
    Dean:F
    Emily:A
    Frank:C
    Ginger:D
    Hal:B
    Ivy:A
    Justin:F
    Karen:D
    

    $ awk -F: '{
        student[$1] = $2
    }
    END {
        printf "Enter Student Name: ";
        getline name < "-";
        print "Grade for student "name" is "student[name]
    }' inputFile
    Enter Student Name: Justin
    Grade for student Justin is F
    

    【讨论】:

    • 是的,很遗憾它必须是一个 bash 脚本。
    【解决方案3】:

    这是一个适用于仍在搜索的学生的有效二进制搜索 bash 脚本。

      binary_search(){
        TARGET=$1
        TO_SEARCH=(${@:2})
        LENGTH=${#TO_SEARCH[@]}
    
        START=0
        END=$((LENGTH - 1))
        while [[ $START -le $END ]]; do
                MIDDLE=$((START + ((END - START)/2)))
                ITEM_AT_MIDDLE=${TO_SEARCH[MIDDLE]}
                if [[  $ITEM_AT_MIDDLE -gt $TARGET ]]; then
                        END=$((END-MIDDLE-1))
                elif [[ $ITEM_AT_MIDDLE -lt $TARGET ]]; then
                        START=$((MIDDLE+1))
                else
                        echo $MIDDLE
                        return 0
                fi
        done
        echo "-1"
        return 0
     }​
    

    【讨论】:

    • 那是整数数组。
    • 这找不到例如6 个元素排序的唯一元素数组的第 4 个元素。 END 在循环中设置错误。
    猜你喜欢
    • 2016-10-10
    • 2013-07-14
    • 2020-02-28
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-27
    • 2017-02-10
    相关资源
    最近更新 更多