【问题标题】:Searching a Sorted List using Binary Search (C#)使用二分搜索 (C#) 搜索排序列表
【发布时间】:2013-03-06 12:08:50
【问题描述】:

要求是使用二进制搜索方法搜索一个按字母顺序/排序的列表(字符串类型),查找指定字符串(在下面的示例中为“yz”)并返回结果(每个以指定的字符串以及该字符串在列表中的索引)在合适的控件(如 ListBox)上。

问题在于 BinarySearch 方法必须在一个循环中运行多次,以便它返回列表中的所有匹配字符串,而不仅仅是一个。这是我的主要问题。我不知道如何正确编写这个循环。如果您查看 while 循环内部,您会看到我正在尝试删除从列表中找到的结果,因此找不到并再次返回。这会导致列表中项目的索引被更改的问题。因此它为结果返回错误的索引。例如,如果您运行下面的代码,它应该返回索引:9、10、11 和 12。但是,我得到 9、10、9、10,因为随着项目被删除,列表变得更短。我可以用另一个随机字符串替换结果字符串,而不是完全删除它,但这意味着列表不再按字母顺序排序。要使 BinarySearch 方法起作用,列表必须按字母顺序排序。

BinarySearch 方法可能没问题,不需要任何更改。问题在于循环。我应该提到这是我大学的作业,所以我不能使用任何快捷代码/内置函数。我已经尝试了几个小时,但无法弄清楚这一点。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    string searchString = "yz";

    List<string> list1 = new List<string>();

    private void btnSearch_Click(object sender, RoutedEventArgs e)
    {
        if (list1.Count != 0)
        {
            list1.Clear();
        }

        list1.Add("ant");   //0
        list1.Add("bb");    //1
        list1.Add("bc");    //2 
        list1.Add("bD");    //3
        list1.Add("Be");    //4
        list1.Add("j");     //5
        list1.Add("RRR");   //6
        list1.Add("sT");    //7
        list1.Add("Uv");    //8      
        list1.Add("yz");    //9
        list1.Add("yza");   //10
        list1.Add("yzb");   //11
        list1.Add("yzc");   //12

        int index = BinarySearch(list1, 0, list1.Count, searchString);

        while (index != list1.Count)
        {
            listBox1.Items.Add("Index: " + index + " File: " + list1[index]);

            list1.RemoveAt(index); //Remove from list so we don't find it again
                                   // but this changes the index of the list

            index = BinarySearch(list1, 0, list1.Count, searchString);
        }
    }

    //BinarySearch method to search an alphabetically sorted list for a specified string
    public int BinarySearch(List<string> strList, int first, int last, string target)
    {
        int mid;    // index of the midpoint
        string midStr;  // object that is assigned listStr[mid]
        int origLast = last;
        // save original value of last
        while (first < last)
        // test for nonempty sublist
        {
            mid = (first + last) / 2;
            midStr = strList[mid];

            int indy = midStr.IndexOf(target, StringComparison.OrdinalIgnoreCase);

            if (indy == 0)
                return mid;// have a match, we're only matching the beginning of the string
            else
            {
                int order = string.Compare(target, midStr, StringComparison.OrdinalIgnoreCase);

                if (order < 0)
                    last = mid; // search lower sublist. Reset last                    
                else
                    first = mid + 1; // search upper sublist. Reset first
            }
        }
        return origLast; // target not found
    }
}

【问题讨论】:

    标签: list search loops binary-search sorted


    【解决方案1】:

    你为什么不呢,一旦你得到一个元素的索引,从索引向上循环,直到你到达最后一个对象或不是从字符串开始的对象,从 index-1 循环直到你得到到 0 或者你到达一个无效的对象。

    编辑:要修改您的代码,我要做的是:

    int index = BinarySearch(list1,0,list1.Count,searchString);
    

    我不会执行删除对象的 while 循环,而是这样做:

    for (int n=index;n<list1.Count;n++) {
        if (list1[n].IndexOf(searchString,StringComparison.OrdinalIgnoreCase)!=0) break;
        listBox1.Items.Add("Index: " + n + " File: " + list1[n]);
    }
    for (int n=index-1;n>=0;n--) {
        //Do same thing as other loop
    }
    

    这只会在列表中双向搜索并执行您的操作,直到找到无效的字符串,然后会中断循环。

    【讨论】:

    • 我不太确定你的意思(我对编程完全陌生)。你能修改我的代码并显示它吗?
    • 这是你的意思吗?我收到错误。 www2.picturepush.com/photo/a/12444975/1024/Anonymous/…
    • 很抱歉这是我的错误。你想在list1[n].IndexOf(...) 之前去掉searchString.。我编辑了这个例子来解决这个问题。
    • 哈哈我又坏了。 ==0 应该是 !=0。当您快速编写示例代码时会发生这种情况。
    • 老兄,你刚刚救了我的命。太感谢了! :)
    猜你喜欢
    • 1970-01-01
    • 2014-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多