您的位置:首页 > 其它

直接插入排序

2015-05-17 19:18 169 查看
直接插入排序(Straight Insertion Sort) 
基本思想:
先把要排序的数组分成两部分,第一部分只包含第一个元素,天然有序,而第二部分则包含了数组中除开第一个元素剩余的所有元素。然后依次将第二部分中的每一个元素插入到已经有序的第一部分中,并且仍保持第一部分有序。每次插入一个元素,有序部分将增加一个元素。
重复此过程,直到最后有序部分包含所有元素。

当然,有序部分也可以是最后一个元素。

好了,话不多说,上图。

初始数组如下:



第一步:进行划分。第一个元素 4 为初始有序部分,其余元素为无序部分。即红线左边为有序部分,右边为无序部分。



第二步:从无序部分的元素中依次找出一个元素插入到左边,并且保持插入后仍然有序。这里先将元素 2 插入到左边的有序部分。


<第一次插入>        2
< 4,因此将 2 插入到 4 的左边


此时,有序部分变成了 2、4, 接着,

第三步:将元素 3 插入到左边,并且保持插入后仍然有序。


<第二次插入>        3
< 4,3 > 2,因此将 3 插入到 2 和 4 的中间


此时,有序部分变成了 2、3、4, 继续,

第四步:将元素 5 插入到左边,并且保持插入后仍然有序。


<第三次插入>        5
> 4,将 5 直接插入到 4 的右边


此时,左边的有序部分变成了 2、3、4、5, 接着

第五步:将元素 1 插入到左边,并且保持插入后仍然有序。


<第四次插入>        1
< 5, 1 < 3, 1 < 2, 因此将 1 插入到 2 的左边


此时,所有元素都已经插入到了左边的有序部分,数组已经有序,排序结束。

其实,我们也看到了,插入排序的核心在于将无序部分元素插入到有序部分中,并且还得保持仍然有序。

就上边的情况来说,设定的是第一个元素为初始有序部分,余下元素为无序部分。其实,前面提到过,最后一个元素为初始有序部分也是可以的。完整的测试代码中包含了这种情况。

算法实现:    

/**
* 插入排序,最前一位作为有序部分
* @param arr 待排序数组
*/
public void insertionSort(int[] arr) {
int length = arr.length;
int j = 0;
int temp = 0;

for (int i = 1; i < length; i++) {
temp = arr[i]; // 存储待插入元素的值
for (j = i; j > 0; j--) { // 找到一个合适的插入位置
if (arr[j - 1] > temp)
arr[j] = arr[j - 1]; // 依次向右移动已经排好序的元素,为待插入元素留出位置
else // 若后面的不小于前面的,则不用移动,因为前面的已经排好序了
break;
}
arr[j] = temp; // 将待插入元素插入到指定位置
}
}


算法测试:

package algorithms;

import java.util.Arrays;
import java.util.Random;

/**
* 插入排序
* @author Wll
*
*/
public class InsertionSortTest {
public static void main(String[] args) {
int[] arr = getRandomArray(9, 1000);
int[] arr2 = Arrays.copyOf(arr, arr.length);
System.out.println("插入排序");
System.out.print("初始数组:");
printArray(arr);

System.out.println("第一位 " + arr[0] + " 为初始有序部分:");
insertionSort(arr);

System.out.println();

System.out.println("最后一位 " + arr2[arr2.length - 1] + " 为初始有序部分:");
insertionSort2(arr2);
}

/**
* 插入排序,最前一位作为有序部分
* @param arr 待排序数组
*/
private static void insertionSort(int[] arr) {
int length = arr.length;
int j = 0;
int temp = 0;

for (int i = 1; i < length; i++) {
temp = arr[i]; // 存储待插入元素的值
for (j = i; j > 0; j--) { // 找到一个合适的插入位置
if (arr[j - 1] > temp)
arr[j] = arr[j - 1]; // 依次向右移动已经排好序的元素,为待插入元素留出位置
else // 若后面的不小于前面的,则不用移动,因为前面的已经排好序了
break;
}
arr[j] = temp; // 将待排序元素插入到指定位置

// 打印每一趟排序的结果
System.out.print("第" + i + "趟插入" + temp + ": ");
for (int k = 0; k < length; k++) {
if (k == (i + 1))
System.out.print("|"); // 使用|分隔有序和无序部分

if (k == j)
System.out.print("▲"); // 为插入元素做标记

System.out.print(arr[k] + "  ");
}
System.out.println("\n");
}
}

/**
* 插入排序,最后一位作为有序部分
* @param arr 待排序数组
*/
private static void insertionSort2(int[] arr) {
int length = arr.length;
int j = 0;
int temp = 0;

for (int i = length - 2; i >= 0; i--) {
temp = arr[i];
for (j = i; j < length - 1; j++) {
if (arr[j + 1] < temp)
arr[j] = arr[j + 1];
else
break;
}
arr[j] = temp;

// 打印每一趟排序的结果
System.out.print("第" + (length - i - 1) + "趟插入" + temp + ": ");
for (int k = 0; k < length; k++) {
if (k == j)
System.out.print("▲"); // 为插入元素做标记

System.out.print(arr[k] + "  ");

if (k == i-1)
System.out.print("|"); // 使用|分隔有序和无序部分
}
System.out.println("\n");
}
}

/**
* 打印数组
* @param arr 待打印数组
*/
private static void printArray(int[] arr) {
int length = arr.length;
for (int i = 0; i < length; i++)
System.out.print(arr[i] + " ");
System.out.println();
System.out.println();
}

/**
* 获得一个随机整型数组
* @param size 数组大小
* @param limit 数组元素大小的上限
* @return 一个随机数组
*/
private static int[] getRandomArray(int size, int limit) {
int[] arr = new int[size];
Random random = new Random();
for (int i = 0; i < size; i++)
arr[i] = random.nextInt(limit);

return arr;
}
}


运行情况:




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: