zoukankan      html  css  js  c++  java
  • 算法学习01:二分查询,选择法、插入法、分治法排序

        查询与排序是使用的再频繁不过的两个功能,算法学习系列实现语言为C#。

    一般情况下的查询

    Int32 Search(Int32[] source, Int32 task)
    {
        var index = 0;
        while (index < source.Length)
            if (source[index++] == task)
                return index - 1;
                
        //返回值为Length则说明未找到
        return source.Length;
    }

        时间复杂度为O(n),在检索源没有排序的情况下,这即为最高的检索方法。


     

    二分查询

        当检索源为顺序排列时,我们可以使用二分查询进行检索。

        可将时间复杂度提升至O(lgn).

        非递归实现:

    Int32 BinarySearch(Int32[] source, Int32 targetVal)
    {
        Int32 leftPointer = 0;
        Int32 rightPointer = source.Length - 1;
        while (leftPointer <= rightPointer)
        {
            Int32 pos = (rightPointer + leftPointer) / 2;
            if (source[pos] == targetVal)
                return pos;
            if (source[pos] < targetVal)
                leftPointer = pos + 1;
            else
                rightPointer = pos - 1;
        }
        return source.Length;
    }

        递归实现:

    Int32 BinarySearch(Int32[] source, Int32 startIndex, Int32 endIndex, Int32 targetVal)
    {
        if (startIndex > endIndex)
            return source.Length;
        Int32 pos = (startIndex + endIndex) / 2;
        if (source[pos] == targetVal)
            return pos;
        if (source[pos] < targetVal)
            return BinarySearch(source, pos + 1, endIndex, targetVal);
        else
            return BinarySearch(source, startIndex, pos - 1, targetVal);
    }

        测试结果:

    //输出均为8
    Console.WriteLine(BinarySearch(new Int32[10] { 4, 3, 2, 1, 3, 8, 9, 19, 88, 57 }, 0, 10, 88));
    Console.WriteLine(BinarySearch(new Int32[10] { 4, 3, 2, 1, 3, 8, 9, 19, 88, 57 }, 88));

          接下来是一些常用的排序方法。


     

    选择法

        时间复杂度O(n*n)。

    Int32[] SelectionSort(Int32[] source)
    {
        for (int i = 0; i < source.Length; i++)
        {
            var smallestValIndex = i;
            for (int j = i + 1; j < source.Length; j++)
            {
                if (source[smallestValIndex] > source[j])
                    smallestValIndex = j;
            }
            var temp = source[i];
            source[i] = source[smallestValIndex];
            source[smallestValIndex] = temp;
        }
        return source;
    }

       


     

    插入法

        时间复杂度O(n*n),与选择法相比,适合在链表结构中使用。

    Int32[] InsertSort(Int32[] source)
    {
        var resultArray = new Int32[source.Length];
        for (int i = 0; i < source.Length; i++)
        {
            var index = 0;
            while (index++ < i)
            {
                if (resultArray[index - 1] > source[i])
                    break;
            }
            for (int j = index - 1; j < i; j++)
                resultArray[j + 1] = resultArray[j];
            resultArray[index - 1] = source[i];
        }
        return resultArray;
    }


     

    分治排序之合并法

        时间复杂度O(n * lgn)。

        分治原理例图:

        image

    Int32[] DevideAndConquerSort(Int32[] source, Int32 startIndex, Int32 endIndex)
    {
        //子数组只有一个元素时,是无需排序的
        if (startIndex + 1>= endIndex)
            return source;
        var middleIndex = (startIndex + endIndex) / 2;
        DevideAndConquerSort(source, startIndex, middleIndex);
        DevideAndConquerSort(source, (startIndex + endIndex) / 2, endIndex);
        MergeSort(source, startIndex, (startIndex + endIndex) / 2, endIndex);
        return source;
    }
    
    void MergeSort(Int32[] source, Int32 startIndex, Int32 middleIndex, Int32 endIndex)
    {
        var arrayAPointer = startIndex;
        var arrayBPointer = middleIndex;
        var loopLength = endIndex - startIndex;
        var resultArray = new Int32[loopLength];
        for (int i = 0; i < loopLength; i++)
        {
            if (arrayBPointer != endIndex && source[arrayAPointer] > source[arrayBPointer])
                resultArray[i] = source[arrayBPointer++];
            else if (arrayAPointer != middleIndex)
                resultArray[i] = source[arrayAPointer++];
            else
                resultArray[i] = source[arrayBPointer++];
        }
        for (int i = 0; i < loopLength; i++)
        {
            source[startIndex + i] = resultArray[i];        
        }
    }


     

    分支排序之快速排序法

        与合并法相比,适合在n不是很大,又不是很小的时候使用。

        分治原理例图:

        image

    Int32[] QuickSort(Int32[] source, Int32 startIndex, Int32 endIndex)
    {
        if(startIndex >= endIndex)
            return source;
        var index = Partition(source, startIndex, endIndex);
        QuickSort(source, startIndex, index - 1);
        QuickSort(source, index + 1, endIndex);
        return source;
    }
    
    Int32 Partition(Int32[] source, Int32 startIndex, Int32 endIndex)
    {
        Int32 index = 0;
        while ((index++) < endIndex - startIndex)
        {
            if (source[startIndex + index - 1] >= source[endIndex - 1])
                break;
        }
        if(startIndex + index - 1 != endIndex)
        { 
            var temp = source[startIndex + index - 1];
            source[startIndex + index - 1] = source[endIndex - 1];
            source[endIndex - 1] = temp;
        }
        return startIndex + index - 1;
    }


     

    总结

    image

    image

  • 相关阅读:
    NBU7.0 RMAN 异机恢复 not found in NetBackup catalog
    配置Apache支持PHP5
    【浅墨Unity3D Shader编程】之中的一个 夏威夷篇:游戏场景的创建 &amp; 第一个Shader的书写
    关于 rman duplicate from active database 搭建dataguard--系列一
    <html>
    hdu 3622 二分+2-sat
    解决duilib水平布局(HorizontalLayout)中控件位置计算错误的问题
    Android SqlDelight具体解释和Demo样例
    HBase总结(十一)hbase Java API 介绍及使用演示样例
    [置顶] MyEclipse显示中文界面,在线安装教程
  • 原文地址:https://www.cnblogs.com/E-WALKER/p/4458087.html
Copyright © 2011-2022 走看看