【问题标题】:c# - Binary Search Algorithm for Custom Class String Listc# - 自定义类字符串列表的二进制搜索算法
【发布时间】:2016-04-16 11:40:33
【问题描述】:

基本上,我需要帮助调整我的二分搜索算法以使用我的字符串列表,如下所示。 注意,我必须使用书面的二分搜索算法,不要使用 .BinarySearch 之类的内置 c# 函数。

我现在将向您展示列表的格式以及列表本身:

// This class formats the list, might be useful to know

public class Demo
{
    public string Col;
    public string S1;
    public string S2;
    public string S3;

    public override string ToString()
    {
        return string.Format("Col: {0}, S1: {1}, S2: {2}, S3: {3}", Col, S1, S2, S3);
    }
}

// The list itself

var list = new List<Demo>
        {   
            new Demo {Col = "Blue", S1 ="88", S2 ="Yes"},
            new Demo {Col = "Green", S1 ="43", S2 ="Yes"},
            new Demo {Col = "Red", S1 ="216", S2 ="No"},
            new Demo {Col = "Yellow", S1 ="100", S2 ="No"}
        };

列表已经按照“Col”字符串值的字母顺序排序,因此蓝色排在第一位,黄色排在最后。 “Col”是列表中需要搜索的部分。下面我插入了我当前可以搜索 int 数组的二进制搜索。

public static int BinarySearch_R(int key, int[] array, int low, int high)
    {
        if (low > high) return -1;
        int mid = (low + high) / 2;
        if (key == array[mid])
        {

            return mid;
        }
        if (key < array[mid]) {
            return BinarySearch_R(key, array, low, mid - 1);
        } else {
            return BinarySearch_R(key, array, mid + 1, high);
        }
    }

我需要帮助调整我的 BinarySearch 算法以适用于上面的列表。如果你们有任何问题,或者需要查看我的更多代码,请尽管提问。

【问题讨论】:

  • @jdweng 我问了一个稍微不同的问题。不想争论就说:)
  • @Fabien 我问了一个稍微不同的问题。不想争论就说:)
  • 您拥有的不是字符串列表,而是自定义类 (Demo) 列表。您最好更新帖子标题(例如“*二分搜索算法通过列表元素的属性”),因为它具有误导性。

标签: c# algorithm list binary-search


【解决方案1】:

具体答案:根据具体情况调整您的方法非常容易。

