通俗的插排是对一个整型数组进行升序排序,可以看出每个元素插入到队列中经过两个步骤:先是挨个比较,找到自己所在的位置;然后把后面的数据全部移位,然后把元素插入。
要把数据插入,移位是必不可少了。那么,挨个比较倒是可以优化,因为要插入的队列已经是排序好的,我们可以使用二分法来减少比较的次数。
二分法的时间复杂度为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
时间: 2024-10-14 09:55:21