算法导论学习笔记之算法基础篇

文章链接:http://blog.csdn.net/jewangs/article/details/52424313

一、插入排序

插入排序属于原址排序,算法在数组A中重排元素,算法思想与玩扑克牌时依次将抓到的牌放到手中合适的位置一致,当输入完成时,手中的牌即已完成排序。

	插入排序(A)
		for j = 2..A.length setp = 1	//A 下标从 1 开始计数
			key = A[j]
			i = j - 1
			while i > 0 && A[i] > key
				A[i + 1] = A[i]
				--i
			A[i + 1] = key         //当 i == 0  ||  A[ i ] <= key 时,插入寻找退出,此时的 key 应该放到 A[ i ] 的下一个单元 A[ i ]+ 1

算法的时间复杂度为O(n^2)

二、分治模式

分治思想:将原问题分解为几个规模较小的但类似于原问题的子问题,递归的求解这些子问题,然后合并这些子问题的解来建立原问题的解。

步骤:

分解:分解原问题为若干个子问题,这些子问题是原问题的规模较小的的实例

解决:递归地求解这些子问题,子问题足够小,可直接求解

合并:合并子问题的解为原问题的解

算法的核心在于 合并 操作,对于数组 A ,p,q,r 为数组下标,满足 p <= q < r,假定子数组 A[ p..q ] 和 A[ q + 1,r] 都已排好序,下面的例程将合并这两个子数组形成单一

的已排好序的子数组A[ p..r ]:

合并(A,p,q,r)
	n1 = q - p + 1
	n2 = r - q
	new array L[ n1 + 1 ] and R[ n2 + 1 ]
	for i = 1..n1 step = 1
		L[ i ] = A[ p + i - 1]            //L数组为 [p,q]
	for j = 1..n2 step = 1
		R[ j ] = A[ q + j ]
	L[ n1 + 1 ] = 哨兵
	R[ n2 + 1 ] = 哨兵
	i = j = 1
	for k = p .. r
		if L[ i ] <= R[ j ]
			A[ k ] = L[ i ]
			++i
		else
			A[ k ] = L[ j ]
			++j	

有了这个合并例程,根据分治思想,归并排序算法水到渠成:

归并排序(A,p,r)
        if p < r
		q = (p + r)/2	//向下取整
		归并排序(A,p,q)
		归并排序(A,q + 1,r)
		合并(A,p,q,r)
算法的时间复杂度为O(nlgn)

三、递归式的求解

归并排序算法复杂度的计算符合递归式:

           T(n) = aT(n/b) + f(n)

其中,a >= 1,b > 1是常数,f(n) 是渐进正函数,关于这个递归式的求解有很多种方法,最常用的当属 主方法,主方法依赖于主定理:

定理:令 a >= 1,b > 1 是常数,f(n) 是一个函数,T(n)是定义在非负整数上的递归式:T(n) = aT(n/b) + f(n)

那么,T(n) 有如下渐进界:

       1.若存在某常数 c > 0 有 f(n) = O(n^(logb(a-c))),则T(n) =O(n^(logb(a)))

       2.若 f(n) = O(n^(logb(a))),则 T(n) = O(n^(logb(a))lgn)

       3.若对于某常数 c > 0 有 f(n) = Ω(n^(logb(a + c))),且对某个常数 c < 1 和所有足够大的 n 有 af(n/b) <= cf(n),则T(n)=O(f(n))


你可能感兴趣的:(算法)