CLRS笔记2:算法入门

[b]1,增量法(incremental)[/b]
例:插入排序(insertion sort)
ruby版本:
[code]
def insertion_sort(a)
a.each_with_index do |el,i|
j = i - 1
while j >= 0
break if a[j] <= el
a[j + 1] = a[j]
j -= 1
end
a[j + 1] = el
end
end
[/code]
erlang版本:
[code]
-module(insertion_sort).
-export([sort/1]).

sort(List) ->
sort(List, []).

sort([H | T], Acc) ->
sort(T, insert(H, Acc));

sort([], Acc) ->
Acc.

insert(E, Acc = [H | _T]) when E < H ->
[E | Acc];

insert(E, [H | T]) when E >= H ->
[H | insert(E, T)];

insert(E, []) ->
[E].
[/code]
循环了1+2+3+...+(n-1) = n(n+1)/2次,时间为Θ(n^2)

[b]2,分治法(divide-and-conquer)[/b]
例:合并排序(merge sort)
ruby版本:
[code]
def merge(l, r)
result = []
while l.size > 0 and r.size > 0 do
if l.first < r.first
result << l.shift
else
result << r.shift
end
end
if l.size > 0
result += l
end
if r.size > 0
result += r
end
result
end

def merge_sort(a)
return a if a.size <= 1
middle = a.size / 2
left = merge_sort(a[0, middle])
right = merge_sort(a[middle, a.size - middle])
merge(left, right)
end
[/code]
erlang版本:
[code]
-module(merge_sort).
-export([sort/1]).

sort([]) -> [];
sort([L]) -> [L];
sort(List) ->
{Left, Right} = lists:split(length(List) div 2, List),
merge(sort(Left),sort(Right)).
merge(L, []) -> L;
merge([], R) -> R;
merge([L|Left], [R|_]=Right) when L < R ->
[L | merge(Left, Right)];
merge(Left, [R|Right]) ->
[R | merge(Left, Right)].
[/code]
运行了n/2+n/4+n/8+... = n次,时间为Θ(n)


回家又看了一下merge sort的时间复杂度的计算方法,发现自己想错了:
merge时间并不是n/2 n/4 n/8的数列
一个数组一直切分切分,最后如果切分到size = 1时,可以认为merge时间为n/2,但向上归并时size > 1时,这时的merge时间不是简单的上级的1/2

正确的公式T(n) = 2T(n/2) + cn,其中cn表示合并两个子数组的时间,为n的线性函数,分解时间为Θ(1),可以忽略
算法导论对merge sort的时间复杂度的推算方法是扩展递归树:
T(n)
||
cn + T(n/2) + T(n/2)
||
cn + (cn/2 + cn/2) + T(n/4) + T(n/4) + T(n/4) + T(n/4)
||
...
cn + (cn/2 + cn/2) + (cn/4 + cn/4 + cn/4 + cn/4) + .... + (c + c + c + ...)
||
cn + (cn/2 + cn/2) + (cn/4 + cn/4 + cn/4 + cn/4) + .... + (cn*(1/2)^x + cn*(1/2)^x + cn*(1/2)^x + ...)

cn*(1/2)^x = c
x = lgn

即一共有lgn + 1层,而每层加起来的和又是cn,所以T(n) = cn*(lgn + 1) = Θ(nlgn)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值