12 October 2013

今天在github上开了一个新项目,专门记录自己学习算法的经历,《算法导论》这个大部头在我书桌上躺的时间够长了,也该活动活动筋骨了。

算法一直以来被我看做是高智商人群的玩具,那是一种追求更高的速度,更美的结构的心理所驱动,这无疑也为算法宝盒增加了不少的解谜难度。

闲话少说,来看看今天完成的两个排序算法——插入排序和归并排序。

插入排序在我看来,其主要的思想就是,每到来一个新的元素,前面的元素是已经排好序的,只需把这个新元素与前面元素依次比较,在合适的位置插入即可。

for (j = 1; j < MAXNUM; j++) {
		key = randomNum[j];
		i = j - 1;
		while ((i >= 0) && (randomNum[i] > key)) {
			swap = randomNum[i + 1];
			randomNum[i + 1] = randomNum[i];
			randomNum[i] = swap;
			i--;
		}
		randomNum[i + 1] = key;
	}

不算很难,那么我们用python画个图看一看到底是什么情况。

我们可以看到,基本是指数增长,复杂度是n^2。

这里我还用scheme实现了插入排序的一个版本:

(define (sort lst key)
  (if (null? lst)
	(list key)
	(if (> key (car lst))
	  (cons (car lst) (sort (cdr lst) key))
	  (cons key lst))))


(define (insertSort new_lst old_lst)
  (if (null? old_lst)
	new_lst
	(insertSort (sort new_lst (car old_lst))
				(cdr old_lst))))

(define lst (list 6 5 4 7 10 2 11))
(define new (list (car lst)))
(define old (cdr lst))

;;testing
;;(insertSort new old)

函数式编程语言实现这类算法还不是很容易,因为表结构这类线性结构,很难从中间某处开始查找(也可能是自己学的还不够),归并算法还没想到该如何实现。

再来看看归并排序,其实就是分而治之的思想,一部分一部分的排序,最后合为一体。

void merge(int data[], int p, int q, int r)
{
	int n1, n2;
	n1 = q - p + 1;
	n2 = r - q;

	int L[n1 + 1], R[n2 + 1];
	int i, j, k;
	for (i = 0; i < n1; i++)
		L[i] = data[p + i];
	for (j = 0; j < n2; j++)
		R[j] = data[q + j + 1];
	
	L[n1] = MAXNUM;
	R[n2] = MAXNUM;
	i = j = 0;
	for (k = p; k < r + 1; k++)
		if (L[i] <= R[j]) {
			data[k] = L[i];
			i++;
		} else {
			data[k] = R[j];
			j++;
		}
}

void mergeSort(int data[], int p, int r)
{
	int q;

	if (p < r) {
		q = (p + r) / 2;
		mergeSort(data, p, q);
		mergeSort(data, q + 1, r);
		merge(data, p, q, r);
	}
}

int main()
{	
	mergeSort(randomNum, 0, MAXNUM - 1);
	/*	
	int i;
	for (i = 0; i < MAXNUM; i++)
		printf("%d ", randomNum[i]);
	*/
	return 0;
}

看起来要比插入排序复杂一些,可别小看归并排序,那简直是so damn fast! 我们知道归并排序是nlogn的复杂度,试想一下,这种排序在数据规模为100000的情况下,要比插入排序快上100000/6那么多,使得我很难找数据测试。数据太小了秒排,数据太大了,编译的时间远远超过运行时间,而且又没有明显走势。我们还是找些10的次方来测试吧。

恩,还是很快就排完了。归并排序真的很快!

排序的方法有很多,我会在后面一点点实现,不过就单单排序这一类算法而言,确实体现了人类的智慧和算法美,ok,今天先写到这里,后续再接再厉!



blog comments powered by Disqus