Princeton Algorithm ElementarySort

11 篇文章 0 订阅

1. Selection Sort

Algorithm:一个指针遍历数组,另一个指针遍历后面位置的值并找到最小值,与当前指针位置的值进行交换。时间复杂度O(N^2).

public void selectionSort(int[] a) {
	int size = a.length;
	for (int i = 0; i < size; i++) {
		// 选择当前遍历到的点作为最小值
		int min = i;
		// 然后遍历后面的数,找到最小值,并且替换到当前位置
		for (int j = i + 1; j < size; j++) {
			if (less(a[j], a[min])) {
				min = j;
			}
			// 注意这里替换的是min而不是j, 因为当取到最小值的时候,min并不会被j赋值,只有j位置比min小的时候,才会被赋值,所以j会在取到min之后再向后移动一次
			exch(a, i, min);
		}
	}
}

(1) 无论input的order, 都是二次方的runtime
(2)不适用小的数据输入,因为每次都要进行exchange(线性复杂度)

2. Insertion Sort

Algorithm:把数组分为可见和不可见两部分,两个指针i和j,遍历到的是可见部分, 同时遍历数组,j从i的位置向后移动,如果比前一位小,那么交换位置。

public void sort(int[] a) {
	int size = a.length;
	for (int i = 0; i < size; i++) {
		// j 从当前位置开始,向前遍历,如果j比前一位小,那么交换
		for (int j = i; j > 0; j--) {
			if (less(a[j], a[j-1])) {
				exch(a, j, j-1);
			}else {
				// 如果j不比前面任意一个数小了,那么结束当前的for循环(因为前面的数组是有序的)
				break;
			}
		}
	}
}

**注意上面两个排序的数组int[] a 都是Comparable[] a, 即是具有比较性质的
((1/4 N^2) compares, and (1/4N^2) exchange)
** Worstcase, 如果数组是降序的,那么每一次都要移动到最前面,runtime θ(N^2), 每次只移动一个位置导致其效率不高
** 那么InsertionSort适用于什么情况呢?
适用于数组中有部分是排序的!!!(这种情况insertionSort的时间复杂度是Linear的)

3.ShellSort

Algorithm: 实际上就是InsertionSort的改良,InsertionSort是一次移动一个位置,Shell一次向前移动h个位置(j指针,i指针从h位置开始向后移动)。
适用情况:1. Linear time for almost-sorted array.
2. Small array (a couple of hundreds elements).
3. Some clever sorting algorithms perform amost-sorting and then let insertion sort take over.
Shell sort is a little bit better than insertion sort.

public void sort(int[] a) {
	int size = a.length;
	int h = 1;
	// 最佳适用的h(来自于经验)
	while (h < size/3) {
		h = h*3 +1;
	}
	while (h >= 1) {
		// 从h处开始遍历
		for (int i = h; i < size; i++) {
			// j 从h处向前遍历可见的部分, 并前每次移动h个位置,如果小于前面的,那么交换 
			for (int j = i; j >= h && less(a[j], a[j-h]); j = j - h) {
				exchan(a, j , j-h);
			}
		}
		h = h / 3;
	}
}

在这里插入图片描述
**其实就是一点一点的排,对于不大的数组是有用的

4. Shuffling

public void sort(int[] a) {
	int size = a.length;
	for (int i = 0; i < size; i++) {
		int random = StdRandom.uniform(i+1);
		exch(a, i , r);
	}
}

5. Convex Hull

public void sortConvextHull(Comparable[] p) {
	Stack<Point> hull = new Stack<>();
	// 根据y坐标排序
	Arrays.sort(p, Point.Y_Order());
	// 根据和p[0](也就是y坐标最小的点)的角度排序
	Arrays.sort(p, p[0].polarOrder());
	hull.push(p[0]);
	hull.push(p[1]);
	for (int i = 2; i < size; i++) {
		// 弹出最后插入的角
		Point top = hull.pop();
		while (Point.ccw(hull.peek, top, p[i]) <= 0) {
			// 当不是逆时针的时候,
			// top 还是前面那个角
			top = hull.pop();

		}
		// repush the top
		hull.push(top);
		hull.push(p[i]);
	}
}
// counterclockwise
public static int ccw(Point a, Point b, Point c) {
	double area2 = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
	.......
	// 只有大于零才是逆时针的
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值