1- using System ;
1+ using System ;
22using System . Collections . Generic ;
33using ToolGood . Algorithm . Enums ;
44
55namespace ToolGood . Algorithm . Internals . Functions . MathSum
66{
77 internal sealed class Function_MEDIAN : Function_N
8- {
9- public Function_MEDIAN ( FunctionBase [ ] funcs ) : base ( funcs )
10- {
11- if ( funcs . Length < 1 ) {
12- throw new ArgumentException ( $ "Function '{ Name } ' requires at least 1 parameter.") ;
13- }
14- }
15-
16- public override string Name => "Median" ;
17-
18- public override Operand Evaluate ( AlgorithmEngine engine , Func < AlgorithmEngine , string , Operand > tempParameter )
19- {
20- var args = new List < Operand > ( funcs . Length ) ;
21- var error = TryEvaluateAll ( engine , tempParameter , args ) ;
22- if ( error != null ) { return error ; }
23-
24- var list = new List < decimal > ( ) ;
25- var o = FunctionUtil . FlattenToList ( args , list ) ;
26-
27- if ( o == false ) { return FunctionError ( ) ; }
28- if ( list . Count == 0 ) { return FunctionError ( ) ; }
29-
30- list . Sort ( ) ;
31- var mid = list . Count / 2 ;
32- if ( list . Count % 2 == 0 ) {
33- return Operand . Create ( ( list [ mid - 1 ] + list [ mid ] ) / 2 ) ;
34- }
35- return Operand . Create ( list [ mid ] ) ;
36- }
8+ {
9+ public Function_MEDIAN ( FunctionBase [ ] funcs ) : base ( funcs )
10+ {
11+ if ( funcs . Length < 1 ) {
12+ throw new ArgumentException ( $ "Function '{ Name } ' requires at least 1 parameter.") ;
13+ }
14+ }
15+
16+ public override string Name => "Median" ;
17+
18+ public override Operand Evaluate ( AlgorithmEngine engine , Func < AlgorithmEngine , string , Operand > tempParameter )
19+ {
20+ var args = new List < Operand > ( funcs . Length ) ;
21+ var error = TryEvaluateAll ( engine , tempParameter , args ) ;
22+ if ( error != null ) { return error ; }
23+
24+ var list = new List < decimal > ( ) ;
25+ if ( FunctionUtil . FlattenToList ( args , list ) == false ) { return FunctionError ( ) ; }
26+ if ( list . Count == 0 ) { return FunctionError ( ) ; }
27+
28+ int n = list . Count ;
29+ if ( n == 1 ) return Operand . Create ( list [ 0 ] ) ;
30+
31+ int mid = n / 2 ;
32+ if ( n % 2 == 0 ) {
33+ return Operand . Create ( ( QuickSelect ( list , mid - 1 ) + QuickSelect ( list , mid ) ) / 2 ) ;
34+ }
35+ return Operand . Create ( QuickSelect ( list , mid ) ) ;
36+ }
37+
38+ private static decimal QuickSelect ( List < decimal > arr , int k )
39+ {
40+ int left = 0 , right = arr . Count - 1 ;
41+ while ( left < right ) {
42+ int pivot = SelectPivot ( arr , left , right ) ;
43+ int partition = Partition ( arr , left , right , pivot ) ;
44+ if ( partition == k ) {
45+ return arr [ k ] ;
46+ }
47+ if ( k < partition ) {
48+ right = partition - 1 ;
49+ } else {
50+ left = partition + 1 ;
51+ }
52+ }
53+ return arr [ left ] ;
54+ }
55+
56+ private static int SelectPivot ( List < decimal > arr , int left , int right )
57+ {
58+ int mid = left + ( right - left ) / 2 ;
59+ decimal a = arr [ left ] , b = arr [ mid ] , c = arr [ right ] ;
60+ if ( a < b ) {
61+ if ( b < c ) return mid ;
62+ if ( a < c ) return right ;
63+ return left ;
64+ }
65+ if ( a < c ) return left ;
66+ if ( b < c ) return right ;
67+ return mid ;
68+ }
69+
70+ private static int Partition ( List < decimal > arr , int left , int right , int pivotIndex )
71+ {
72+ decimal pivot = arr [ pivotIndex ] ;
73+ ( arr [ pivotIndex ] , arr [ right ] ) = ( arr [ right ] , arr [ pivotIndex ] ) ;
74+ int storeIndex = left ;
75+ for ( int i = left ; i < right ; i ++ ) {
76+ if ( arr [ i ] < pivot ) {
77+ ( arr [ storeIndex ] , arr [ i ] ) = ( arr [ i ] , arr [ storeIndex ] ) ;
78+ storeIndex ++ ;
79+ }
80+ }
81+ ( arr [ storeIndex ] , arr [ right ] ) = ( arr [ right ] , arr [ storeIndex ] ) ;
82+ return storeIndex ;
83+ }
84+
3785 public override OperandType GetResultType ( )
3886 {
3987 return OperandType . NUMBER ;
@@ -50,5 +98,4 @@ internal override void GetParameterTypes(NoneEngine noneEngine, List<ParameterTy
5098 }
5199 }
52100 }
53-
54101}
0 commit comments