我知道如何从简单的递归算法中找到递归关系。
For e.g.
QuickSort(A,LB, UB){
key = A[LB]
i = LB
j = UB + 1
do{
do{
i = i + 1
}while(A[i] < key)
do{
j = j - 1
}while(A[j] > key)
if(i < j){
swap(A[i]<->A[j])
}while(i <= j)
swap(key<->A[j]
QuickSort(A,LB,J-1)
QuickSort(A,J+1,UB)
}
T(n) = T(n - a) + T(a) + n
在上面的递归算法中,很容易理解每次递归调用后输入大小是如何减少的。但是如何找到一般算法的递归关系,这不是递归的,但也可能是迭代的。所以我开始学习如何将迭代算法转换为递归,以便于查找递归关系。 我找到了这个链接http://refactoring.com/catalog/replaceIterationWithRecursion.html。 我曾经将我的线性搜索算法转换为递归。
LinearSearch(A,x,LB,UB){
PTR = LB
while(A[PTR]!=x && PTR<=UB){
if(PTR==UB+1){
print("Element does not exist")
}
else{
print("location"+PTR)
}
}
}
got converted to
LinearSearch(A,x,LB,UB){
PTR=LB
print("Location"+search(A,PTR,UB,x))
}
search(A,PTR,UB,x){
if(A[PTR]!=x && PTR<=UB){
if(PTR==UB+1){
return -1
}
else{
return search(A,PTR+1,UB,x)
}
}
else{
return PTR
}
}
This gives the recurrence relation to be T(n) = T(n-1) + 1
但我想知道这是找到任何算法的递归关系的正确方法吗? 另外,我不知道如何找到多个参数增加或减少的算法的递归关系。
e.g.
unsigned greatest_common_divisor (const unsigned a, const unsigned b)
{
if (a > b)
{
return greatest_common_divisor(a-b, b);
}
else if (b > a)
{
return greatest_common_divisor(a, b-a);
}
else // a == b
{
return a;
}
}
答案 0 :(得分:1)
首先,algorithms are very flexible所以你不应期望有一个涵盖所有这些规则的简单规则。
那就是说,我认为对你有帮助的一件事是更多地关注你传递给你的算法的输入结构而不是你自己的算法。例如,考虑您在帖子中显示的QuickSort。如果你看一下那些嵌套的do-whiles,你可能会猜到它的O(N ^ 2),而实际上是O(N)。通过查看输入更容易找到真正的答案:我总是增加并且j总是减少,当它们最终彼此相遇时,阵列的每个N个索引都将被访问一次。
另外,我不知道如何找到多个参数增加或减少的算法的递归关系。
那么,那些算法肯定比单变量的算法更难。对于您用作示例的欧几里德算法,复杂度实际上是not trivial来计算出来的,它涉及到考虑最大公约因子,而不仅仅是查看算法实现的源代码。