尝试解决递归的每一步通常不是一个理想的方法,但对于初学者来说,它肯定有助于理解递归背后的基本思想,并且可以更好地编写递归函数。
这是合并排序的 C 解决方案:-
#include <stdio.h>
#include <stdlib.h>
void merge_sort(int *, unsigned);
void merge(int *, int *, int *, unsigned, unsigned);
int main(void)
{
unsigned size;
printf("Enter the no. of integers to be sorted: ");
scanf("%u", &size);
int * arr = (int *) malloc(size * sizeof(int));
if (arr == NULL)
exit(EXIT_FAILURE);
printf("Enter %u integers: ", size);
for (unsigned i = 0; i < size; i++)
scanf("%d", &arr[i]);
merge_sort(arr, size);
printf("\nSorted array: ");
for (unsigned i = 0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
free(arr);
return EXIT_SUCCESS;
}
void merge_sort(int * arr, unsigned size)
{
if (size > 1)
{
unsigned left_size = size / 2;
int * left = (int *) malloc(left_size * sizeof(int));
if (left == NULL)
exit(EXIT_FAILURE);
for (unsigned i = 0; i < left_size; i++)
left[i] = arr[i];
unsigned right_size = size - left_size;
int * right = (int *) malloc(right_size * sizeof(int));
if (right == NULL)
exit(EXIT_FAILURE);
for (unsigned i = 0; i < right_size; i++)
right[i] = arr[i + left_size];
merge_sort(left, left_size);
merge_sort(right, right_size);
merge(arr, left, right, left_size, right_size);
free(left);
free(right);
}
}
/*
This merge() function takes a target array (arr) and two sorted arrays (left and right),
all three of them allocated beforehand in some other function(s).
It then merges the two sorted arrays (left and right) into a single sorted array (arr).
It should be ensured that the size of arr is equal to the size of left plus the size of right.
*/
void merge(int * arr, int * left, int * right, unsigned left_size, unsigned right_size)
{
unsigned i = 0, j = 0, k = 0;
while ((i < left_size) && (j < right_size))
{
if (left[i] <= right[j])
arr[k++] = left[i++];
else
arr[k++] = right[j++];
}
while (i < left_size)
arr[k++] = left[i++];
while (j < right_size)
arr[k++] = right[j++];
}
这是递归的分步说明:-
Let arr be [1,4,0,3,7,9,8], having the address 0x0000.
In main(), merge_sort(arr, 7) is called, which is the same as merge_sort(0x0000, 7).
After all of the recursions are completed, arr (0x0000) becomes [0,1,3,4,7,8,9].
| | |
| | |
| | |
| | |
| | |
arr - 0x0000 - [1,4,0,3,7,9,8] | | |
size - 7 | | |
| | |
left = malloc() - 0x1000a (say) - [1,4,0] | | |
left_size - 3 | | |
| | |
right = malloc() - 0x1000b (say) - [3,7,9,8] | | |
right_size - 4 | | |
| | |
merge_sort(left, left_size) -------------------> | arr - 0x1000a - [1,4,0] | |
| size - 3 | |
| | |
| left = malloc() - 0x2000a (say) - [1] | |
| left_size = 1 | |
| | |
| right = malloc() - 0x2000b (say) - [4,0] | |
| right_size = 2 | |
| | |
| merge_sort(left, left_size) -------------------> | arr - 0x2000a - [1] |
| | size - 1 |
| left - 0x2000a - [1] <-------------------------- | (0x2000a has only 1 element) |
| | |
| | |
| merge_sort(right, right_size) -----------------> | arr - 0x2000b - [4,0] |
| | size - 2 |
| | |
| | left = malloc() - 0x3000a (say) - [4] |
| | left_size = 1 |
| | |
| | right = malloc() - 0x3000b (say) - [0] |
| | right_size = 1 |
| | |
| | merge_sort(left, left_size) -------------------> | arr - 0x3000a - [4]
| | | size - 1
| | left - 0x3000a - [4] <-------------------------- | (0x3000a has only 1 element)
| | |
| | |
| | merge_sort(right, right_size) -----------------> | arr - 0x3000b - [0]
| | | size - 1
| | right - 0x3000b - [0] <------------------------- | (0x3000b has only 1 element)
| | |
| | |
| | merge(arr, left, right, left_size, right_size) |
| | i.e. merge(0x2000b, 0x3000a, 0x3000b, 1, 1) |
| right - 0x2000b - [0,4] <----------------------- | (0x2000b is now sorted) |
| | |
| | free(left) (0x3000a is now freed) |
| | free(right) (0x3000b is now freed) |
| | |
| | |
| merge(arr, left, right, left_size, right_size) | |
| i.e. merge(0x1000a, 0x2000a, 0x2000b, 1, 2) | |
left - 0x1000a - [0,1,4] <---------------------- | (0x1000a is now sorted) | |
| | |
| free(left) (0x2000a is now freed) | |
| free(right) (0x2000b is now freed) | |
| | |
| | |
merge_sort(right, right_size) -----------------> | arr - 0x1000b - [3,7,9,8] | |
| size - 4 | |
| | |
| left = malloc() - 0x2000c (say) - [3,7] | |
| left_size = 2 | |
| | |
| right = malloc() - 0x2000d (say) - [9,8] | |
| right_size = 2 | |
| | |
| merge_sort(left, left_size) -------------------> | arr - 0x2000c - [3,7] |
| | size - 2 |
| | |
| | left = malloc() - 0x3000c (say) - [3] |
| | left_size = 1 |
| | |
| | right = malloc() - 0x3000d (say) - [7] |
| | right_size = 1 |
| | |
| | merge_sort(left, left_size) -------------------> | arr - 0x3000c - [3]
| left - [3,7] was already sorted, but | | size - 1
| that doesn't matter to this program. | left - 0x3000c - [3] <-------------------------- | (0x3000c has only 1 element)
| | |
| | |
| | merge_sort(right, right_size) -----------------> | arr - 0x3000d - [7]
| | | size - 1
| | right - 0x3000d - [7] <------------------------- | (0x3000d has only 1 element)
| | |
| | |
| | merge(arr, left, right, left_size, right_size) |
| | i.e. merge(0x2000c, 0x3000c, 0x3000d, 1, 1) |
| left - 0x2000c - [3,7] <------------------------ | (0x2000c is now sorted) |
| | |
| | free(left) (0x3000c is now freed) |
| | free(right) (0x3000d is now freed) |
| | |
| | |
| merge_sort(right, right_size) -----------------> | arr - 0x2000d - [9,8] |
| | size - 2 |
| | |
| | left = malloc() - 0x3000e (say) - [9] |
| | left_size = 1 |
| | |
| | right = malloc() - 0x3000f (say) - [8] |
| | right_size = 1 |
| | |
| | merge_sort(left, left_size) -------------------> | arr - 0x3000e - [9]
| | | size - 1
| | left - 0x3000e - [9] <-------------------------- | (0x3000e has only 1 element)
| | |
| | |
| | merge_sort(right, right_size) -----------------> | arr - 0x3000f - [8]
| | | size - 1
| | right - 0x3000f - [8] <------------------------- | (0x3000f has only 1 element)
| | |
| | |
| | merge(arr, left, right, left_size, right_size) |
| | i.e. merge(0x2000d, 0x3000e, 0x3000f, 1, 1) |
| right - 0x2000d - [8,9] <----------------------- | (0x2000d is now sorted) |
| | |
| | free(left) (0x3000e is now freed) |
| | free(right) (0x3000f is now freed) |
| | |
| | |
| merge(arr, left, right, left_size, right_size) | |
| i.e. merge(0x1000b, 0x2000c, 0x2000d, 2, 2) | |
right - 0x1000b - [3,7,8,9] <------------------- | (0x1000b is now sorted) | |
| | |
| free(left) (0x2000c is now freed) | |
| free(right) (0x2000d is now freed) | |
| | |
| | |
merge(arr, left, right, left_size, right_size) | | |
i.e. merge(0x0000, 0x1000a, 0x1000b, 3, 4) | | |
(0x0000 is now sorted) | | |
| | |
free(left) (0x1000a is now freed) | | |
free(right) (0x1000b is now freed) | | |
| | |
| | |
| | |