1.非递归实现思路
我们之前学习了递归实现的归并排序,是分治的思想,即先分解,再归并
这篇文章我们讲一下非递归的实现
非递归实现的思路是模拟递归的过程,在递归过程中,我们找key将数组分成左右数组,然后递归子数组,知道该数组剩一个元素,然后归并:两个两元素数组归并为四元素数组,两个四元素数字归并为八元素数组
而非递归的实现不需要递归子数组进行分解,我们可以将n个元素的数组看作n个数组,直接进行下面的合并
我们先设gap为1,表示先控制一个元素的数组进行归并,malloc一个临时数组tmp,归并到tmp数组;一整趟归并结束后gap*=2,同时将归并完成的数组拷贝到原数组,继续控制两元素的数组进行归并,直到gap>=n则停止归并,此时原数组已经有序了
2.图示归并
归并的过程和递归方式的归并排序一样
每次归并的时候,两个数组中找小的排到前面,排空一个数组之后将另外一个数组尾插到后面即可
3.代码展示
函数代码和测试代码如下
1. #define _CRT_SECURE_NO_WARNINGS 1 2. #include<stdio.h> 3. #include<stdlib.h> 4. #include<string.h> 5. void MergeSortNonR(int* a, int n) 6. { 7. int* tmp = (int*)malloc(sizeof(int) * n); 8. if (tmp == NULL) 9. { 10. perror("malloc fail!"); 11. return; 12. } 13. int gap = 1;//先控制一个一个归并 14. while (gap < n) 15. { 16. for (int i = 0; i < n; i += 2 * gap) 17. { 18. int begin1 = i, end1 = i + gap - 1; 19. int begin2 = i + gap, end2 = i + 2 * gap - 1; 20. if (end1 >= n || begin2 >= n) 21. { 22. break; 23. } 24. if (end2 >= n) 25. { 26. end2 = n - 1; 27. } 28. int j = begin1; 29. while (begin1 <= end1 && begin2 <= end2) 30. { 31. if (a[begin1] < a[begin2]) 32. tmp[j++] = a[begin1++]; 33. else 34. tmp[j++] = a[begin2++]; 35. } //[begin1,end1][begin2,end2]归并->tmp[] 36. while (begin1 <= end1) 37. tmp[j++] = a[begin1++]; 38. while (begin2 <= end2) 39. tmp[j++] = a[begin2++]; 40. memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1)); 41. } 42. gap *= 2; 43. } 44. free(tmp); 45. } 46. int main() 47. { 48. int i = 0; 49. int a[] = { 10,10,2,5,7,9,3,4,5,4,1,0 }; 50. int n = sizeof(a) / sizeof(a[0]); 51. for (i = 0; i < n; i++) 52. { 53. printf("%d ", a[i]); 54. } 55. printf("\n"); 56. MergeSortNonR(a, n); 57. for (i = 0; i < n; i++) 58. { 59. printf("%d ", a[i]); 60. } 61. return 0; 62. }