-1

我正在用 VB 编写一个程序,该程序将从文件中对联系人列表(二维数组)进行排序,Binary Search Algorithm然后starting with使用user input. 然后,我会显示找到的姓名,以及他们的其他联系信息。问题是Binary Search Algorithm只搜索了一个名字。我需要找到所有start with.user input

到目前为止,这是我的代码:

Dim found As Boolean = False
Dim search as String = txtInput.Text

Do
    middle = CInt((first + last) / 2) 'calcuate the middle position of the scope

    If contacts(middle, 1).ToLower.StartsWith(search) Then 'if the middle name starts with the search String
        found = True 'name was found
    ElseIf contacts(middle, 1).ToLower < search Then 'if the search name comes after the middle position's value
        first = middle + 1 'move the first position to be 1 below the middle
    ElseIf contacts(middle, 1).ToLower > search Then 'if the search name comes before the middle position's value
        last = middle - 1 'move the last position to be 1 above the middle
    End If

Loop Until first > last Or found = True 'loop until the name is not found or the name is found

If found = True Then
    For x = 0 To 4 'display the whole list of data for that name
        txtDisplay.Text += contacts(middle,x).padLeft(15)
    Loop 
End If
4

2 回答 2

3

二进制搜索将终止“匹配值列表中的某个位置”。如果您预计有多个值可能匹配,则需要从该点(朝向 A)向后工作,直到没有匹配,然后再次向前(朝向 Z)。这就是您找到所有部分匹配项的方式。如果您不关心它们的显示顺序,您可以将代码的最后一部分更改为(类似于):

编辑以包括一些边界检查:

If found = True Then
    lb = 0
    ub = UBound(contacts)
    if middle > lb Then
      ii = middle
      While contacts(ii, 1).ToLower.StartsWith(search)
        ii = ii - 1
        if ii < lb Then Exit While
      End While
      firstContact = ii + 1
    Else
      firstContact = lb
    End If

    ii = middle + 1
    If middle <= ub Then
      ii = middle
      While contacts(ii, 1).ToLower.StartsWith(search)
        ii = ii + 1
        if ii > ub Then Exit While
      End While
      lastContact = ii - 1
    Else
      lastContact = ub
    End If

    numMatching = lastContact - firstContact + 1

    Dim matchingContacts(1,1)
    ReDim matchingContacts(1 To numMatching, 0 To 4)

    For ii = 1 To numMatching
      For jj = 0 To 4
        matchingContacts(ii, jj) = contacts(firstContact + ii - 1, jj).padLeft(15)
      Next jj
    Next ii

End If

这应该找到匹配联系人的范围,并创建一个仅包含这些联系人的新数组。我没有对此进行测试 - 所以请原谅拼写错误(我不经常写 VB)。我添加了一些边界检查;不能保证它现在是“完美的”......

于 2013-07-30T16:34:35.877 回答
0

您将需要创建另一个数组来跟踪找到的名称。

可以这样想:你找到了一个名字,然后你想再找一个。好吧,其余名称必须高于和/或低于找到的名称。因此,使用 while 循环检查上面和下面的名称是否与输入匹配,如果匹配,则将它们添加到数组中。

首先,创建一个过程来确定保存所有名称所需的数组大小(在设置值之前需要设置一个大小):

'make sure the array is passed as ByRef because it needs to be changed
Private Sub determineSize(ByVal middle As Integer, ByVal search As String, ByRef foundNames() As Integer) 

    'middle1 and middle2 as the positions (above and below) of the middle position in the search scope
    Dim middle1 As Integer = middle, middle2 As Integer = middle 
    Dim foundTrack As Integer = 0 'number of names found

    Do While contacts(middle1, 1).ToLower.StartsWith(search)
        foundTrack += 1 '1 more name has been found

        If middle1 > 0 Then 'if there are any positions above the current one
            middle1 -= 1 'move up 1
        Else
            Exit Do
        End If
    Loop

    If middle < UBound(contacts, 1) Then 'if there are more names below the current one
        middle2 += 1 'this will help to not have a duplicate name from the other list

        Do While contacts(middle2, 1).ToLower.StartsWith(search)

            foundTrack += 1 'Add 1 to the name found tracker.

            If middle2 < UBound(contacts, 1) Then 'if there are any positions below the current one
                middle2 += 1 'move the position down to check for another name on the list
            Else
                Exit Do
            End If
        Loop
    End If

    ReDim foundNames(foundTrack - 1) 'set the size to be 1 less than the names found
End Sub

然后创建一个查找所有名称并将这些位置分配给foundNames数组的过程:

Private Sub FindNames(ByVal middle As Integer, ByVal search As String, ByVal foundNames(,) As String)

    Dim foundTrack As Integer = 0 'number of names found
    'middle1 and middle2 as the positions (above and below) of the middle position in the search scope
    Dim middle1 As Integer = middle, middle2 As Integer = middle 

    Do While contacts(middle1, 1).ToLower.StartsWith(search)
        foundTrack += 1 '1 more name has been found
        foundNames(foundTrack - 1) = middle 'set the position in the array to be the position of the name found

        If middle1 > 0 Then 'if there are any positions above the current one
            middle1 -= 1 'move up 1
        Else
            Exit Do
        End If
    Loop

    If middle < UBound(contacts, 1) Then 'if there are more names on the list below the current position
        middle2 += 1 'this will help to not have a duplicate name from the other list

        Do While contacts(middle2, 1).ToLower.StartsWith(search)

            foundTrack += 1 'Add 1 to the name found tracker.

            If middle2 < UBound(contacts, 1) Then 'if there are any positions below the current one
                middle2 += 1 'move the position down to check for another name on the list
            Else
                Exit Do
            End If
        Loop
    End If
End Sub

然后只需编辑您以前Binary Search Algorithm的内容以合并这些程序:

Dim found As Boolean = False
Dim search as String = txtInput.Text
Dim foundNames() As Integer 'array that holds the row position of each of the found names

Do
    middle = CInt((first + last) / 2) 'calcuate the middle position of the scope

    If contacts(middle, 1).ToLower.StartsWith(search) Then 'if middle name starts with search string
        found = True 'keep track of the fact that the name was found.
        Call determineSize(middle, search, foundNames)
        Call findNames(middle, search, foundNames)
    ElseIf contacts(middle, 1).ToLower < search Then 'if the search name comes after the middle position's value
        first = middle + 1 'move the first position to be 1 below the middle
    ElseIf contacts(middle, 1).ToLower > search Then 'if the search name comes before the middle position's value
        last = middle - 1 'move the last position to be 1 above the middle
    End If

Loop Until first > last Or found = True 'loop until the name is not found or the name is found

If found = True Then
    For i = 0 To UBound(foundNames)
        For j = 0 To 4
            txtDisplay.Text += contacts(i,j).padLeft(15)
        Loop
    Loop 
End If

现在您有了数组中的位置,因此您可以根据需要对其进行排序。

于 2013-07-30T16:59:24.560 回答