插入排序

来源:互联网 发布:mac airdrop在哪 编辑:程序博客网 时间:2024/05/21 22:35

插入排序,对少量元素进行原位排序的有效算法。

渐近界:theta(n^2)


算法

将数组想象为两部分,已排序部分和未排序部分。开始,排序部分只包含第一个元素,余下为未排序部分。

每次,将未排序部分的第一个元素插入到已排序部分中正确的位置。

假如我们要对数组{7, -5, 2, 16, 4}排序,插入排序过程如下:

Insertion sort example


插入过程

插入算法的主要操作就是插入。即将一个值插入已排序的数组中。下面看看我们如何实现该过程。

交换

最简单的方法就是顺序往下交换,直到正确的地方。开始,待排序元素在排序部分后的第一位上。每次,待排序元素和前一位对比,如果顺序不对,就交换位置。如下:

insertion sort, sift down illustration

交换方法对待排序元素有多次不必要的临时写操作,看下面一个实现,会消除这一点。

转移

仅在最后一步时执行写操作:

insertion sort, shifting illustration

该方法在插入排序中最常用。

使用二分查找

使用二分查找来为插入元素寻找位置比上面的方法明显更高效。此时我们应该叫它二分插入排序。这种排序方法和上面相比,比较的次数会减少,不过整体的平均复杂度依然是theta(n^2)。从实用的角度来讲,这种提高是可以忽略的,因为插入排序本来就是用于小型数组的排序,比较的次数本就不会很多。

复杂度分析

不管插入的方式如何,插入排序的整体平均复杂度为theta(n^2)。需要的平均写操作数为theta(n^2),而比较操作数和插入方法有关,如果使用交换和转移,比较数目为theta(n^2),如果使用二分查找插入,则为theta(nlogn)。

从实用角度将,插入排序应用于小型数组(8到12)的性能比其他二次的排序算法好,如选择排序和冒泡排序。


实现

Java实现

void insertionSort(int[] arr) {      int i, j, newValue;      for (i = 1; i < arr.length; i++) {            newValue = arr[i];            j = i;            while (j > 0 && arr[j - 1] > newValue) {                  arr[j] = arr[j - 1];                  j--;            }            arr[j] = newValue;      }}

C++实现

void insertionSort(int arr[], int length) {      int i, j, tmp;      for (i = 1; i < length; i++) {            j = i;            while (j > 0 && arr[j - 1] > arr[j]) {                  tmp = arr[j];                  arr[j] = arr[j - 1];                  arr[j - 1] = tmp;                  j--;            }      }}


0 0
原创粉丝点击