小橙书阅读指南(三)——插入排序

算法描述:通常人们在整理扑克的方法是一张一张的来,将每一张牌插入到其他已经有序的牌中的适当位置。在算法的实现中,为了给要插入的元素腾出1个空间,我们需要将其余所有元素在插入之前都向右移动1位。这种算法叫插入算法。

算法图示:

 算法解释:在基础版本中通常的做法是,当新元素需要被插入有序数组的时候,从右向左依次交换。直到新元素到达它合适的位置。

Java代码示例:

import common.ArraysGenerator;
import common.Sortable;

import java.io.IOException;
import java.util.Arrays;

public class Insertion implements Sortable<Integer> {

    @Override
    public void sort(Integer[] array) {
        for (int i = 1; i < array.length; ++i) {
            for (int j = i; j > 0; --j) {
                // 如果数组 array[index] < array[index-1] 交换位置
                if (array[j] < array[j - 1]) {
                    int tmp = array[j];
                    array[j] = array[j - 1];
                    array[j - 1] = tmp;
                }
            }
        }
    }

    public static void main(String arg[]) throws IOException {
        // 从文件中读取数组的静态方法,指定文件名和数组长度
        Integer[] arr = ArraysGenerator.fromFile("disorder.txt", 1000000);

        Insertion insertion = new Insertion();
        long start = System.currentTimeMillis();
        insertion.sort(arr);
        long end = System.currentTimeMillis();

        System.out.println(Arrays.toString(arr));
        System.out.println(end - start);
    }
}

Qt/C++代码示例:

void Insertion::sort(int * arr, int len)
{
    for (int i = 1; i < len; ++i) {
        for (int j = i; j > 0; --j) {
            if (arr[j] < arr[j - 1]) {
                int tmp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = tmp;
            }
        }
    }
}

 

算法改进:仍然考虑人们整理扑克的情形,当需要插入的时候并仅仅做了一次操作并且当新牌不需要整理的时候直接摸下一张手牌。因此,要大幅提高插入排序的速度并不难, 只需要在内循环中将较大的元素都向右移动和不是交换两个元素的位置。

算法图示:

Java代码示例:

import common.Sortable;

public class InsertionImprove implements Sortable<Integer> {
    @Override
    public void sort(Integer[] array) {
        for (int i = 1; i < array.length; ++i) {
            // 如果array[index] 大于 有序数组array[0-index)的最后1位
            if (array[i] > array[i - 1]) {
                continue;
            }
            for (int j = i; j > 0; --j) {
                // 如果存在 array[j-1] <= array[index] < array[j]
                if (array[i] < array[j] && array[i] >= array[j - 1]) {
                    int tmp = array[i];
                    // 数组array[j-i)的部分 都向后移动1位
                    for (int n = i; n > j; --n) {
                        array[n] = array[n - 1];
                    }
                    array[j] = tmp;
                    break;
                }
            }
        }
    }
}

Qt/C++代码示例(略)

总的来说,插入排序对于部分有序数组十分搞笑,也很适合小规模数组。这很重要,因为这些类型的数组在实际应用经常出现,并且他们也是高级排序算法的中间过程。

相关链接:

Algorithms for Java

Algorithms for Qt

posted @ 2018-08-12 00:08  冷豪  阅读(271)  评论(0编辑  收藏  举报