1.希尔排序算法
/***
*
* @author xiaoo_gan
* 排序算法:希尔排序算法
* 实现过程:希尔排序的思想是使数组中任意间隔为h的元素都是有序的。
*
*
*
* 测试:
* input: S H E L L S O R T E X A M P L E
* output:
* h = 13 第 0 轮:S H E L L S O R T E X A M P L E
* h = 4 第 1 轮:P H E L L S O R T E X A M S L E
* h = 1 第 2 轮:L E E A M H L E P S O L T S X R
* h = 0 第 3 轮:A E E E H L L L M O P R S S T X
*/
public class Shell {
// 排序算法实现
public static void sort(Comparable[] a) {
int N = a.length;
int h = 1;
int cnt = 0;
while (h < N / 3) { // 增幅序列:1,4,13,40,121,364,1093,...
h = 3 * h + 1;
}
while(h >= 1) {
for (int i = h; i < N; i++) {
//将a[i] 插入到a[i-h], a[i-2*h],a[i-3*h],... 中去
for (int j = i; j >= h && less(a[j], a[j-h]); j -= h) { //升序
//for (int j = i; j >= h && less(a[j-h], a[j]); j -= h) { //降序
exch(a, j, j - h);
System.out.printf("h = %2d 第 %d 轮:", h, cnt);
show(a);
}
}
System.out.println();
cnt ++;
h /= 3;
}
}
// 判断第一个数是否大于第二个数
private static boolean less(Comparable v, Comparable w) {
return v.compareTo(w) < 0;
}
// 交换两个数的位置
private static void exch(Comparable[] a, int i, int j) {
Comparable t = a[i];
a[i] = a[j];
a[j] = t;
}
// 打印数组
private static void show(Comparable[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
// 判断是否已排序
public static boolean isSorted(Comparable[] a) {
for (int i = 0; i < a.length; i++) {
if (less(a[i], a[i-1])) {
return false;
}
}
return true;
}
public static void main(String[] args) {
String[] a = {"S", "H", "E", "L", "L", "S", "O", "R", "T", "E", "X", "A", "M", "P", "L", "E"};
sort(a); //排序
assert isSorted(a); //判断数组是否有序
//show(a); //打印数组
}
}
2.希尔排序算法的轨迹图
/***
*
* @author xiaoo_gan
* 希尔排序的轨迹图
* 2.1.9 按照算法Insertion给出插入排序是如何将数组 E A S Y Q U E S T I O N 排序的。
*/
public class TraceShell {
private static double row;
public TraceShell() {
row = 0;
}
private static void header(String[] a) {
int N = a.length;
StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.text(N * 3 / 7.0, -2, "希尔排序算法轨迹");
StdDraw.text(-2.5, -1, "输入");
for (int i = 0; i < N; i++) {
StdDraw.text(i, -1, a[i]);
}
StdDraw.setPenColor(StdDraw.BOOK_RED);
StdDraw.line(-3.5, -0.5, N - 0.5, -0.5);
}
public static void sort(String[] a) {
int N = a.length;
int h = 1;
while (h < N / 3) {
h = 3 * h + 1;
}
while (h >= 1) {
boolean flag = true;
for (int i = h; i < N; i++) {
int min = i;
for (int j = i; j >= h; j -= h) {
if(less(a[j], a[j-h])) {
min = j - h;
exch(a, j-h, j);
}
}
if(flag) {
flag = false;
StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.text(-2.5, row, h + "-sort");
}
draw(a, i, h, min);
row += 0.7;
}
row = row + 0.3;
h /= 3;
}
}
private static void draw(String[]a, int ith,int h, int min) {
StdDraw.setPenColor(StdDraw.BLACK);
for (int i = 0; i < a.length; i++) {
if (i == min) {
StdDraw.setPenColor(StdDraw.BOOK_RED);
} else if (i > min && i <= ith && ((i - min) % h == 0)) {
StdDraw.setPenColor(StdDraw.BLACK);
} else {
StdDraw.setPenColor(StdDraw.LIGHT_GRAY);
}
StdDraw.text(i, row, a[i]);
}
}
private static boolean less(String a, String b) {
return (a.compareTo(b) < 0);
}
private static void exch(String[] a, int i, int j) {
String swap = a[i];
a[i] = a[j];
a[j] = swap;
}
private static void footer(String[] a) {
StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.text(-2.5, row, "输出");
for (int i = 0; i < a.length; i++) {
StdDraw.text(i, row, a[i]);
}
}
public static void main(String[] args) {
String s = args[0];
int N = s.length();
String[] a = new String[N];
for (int i = 0; i < N; i++) {
a[i] = s.substring(i, i + 1);
}
int height = 0;
int h = 1;
while(h < N / 3) {
height += N - h + 1;
h = 3 * h + 1;
}
height += N - h + 1;
StdDraw.setCanvasSize(30 * (N + 4), 30 * (height + 3));
StdDraw.setXscale(-4, N + 1);
StdDraw.setYscale(height + 1, -2);
StdDraw.setFont(new Font("SansSerif", Font.PLAIN, 13));
header(a);
sort(a);
footer(a);
}
}