将二进制搜索应用于程序

时间:2017-04-25 23:41:43

标签: c# sorting search binary

我目前有一个程序,我在其中读取文件并使用冒泡排序进行排序。但是我需要实现一个允许我在任何文件中搜索值的函数。我想要使​​用的算法是二进制搜索,但我不确定如何实现它。

我如何制作它以便我可以选择一个文件来搜索我输入的值?

用于读入文件并允许排序的代码(排序时无需帮助):

var fileData = GetFileData(@"Data1/Day_1.txt", @"Data1/Depth_1.txt", 
    @"Data1/IRIS_ID_1.txt", @"Data1/Latitude_1.txt", @"Data1/Longitude_1.txt", 
    @"Data1/Magnitude_1.txt", @"Data1/Month_1.txt", @"Data1/Region_1.txt", 
    @"Data1/Time_1.txt", @"Data1/Timestamp_1.txt", @"Data1/Year_1.txt"); 

以上部分来自Main方法

public class FileData
{
    public int File1Value { get; set; }
    public decimal File2Value { get; set; }
    public int File3Value { get; set; }
    public decimal File4Value { get; set; }
    public decimal File5Value { get; set; }
    public decimal File6Value { get; set; }
    public string File7Value { get; set; }
    public string File8Value { get; set; }
    public float File9Value { get; set; }
    public int File10Value { get; set; }
    public int File11Value { get; set; }

    public override string ToString()
    {
        return String.Format($"{File1Value}|{File2Value}|{File3Value}|{File4Value}|{File5Value}|{File6Value}|{File7Value}|{File8Value}|{File9Value}|{File10Value}|{File11Value}");
    }
}

public static FileData[] GetFileData(string firstFilePath, string secondFilePath, 
    string thirdFilePath, string fourthFilePath, string fifthFilePath, 
    string sixthFilePath, string seventhFilePath, string eigthFilePath, 
    string ninthFilePath, string tenthFilePath, string eleventhFilePath)
{

    int intHolder = 0;
    decimal decHolder = 0;
    float time = 0;

    // Get a list of ints from the first file
    var fileOneValues = File
        .ReadAllLines(firstFilePath)
        .Where(line => int.TryParse(line, out intHolder))
        .Select(v => intHolder)
        .ToArray();

    // Get a list of decimals from the second file
    var fileTwoValues = File
        .ReadAllLines(secondFilePath)
        .Where(line => decimal.TryParse(line, out decHolder))
        .Select(v => decHolder)
        .ToArray();

    var fileThreeValues = File
        .ReadAllLines(thirdFilePath)
        .Where(line => int.TryParse(line, out intHolder))
        .Select(v => intHolder)
        .ToArray();

    var fileFourValues = File
        .ReadAllLines(fourthFilePath)
        .Where(line => decimal.TryParse(line, out decHolder))
        .Select(v => decHolder)
        .ToArray();

    var fileFiveValues = File
        .ReadAllLines(fifthFilePath)
        .Where(line => decimal.TryParse(line, out decHolder))
        .Select(v => decHolder)
        .ToArray();

    var fileSixValues = File
       .ReadAllLines(sixthFilePath)
       .Where(line => decimal.TryParse(line, out decHolder))
       .Select(v => decHolder)
       .ToArray();

    var fileSevenValues = File
        .ReadAllLines(seventhFilePath)
        .ToArray();

    var fileEightValues = File
        .ReadAllLines(eigthFilePath)
        .ToArray();

    var fileNineValues = File
        .ReadAllLines(ninthFilePath)
        .Where(line => float.TryParse(line, out time))
        .Select(v => time)
        .ToArray();

    var fileTenValues = File
        .ReadAllLines(tenthFilePath)
        .Where(line => int.TryParse(line, out intHolder))
        .Select(v => intHolder)
        .ToArray();

    var fileElevenValues = File
        .ReadAllLines(eleventhFilePath)
        .Where(line => int.TryParse(line, out intHolder))
        .Select(v => intHolder)
        .ToArray();

    // I guess the file lengths should match, but in case they don't, 
    // use the size of the smaller one so we have matches for all items
    var numItems = Math.Min(fileOneValues.Count(), fileTwoValues.Count());

    // Populate an array of new FileData objects
    var fileData = new FileData[numItems];
    for (var index = 0; index < numItems; index++)
    {
        fileData[index] = new FileData
        {
            File1Value = fileOneValues[index],
            File2Value = fileTwoValues[index],
            File3Value = fileThreeValues[index],
            File4Value = fileFourValues[index],
            File5Value = fileFiveValues[index],
            File6Value = fileSixValues[index],
            File7Value = fileSevenValues[index],
            File8Value = fileEightValues[index],
            //File9Value = fileNineValues[index],
            File10Value = fileTenValues[index],
            File11Value = fileElevenValues[index]
        };
    }

    return fileData;
}

二进制搜索代码:

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

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

        return BinarySearch_R(key, fileData, mid + 1, high);
    }
}

1 个答案:

答案 0 :(得分:0)

听起来您正在寻找一种方法来使您的BinarySearch方法通用,以便它可以在不同类型的对象上工作。

下面我将您发布的第一个更改为通用,其中类型T仅限于实现IComparable<T>的类型(因为我们需要能够比较key使用方法内inputArray中的项目。

这应该适用于您为文件定义的类型(intdecimalstringfloat都实现IComparable)。< / p>

/// <summary>
/// Returns the index of an item in inputArray that matches the value of key
/// </summary>
/// <typeparam name="T">The type of objects in the array</typeparam>
/// <param name="inputArray">An array of items to search</param>
/// <param name="key">A key item value to search for</param>
/// <returns>The index of an item that matches key, or -1 if no match is found</returns>
public static int BinarySearchIterative<T>(T[] inputArray, T key) 
    where T : IComparable<T>
{
    int min = inputArray.GetLowerBound(0);
    int max = inputArray.GetUpperBound(0);

    while (min <= max)
    {
        int mid = (min + max) / 2;
        int comparison = key.CompareTo(inputArray[mid]);

        if (comparison == 0)
        {
            return mid;
        }
        else if (comparison < 0)
        {
            max = mid - 1;
        }
        else
        {
            min = mid + 1;
        }
    }

    return -1;
}