让我们首先更新您现有的方法以使用更通用的方法(IComparable&lt;T&gt;.CompareTo 用于比较而不是 int 运算符:

public static int BinarySearch_R(int key, int[] array, int low, int high)
{
    if (low > high) return -1;
    int mid = (low + high) / 2;
    int compare = key.CompareTo(array[mid]);
    if (compare == 0)
    {
        return mid;
    }
    if (compare < 0)
    {
        return BinarySearch_R(key, array, low, mid - 1);
    }
    else {
        return BinarySearch_R(key, array, mid + 1, high);
    }
}

然后您只需复制/粘贴上述方法,将int key 替换为string key,将int[] array 替换为List&lt;Demo&gt; array,将array[mid] 替换为array[mid].Col

public static int BinarySearch_R(string key, List<Demo> array, int low, int high)
{
    if (low > high) return -1;
    int mid = (low + high) / 2;
    int compare = key.CompareTo(array[mid].Col);
    if (compare == 0)
    {
        return mid;
    }
    if (compare < 0)
    {
        return BinarySearch_R(key, array, low, mid - 1);
    }
    else {
        return BinarySearch_R(key, array, mid + 1, high);
    }
}

扩展答案:虽然您可以执行上述操作,但您需要对需要此类功能的任何其他属性/类执行相同操作。

更好的方法是概括代码。例如,int[]List&lt;Demo&gt; 可以概括为IReadOnlyList&lt;T&gt;int/string keyTKey keyDemo.ColFunc&lt;T, TKey&gt;CompareToIComparer&lt;TKey&gt;.Compare,所以最终的泛型方法可以是这个:

public static class MyAlgorithms
{
    public static int BinarySearch<T, TKey>(this IReadOnlyList<T> source, Func<T, TKey> keySelector, TKey key, IComparer<TKey> keyComparer = null)
    {
        return source.BinarySearch(0, source.Count, keySelector, key, keyComparer);
    }

    public static int BinarySearch<T, TKey>(this IReadOnlyList<T> source, int start, int count, Func<T, TKey> keySelector, TKey key, IComparer<TKey> keyComparer = null)
    {
        // Argument validations skipped
        if (keyComparer == null) keyComparer = Comparer<TKey>.Default;
        int lo = start, hi = start + count - 1;
        while (lo <= hi)
        {
            int mid = lo + (hi - lo) / 2;
            int compare = keyComparer.Compare(key, keySelector(source[mid]));
            if (compare < 0)
                hi = mid - 1;
            else if (compare > 0)
                lo = mid + 1;
            else
                return mid;
        }
        return -1;
    }
}

现在您可以对任何数据结构使用该单一方法。例如,通过Col 搜索您的List&lt;Demo&gt; 将是这样的:

int index = list.BinarySearch(e => e.Col, "Red");

【讨论】:

  • 非常有用!帮助我解决了我的问题。谢谢!
【解决方案2】:

我只在 C# 中做了最基本的事情,所以这可能完全没用。我有一个 CS 2 课的作业,至少听起来和你想要的有点相似,但我们使用的是 java。因此,我假设您希望您的项目列表按某个关键字(“蓝色”、“绿色”等)排序。我使用了 LinkedList 但没关系。

    class Node {
    String keyword;
    LinkedList<String> records = new LinkedList<>();
    Node left;
    Node right;


    public Node(String keyword, LinkedList<String> records) {
        this.keyword = keyword;
        this.records = records;
    }
}

现在,至少我可以分辨出按字符串排序的 BST 和按数字排序的 BST 之间的唯一真正区别是,您需要某种类型的比较方法来查看一个单词是字母表中的 > 还是

   /**
 * insert node
 * @param keyword compare it to other strings
 */
public void insert(String keyword, LinkedList<String> records) {
    //create a new Node
    Node n = new Node(keyword, records);
    int result;
    Node current = root;
    Node parent = null;


    //cont. until NULL
    while (current != null) {
        result = current.keyword.compareTo(n.keyword);
        if (result == 0) return;
        else if (result > 0) {
            parent = current;
            current = current.left;
        }
        else if (result < 0) {
            parent = current;
            current = current.right;
        }
    }

    if (parent == null) root = n;
    else {
        result = parent.keyword.compareTo(n.keyword);
        if (result > 0) parent.left = n;

        else if (result < 0) parent.right = n;

    }
}

因此,如果字符串在字母表中较高,则“compareTo(...)”方法返回 1,如果相同,则返回 0,如果较低,则返回 -1。因此,如果我完全接近您的要求,我会获取此方法的 C# 版本并像往常一样实现 BST。

【讨论】:

    【解决方案3】:

    只需创建 make 类 IComparable 并创建自定义 CompareTo() 方法。一旦类继承了 IComparable,诸如 sort 之类的标准方法将自动起作用。

       public class Demo : IComparable 
        {
            public string Color;
            public int value;
            public Boolean truth;
    
    
            public int CompareTo(Demo other)
            {
                int results = 0;
                if (this.Color == other.Color)
                {
                    if (this.value == other.value)
                    {
                        results = this.truth.CompareTo(other.truth);
                    }
                    else
                    {
                        results = this.value.CompareTo(other.value);
                    }
                }
                else
                {
                    results = this.Color.CompareTo(other.Color);
                }
    
                return results;
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-27
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 2021-11-19
      • 2017-04-30
      • 2013-02-12
      • 1970-01-01
      相关资源
      最近更新 更多