[算法之排序]希尔排序算法 (java实现)

7 篇文章 0 订阅
7 篇文章 0 订阅

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);
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值