如何在Bash中进行内存中二进制搜索?

时间:2014-02-27 00:54:47

标签: linux bash search binary

编写一个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

3 个答案:

答案 0 :(得分:2)

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

请记住,这里提出的任何解决方案都是一个程序员如何做到这一点,而不一定是真正的方式。

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

如果你谷歌搜索'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[@]}

获取数组的长度

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

答案 1 :(得分:1)

如果它不必在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

答案 2 :(得分:1)

这是一个工作二进制搜索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
 }​