排序二:二分查找法优化插入排序

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

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

二分法的时间复杂度为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

posted @ 2015-03-16 19:34  叫我霍啊啊啊  阅读(378)  评论(0编辑  收藏  举报