zoukankan      html  css  js  c++  java
  • 排序二:二分查找法优化插入排序

    通俗的插排是对一个整型数组进行升序排序,可以看出每个元素插入到队列中经过两个步骤:先是挨个比较,找到自己所在的位置;然后把后面的数据全部移位,然后把元素插入。

    要把数据插入,移位是必不可少了。那么,挨个比较倒是可以优化,因为要插入的队列已经是排序好的,我们可以使用二分法来减少比较的次数。

    二分法的时间复杂度为O(log 2 n),而线性查找的复杂度为O(n)

    在对50000个随机数进行测试比较中,发现加了二分查找的插排比普通的插排速度快了将近一倍!(通俗插排7888ms,优化插排4852ms)

    下面是测试程序源码:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Diagnostics;
     4 using System.Linq;
     5 using System.Text;
     6 using System.Threading.Tasks;
     7 
     8 namespace InsertSort
     9 {
    10     class Program
    11     {
    12         static void Main(string[] args)
    13         {
    14             int[] arr = new int[50000];
    15 
    16             Random rd = new Random();
    17             for (int i = 0; i < arr.Length; i++)
    18             {
    19                 arr[i] = rd.Next();
    20             }
    21 
    22             Stopwatch watch = new Stopwatch();
    23             watch.Start();
    24             //InsertSortCommon(arr);        //通俗插排7888ms
    25             InsertSortOptimize(arr);        //优化插排4852ms
    26             watch.Stop();
    27 
    28             Console.WriteLine(watch.ElapsedMilliseconds.ToString());
    29         }
    30 
    31         /// <summary>
    32         /// 通俗插排
    33         /// </summary>
    34         public static void InsertSortCommon(int[] arr)
    35         {
    36             int temp, j;
    37             for (int i = 1; i < arr.Length; i++)
    38             {
    39                 temp = arr[i];
    40                 for (j = i - 1; j >= 0 && temp < arr[j]; j--)
    41                 {
    42                     arr[j + 1] = arr[j];
    43                 }
    44                 arr[j + 1] = temp;
    45             }
    46         }
    47 
    48         /// <summary>
    49         /// 优化插排
    50         /// </summary>
    51         public static void InsertSortOptimize(int[] arr)
    52         {
    53             int temp, j, position;
    54             for (int i = 1; i < arr.Length; i++)
    55             {
    56                 temp = arr[i];
    57                 position = BinSearchNum(arr, temp, 0, i - 1);
    58                 for (j = i - 1; j >= position; j--)
    59                     arr[j + 1] = arr[j];
    60                 arr[j + 1] = temp;
    61             }
    62         }
    63 
    64         /// <summary>
    65         /// 二分查找(因为不是查找与其相等值得位置,所以和传统的二分查找略有不同)
    66         /// </summary>
    67         public static int BinSearchNum(int[] arr, int searchNum, int low, int high)
    68         {
    69             int mid = 0;
    70             while (low <= high)
    71             {
    72                 mid = (low + high) / 2;
    73                 if (searchNum < arr[mid])
    74                     high = mid - 1;
    75                 else if (searchNum > arr[mid])
    76                     low = mid + 1;
    77                 else
    78                     return mid;
    79             }
    80             return low;//这块的返回值需要注意,为什么要这么写?
    81         }
    82     }
    83 }

    参考文献:

    http://hi.baidu.com/sangwf/item/5cc1ae54d9a2889408be1722

  • 相关阅读:
    【支付宝支付】手机网页内 支付宝支付实现过程
    【微信支付】微信端的手机网页支付 开发流程
    【Linux】Linux下 环境变量/etc/profile、/etc/bashrc、~/.bashrc的区别【转】
    SLF4J 和 Logback 在 Maven 项目中的使用方法
    打造Spring Cloud构建微服务架构的最全资料
    WebApi安全性 使用TOKEN+签名验证
    <meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1" />的意义
    request.getParameter(“参数名”) 中文乱码解决方法
    Mysql的timestamp类型,自动记录数据的更新时间
    根据身份证号,取得行政区划的Javascript实现
  • 原文地址:https://www.cnblogs.com/HuoAA/p/4342601.html
Copyright © 2011-2022 走看看