我的想法是这是不可能的,因为数组可以是任何大小,没有使用任何形式的迭代就不能用C程序来实现。
function reverse(array)
if (length(array) < 2) then
return array
left_half = reverse(array[0 .. (n/2)-1])
right_half = reverse(array[(n/2) .. (n-1)])
return right_half + left_half
end
Original Input
1. ABCDEFHGIJKLMNOP Recurse
2. ABCDEFGH IJKLMNOP Recurse
3. ABCD EFGH IJKL MNOP Recurse
4. AB CD EF GH IJ KL MN OP Recurse
5. A B C D E F G H I J K L M N O P Terminate
6. BA DC FE HG JI LK NM PO Reverse
7. DCBA HGFE LKJI PONM Reverse
8. HGFEDCBA PONMLKJI Reverse
9. PONMLKJIHGFEDCBA Reverse
Reversed Output
function insertionSort(array)
if (length(array) == 1)
return array
end
itemToSort = array[length(array)]
array = insertionSort(array[1 .. (length(array)-1)])
find position of itemToSort in array
insert itemToSort into array
return array
end
function reverse(array)
for each index i = 0 to (length(array) / 2 - 1)
swap array[i] with array[length(array) - i]
next
end
Original Input
1. ABCDEFHGIJKLMNOP Divide
2. ABCDEFGH IJKLMNOP Divide
3. ABCD EFGH IJKL MNOP Divide
4. AB CD EF GH IJ KL MN OP Divide
5. A B C D E F G H I J K L M N O P Terminate
6. BA DC FE HG JI LK NM PO Conquer (Reverse) and Merge
7. DCBA HGFE LKJI PONM Conquer (Reverse) and Merge
8. HGFEDCBA PONMLKJI Conquer (Reverse) and Merge
9. PONMLKJIHGFEDCBA Conquer (Reverse) and Merge
Reversed Output
function reverse(array)
/* check terminating condition. all single elements are also reversed
* arrays of unit length.
*/
if (length(array) < 2) then
return array
/* divide problem in two equal sub-problems. we process the sub-problems
* in reverse order so that when combined the array has been reversed.
*/
return reverse(array[(n/2) .. (n-1)]) + reverse(array[0 .. ((n/2)-1)])
end
function reverse(array)
if length(array) < 2
return
end
swap array[0] and array[n-1]
reverse(array[1..(n-1)])
end
正如评论中所说,这取决于迭代的定义。
如果将递归仅仅视为迭代的一种“替代方法”,那么Kalai提出的递归解法就是正确答案。
如果将迭代理解为“检查每个元素”,那么问题就变成了数组翻转是否需要线性时间或者可以在次线性时间内完成。
为了证明数组翻转没有次线性算法,考虑一个包含n个元素的数组。假设存在一种算法A可以在不需要读取每个元素的情况下进行翻转。那么对于一些0到n-1范围内的i,存在一个元素a[i],该算法从未读取过它,但仍能够正确地翻转数组。(编辑:我们必须排除奇数长度数组的中间元素--请参见下面的注释--但这不影响算法是否在渐近情况下是线性还是次线性的)
由于算法从未读取元素a[i],所以我们可以改变其值。假设我们这样做了。那么该算法从未读取过这个值,却会产生与之前相同的翻转答案。但这个答案对于新值的a[i]来说是不正确的。因此,不存在一种能够在不至少读取每个输入数组元素(除一个)的情况下进行正确翻转的算法。因此,数组翻转具有O(n)的下限,因此需要迭代(根据此情况下的工作定义)。
(请注意,这个证明只适用于数组翻转,而不能推广到真正具有次线性实现的算法,例如二分查找和元素查找。)
如果迭代被视为“循环直到满足条件”,那么它将转换为机器码,需要进行一些严格的编译器优化(利用分支预测等)。在这种情况下,询问是否有一种“不需要迭代”的方法可能会考虑展开循环(变成一条直线的代码)。在这种情况下,您可以原则上编写直线式(无循环)C代码。但是这种技术并不通用;它仅在您事先知道数组大小的情况下才起作用。(抱歉将这个更多或更少的轻率案例添加到答案中,但我这样做是为了完整性和因为我听过“迭代”这个术语,并且展开循环是一个重要的编译器优化。)
i
处更改值与反转有什么关系。反转是无视值的,它是按位置进行的 - 这就是我的观点 - 因此在任何i
处更改值不能证明任何关于反转的事情。 - Will Ness使用递归函数。
void reverse(int a[],int start,int end)
{
int temp;
temp = a[start];
a[start] = a[end];
a[end] = temp;
if(start==end ||start==end-1)
return;
reverse(a, start+1, end-1);
}
只需调用上述方法:reverse(array,0,lengthofarray-1)
rev(a) = (a[n]) + rev(a[2..n-1]) + (a[1])
相同(具有适当的停止条件)。 - huon实现一个递归函数来反转已排序的数组。例如,给定数组[1, 2, 3, 4, 5],您的程序应返回[5, 4, 3, 2, 1]。
void reverse(int a[], int start, int end )
{
std::cout<<a[end] <<std::endl;
if(end == start)
return;
reverse(a, start, end-1);
}
#include <stdio.h>
#include <stdlib.h>
void swap(int v[], int v_start, int v_middle, int v_end) {
int *aux = calloc(v_middle - v_start, sizeof(int));
int k = 0;
for(int i = v_start; i <= v_middle; i++) {
aux[k] = v[i];
k = k + 1;
}
k = v_start;
for(int i = v_middle + 1; i <= v_end; i++) {
v[k] = v[i];
k = k + 1;
}
for(int i = 0; i <= v_middle - v_start; i++) {
v[k] = aux[i];
k = k + 1;
}
}
void divide(int v[], int v_start, int v_end) {
if(v_start < v_end) {
int v_middle = (v_start + v_start)/2;
divide(v, v_start, v_middle);
divide(v, v_middle + 1, v_end);
swap(v, v_start, v_middle, v_end);
}
}
int main() {
int v[10] = {4, 20, 12, 100, 50, 9}, n = 6;
printf("Array: \n");
for (int i = 0; i < n; i++) {
printf("%d ", v[i]);
}
printf("\n\n");
divide(v, 0, n - 1);
printf("Reversed: \n");
for (int i = 0; i < n; i++) {
printf("%d ", v[i]);
}
return 0;
}
/* Use recursion to reverse an array */
function reverse(a){
if(a.length==undefined || a.length<2){
return a;
}
b=[];
b.push(reverse(copyChop(a)));
b.push(a[0]);
return b;
/* Return a copy of an array minus the first element */
function copyChop(a){
b=a.slice(1);
return b;
}
}
按以下方式调用:
reverse([1,2,3,4]);
#include<stdio.h>
void rev(int *a,int i,int n)
{
if(i<n/2)
{
int temp = a[i];
a[i]=a[n-i-1];
a[n-i-1]=temp;
rev(a,++i,n);
}
}
int main()
{
int array[] = {3,2,4,5,6,7,8};
int len = (sizeof(array)/sizeof(int));
rev(array,0,len);
for(int i=0;i<len;i++)
{
printf("\n array[%d]->%d",i,array[i]);
}
}