最近工作轻松了点,抽空看了一下排序算法,写下来一点自己的一些体会看法。如果哪天忘了也方便捡回来,网上有蛮多瞎转的,记录下来,以免被误导理解错了。
一.直接插入排序
直接插入排序的思想是在一组待排序的数组R[0.1...n]中,分为两部分,第一部分为已排序的,另一部分为待排序的。第一部分初始数据只有R[0](只有一个数据当然是有序的啦),第二部分是R[1...n]。接下来在第二部分按顺序去数据插入在第一部分有序的位置。调度如下()内为有序部分红色数字为该次插入到有序序列中的数字:
1:[(2), 5, 1, 4, 3, 9, 7]
2:[(2,5), 1, 4, 3, 9, 7 ]---[(2, 5, 5), 4, 3, 9, 7 ]---[(2, 2, 5),4 , 3, 9, 7]---[(1, 2, 5), 4, 3, 9, 7]
3:[(1, 2, 5), 4, 3, 9, 7]
4:[(1, 2,4, 5), 3, 9, 7]
5:[(1, 2,3, 4, 5), 9, 7]
6:[(1, 2, 3, 4, 5,9), 7]
7:[(1, 2, 3, 4, 5, 7, 9)]
java代码如下:
<span style="font-size:18px;">private static void insertSort(int[] data, int length) {
//从左往右遍历数组插入数据
for (int i = 1; i < length; i++) {
//带插入数据小于有序部分最后一个数据开始寻找带插入位置,相反直接检查下一个带插入数据,这个数据直接就在有序部分的最后一个也是最大的一个
if (data[i] < data[i - 1]) {
//记录下带插入数据
int temp = data[i];
//从带插入数据往前遍历,带插入数据小于前面的数据就将前面数据赋值给后面数据。具体不走如上第二步,后面底部均已省略。
int j = i;
while(j > 0 && temp < data[j - 1]){
data[j] = data[j - 1];
j--;
}
//插入带插入数据
data[j] = temp;
}
//打印数组
print(data);
}
}</span>
二.shell排序
希尔排序是一种插入排序算法,它出自D.L.Shell,因此而得名。Shell排序又称作缩小增量排序。首先选取小于data.length / 3的数h1作为第一个增量,h1由以下代码得出:
<span style="white-space:pre"> </span><span style="font-size:18px;">int h = 1;
if(h <= length / 3){
h = h * 3 + 1;
}</span>
之后的增量h2 = (h1 - 1) / 3, h3 = (h2 - 1) / 3以此类推,总之h1 > h2 > h3 > ... > hn(hn=1)。然后每组有h1个数据,之后再每组第一个比较,比较方法和直接插入排序比较方法一样。当每组相对应位置比较完了之后。得到增量h2的值继续比较。其实直接插入排序是增量为1的shell排序。可以得到第一个增量是4,所以每4个一组。
具体的实现如下:
增量:4
1:[(6, 7, 5, 1), (2, 5, 2, 8) , (3 , 9)]
2:[(2, 7, 5, 1), (6, 5, 2, 8) , (3 , 9)]
3:[(2, 7, 5, 1), (3, 5, 2, 8) , (6 , 9)]
4:[(2, 5, 5, 1), (3, 7, 2, 8) , (6 , 9)]
5:[(2, 5, 5, 1), (3, 7, 2, 8) , (6 , 9)]
6:[(2, 5, 2, 1), (3, 7, 5, 8) , (6 , 9)]
7:[(2, 5, 2, 1), (3, 7, 5, 8) , (6 , 9)]
增量:1
8:[2, 5, 2, 1, 3, 7, 5, 8, 6, 9]
9:[2, 2, 5, 1, 3, 7, 5, 8, 6, 9]
10:[1, 2, 2, 5, 3, 7, 5, 8, 6, 9]
11:[1, 2, 2, 3, 5, 7, 5, 8, 6, 9]
12:[1, 2, 2, 3, 5, 7, 5, 8, 6, 9]
13:[1, 2, 2, 3, 5, 5, 7, 8, 6, 9]
14:[1, 2, 2, 3, 5, 5, 7, 8, 6, 9]
15:[1, 2, 2, 3, 5, 5, 6, 7, 8, 9]
16:[1, 2, 2, 3, 5, 5, 6, 7, 8, 9]
private static void shellSort(int[] data, int length){
int h = 1;
if(h <= length / 3){
h = h * 3 + 1;
}
System.out.println("增量h = " + h);
while(h > 0){
for (int k = h; k > 0; k--) {
for (int i = 2 * h - k; i < length; i += h) {
if(data[i] < data[i - h]){
int temp = data[i];
int j = i - h;
while(j >= 0 && temp < data[j]){
data[j + h] = data[j];
j -= h;
}
data[j + h] = temp;
}
print(data);
}
}
h = (h - 1) /3;
System.out.println("增量h = " + h);
}
}