1
1
<?php
2
+
2
3
/**
3
4
* @example 归并排序
4
5
* @author ShaoWei Pu <[email protected] >
13
14
* 归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,
14
15
* 最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]
15
16
*/
16
-
17
- $ arrStoreList = array (3 ,2 ,4 ,1 ,5 );
18
- //$sort = new Merge_sort();
19
- //$sort->stableSort($arrStoreList, function ($a, $b) { // function ($a, $b)匿名函数
20
- // return $a < $b;
21
- //});
22
-
23
- //静态调用方式也行
24
- Merge_sort:: stableSort ($ arrStoreList , function ($ a , $ b ) {
25
- return $ a < $ b ;
26
- });
27
- print_r ($ arrStoreList );
28
-
29
- class Merge_sort{
30
-
31
- public static function stableSort (&$ array , $ cmp_function = 'strcmp ' ) {
32
-
33
- //使用合并排序
34
- self ::mergeSort ($ array , $ cmp_function );
35
- return ;
17
+ class MergeSort
18
+ {
19
+ /**
20
+ * MergeSort constructor.
21
+ * 是开始递归函数的一个驱动函数
22
+ *
23
+ * @param array $arr 待排序的数组
24
+ */
25
+ public function __construct (array $ arr )
26
+ {
27
+ $ len = count ($ arr );//求得数组长度
28
+ $ this ->mSort ($ arr , 0 , $ len - 1 );
29
+ var_dump ($ arr );
36
30
}
37
- public static function mergeSort (&$ array , $ cmp_function = 'strcmp ' ) {
38
- // Arrays of size < 2 require no action.
39
- if (count ($ array ) < 2 ) {
40
- return ;
41
- }
42
- // Split the array in half
43
- $ halfway = count ($ array ) / 2 ;
44
- $ array1 = array_slice ($ array , 0 , $ halfway );
45
- $ array2 = array_slice ($ array , $ halfway );
46
- // Recurse to sort the two halves
47
- self ::mergeSort ($ array1 , $ cmp_function );
48
- self ::mergeSort ($ array2 , $ cmp_function );
49
- // If all of $array1 is <= all of $array2, just append them.
50
- //array1 与 array2 各自有序;要整体有序,需要比较array1的最后一个元素和array2的第一个元素大小
51
- if (call_user_func ($ cmp_function , end ($ array1 ), $ array2 [0 ]) < 1 ) {
52
- $ array = array_merge ($ array1 , $ array2 );
53
31
54
- return ;
32
+ /**
33
+ * 实际实现归并排序的程序
34
+ *
35
+ * @param $arr array 需要排序的数组
36
+ * @param $left int 子序列的左下标值
37
+ * @param $right int 子序列的右下标值
38
+ */
39
+ public function mSort (&$ arr , $ left , $ right )
40
+ {
41
+ if ($ left < $ right ) {
42
+ //说明子序列内存在多余1个的元素,那么需要拆分,分别排序,合并
43
+ //计算拆分的位置,长度/2 去整
44
+ $ center = floor (($ left + $ right ) / 2 );
45
+ //递归调用对左边进行再次排序:
46
+ $ this ->mSort ($ arr , $ left , $ center );
47
+ //递归调用对右边进行再次排序
48
+ $ this ->mSort ($ arr , $ center + 1 , $ right );
49
+ //合并排序结果
50
+ $ this ->mergeArray ($ arr , $ left , $ center , $ right );
55
51
}
56
- // 将两个有序数组合并为一个有序数组:Merge the two sorted arrays into a single sorted array
57
- $ array = array ();
58
- $ ptr1 = $ ptr2 = 0 ;
59
- while ($ ptr1 < count ($ array1 ) && $ ptr2 < count ($ array2 )) {
60
- if (call_user_func ($ cmp_function , $ array1 [$ ptr1 ], $ array2 [$ ptr2 ]) < 1 ) {
61
- $ array [] = $ array1 [$ ptr1 ++];
52
+ }
53
+
54
+ /**
55
+ * 将两个有序数组合并成一个有序数组
56
+ *
57
+ * @param &$arr , 待排序的所有元素
58
+ * @param $left , 排序子数组A的开始下标
59
+ * @param $center , 排序子数组A与排序子数组B的中间下标,也就是数组A的结束下标
60
+ * @param $right , 排序子数组B的结束下标(开始为$center+1)
61
+ */
62
+ public function mergeArray (&$ arr , $ left , $ center , $ right )
63
+ {
64
+ //设置两个起始位置标记
65
+ $ a_i = $ left ;
66
+ $ b_i = $ center + 1 ;
67
+ $ temp = [];
68
+
69
+ while ($ a_i <= $ center && $ b_i <= $ right ){
70
+ //当数组A和数组B都没有越界时
71
+ if ($ arr [ $ a_i ] < $ arr [ $ b_i ]) {
72
+ $ temp [] = $ arr [ $ a_i ++ ];
62
73
} else {
63
- $ array [] = $ array2 [ $ ptr2 ++ ];
74
+ $ temp [] = $ arr [ $ b_i ++ ];
64
75
}
65
76
}
66
- // Merge the remainder
67
- while ($ ptr1 < count ( $ array1 )) {
68
- $ array [] = $ array1 [ $ ptr1 ++ ];
77
+ //判断 数组A内的元素是否都用完了,没有的话将其全部插入到C数组内:
78
+ while ($ a_i <= $ center ) {
79
+ $ temp [] = $ arr [ $ a_i ++ ];
69
80
}
70
- while ($ ptr2 < count ($ array2 )) {
71
- $ array [] = $ array2 [$ ptr2 ++];
81
+ //判断 数组B内的元素是否都用完了,没有的话将其全部插入到C数组内:
82
+ while ($ b_i <= $ right ){
83
+ $ temp [] = $ arr [ $ b_i ++ ];
84
+ }
85
+
86
+ //将$arrC内排序好的部分,写入到$arr内:
87
+ for ($ i = 0 , $ len = count ($ temp ); $ i < $ len ; $ i ++){
88
+ $ arr [ $ left + $ i ] = $ temp [ $ i ];
72
89
}
73
- return ;
74
90
}
75
- }
91
+ }
92
+
93
+ //do some test:
94
+ new mergeSort ([4 , 7 , 6 , 3 , 9 , 5 , 8 ]);
95
+
96
+
0 commit comments