1、插入排序
插入排序是一种很常用的排序算法。它的基本思想是:一个未排序的数据分成两部分,前半部是已经排序的,后半部分是未排序的。在进行排序时,只需要在未排序的部分中选择一个元素,将其插入到前面有序的数组中即可。最终未排序的部分会越来越少,直到为0,那么排序就完成了。
平均时间复杂度 O(n2) 最好情况是 O(n) 最差时间是O(n2)
代码如下:
public class InsertSortTest {
public static void main(String args[]) {
int a[] = { 1, 5, 3, 6, 34, 45, 2, 54, 415 };
insertSort(a);
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
}
}
public static void insertSort(int a[]) {
int len = a.length;
int i, j, key;
for (i = 1; i < len; i++) {
j = i - 1;
key = a[i];
while (j >= 0 && key < a[j]) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = key;
}
}
}
2、希尔排序
希尔排序是对插入排序的扩展,它将整个数组根据间隔h分割为若干个子数组。子数组相互穿插在一起,每一次排序时,分别对每一个子数组进行排序。
希尔排序的一个主要优点是,即使一个较小的元素在数组的末尾,由于每次元素移动都以h为间隔进行,因此数组末尾的小元素可以在很少的交换次数下,就被置换到最接近元素最终的位置的地方。
平均时间复杂度 O(n1.3) 最好情况是 O(n) 最差时间是O(n2)
public static void main(String args[]) {
int a[] = { 1, 5, 3, 6, 34, 45, 2, 54, 415 };
shellSort(a);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
public static void shellSort(int a[]) {
int len = a.length;
int h = 1;
while (h <= len / 3) {
h = h * 3 + 1;
}
while (true) {
for (int n = 0; n < h; n++) {
int i, j, key;
for (i = n+h; i < len; i =i+h) {
if (a[i] < a[i - h]) {
j = i - h;
key = a[i];
while (j >= 0 && a[j] > key) {
a[j + h] = a[j];
j -= h;
}
a[j + h] = key;
}
}
}
if(h==1){
break;
}
h = (h - 1) / 3;
}
}
}
3、并行改进希尔排序
在子数组之间进行的插入排序是互相不会干扰,因此可以并行进行。
public class ParllShellSortTest {
static int[] a = { 1, 4, 2, 5, 6, 3 };
static ExecutorService pool = Executors.newCachedThreadPool();
public static class ShellSortTask implements Runnable {
int x = 0;
int h = 0;
CountDownLatch l;
public ShellSortTask(int x, int h, CountDownLatch latch) {
this.x = x;
this.h = h;
this.l = latch;
}
public void run() {
int i, j, key;
for (i = x + h; i < a.length; i = i + h) {
if (a[i] < a[i - h]) {
j = i - h;
key = a[i];
while (j >= 0 && a[j] > key) {
a[j + h] = a[j];
j -= h;
}
a[j + h] = key;
}
}
l.countDown();
}
}
public static void pShellSort(int[] arr) throws InterruptedException {
// 计算出最大的n值
int h = 1;
CountDownLatch lathc = null;
while (h <= arr.length / 3) {
h = h * 3 + 1;
}
while (h > 0) {
System.out.println("h=" + h);
lathc = new CountDownLatch(h);
for (int x = 0; x < h; x++) {
pool.submit(new ShellSortTask(x, h, lathc));
}
lathc.await();
// 计算下一个h值
h = (h - 1) / 3;
}
pool.shutdown();
}
public static void main(String[] args) throws InterruptedException {
System.out.println(Arrays.toString(a));
pShellSort(a);
for (int i : a) {
System.out.print(i);
}
System.out.println("end");
}
}
PS:《实战Java高并发程序设计》这本书写的很好,但是第五章 中的希尔排序应该是写错了。