Binary Search of extension methods

Source: Internet
Author: User
Tags mscorlib

Binary Search of extension methods

Version: 0.1

Last modified:

Written by Li Xianmin

Recent project planning case adjustments, requirementsProgramYou can quickly locate the action that the current game role is using based on music time, location, and other conditions. Because the query is very frequent, you have to use binary search.

The C # class library contains binary searches, which are scattered in classes such as array, list, And arraylist, but the interfaces are not satisfactory. It is good for a simple integer array and can be used directly, but for complex queries, the default class library will be more complex to use, such:

 

Class Action
{
Public String Name;
Public Int Time;
Public Int Position;
}

Class Timecomparer: icomparer <action>
{
Public Int Compare (Action LHS, Action RHs)
{
If ( Null = LHS)
{
Return - 1 ;
}
Else If ( Null = RHs)
{
Return 1 ;
}

ReturnLHS. Time. compareto (RHS. time );
}
}

Class Program
{
Static Int Binarysearchbytime (action [] actions, Int Time)
{
VaR Testaction = New Action () {time = time };
VaR Index = array. binarysearch (actions, testaction, New Timecomparer ());
If (Index < 0 )
{
Return ~ Index- 1 ;
}

ReturnIndex;
}

Static Void Main (String [] ARGs)
{
VaR Actions = New Action [] {
New Action () {name = " Action1 " , Time = 0 , Position = 0 },
New Action () {name = " Action2 " , Time = 2 , Position = 60 },
New Action () {name = " Action3 " , Time =4 , Position = 90 }};

VaRTime =3;
VaRIndex = binarysearchbytime (actions, time );

Console. readkey ();
}

}

 

The example shows a class that represents the actions of a role in the game. The actions array stores the actions that need to be played at each time point and position in order, query the action that is being played at the time of time = 4.

ByCodeThe default class library has at least two disadvantages:

    1. You need to write the corresponding comparator by yourself. In this example, You need to query by time, so it is implemented as the timecomparer class. If you need to query by position further, you need to implement the positioncomparer class, in this case, when the comparison methods are diversified, the amount of code for the comparator alone will be very large.

    2. The comparator requires that the two input parameters have the same type. In this example, they are action classes. Therefore, even if we only need to compare by time, we have to construct a temporary testaction object. This should not be necessary for the functions we need to implement. In some cases, due to the limitations of the action class constructor, we may have to construct such an object through a very complex method.

In addition, because binarysearch () is scattered in multiple classes, the usage of code is not very similar (for example, the static method in the array class, but the Member method in the List class ), to some extent, obfuscation may occur.

Based on the above reasons, I hope to solve the above problems in some way, so that the Code customers can call binary search through simple and consistent interfaces.Algorithm. The Code Implementation of the new solution is as follows:

Public Static Int Binarysearch <t> ( This Ilist <t> list, Int Key, func <t, Int > Extract)
{
If ( Null = List)
{
Throw New Argumentnullexception ( " List is null " );
}

Int Count = List. count;
Int I =- 1 ;
Int J = count;
While (I + 1 ! = J)
{
Int Mid = I + (J-I> 1 );
If (Extract (list [Mid]) <key)
{
I = mid;
}
Else
{
J = mid;
}
}

If(J = count | extract (list [J])! = Key)
{
J = ~ J;
}

ReturnJ;
}

Static Void Main ( String [] ARGs)
{
VaR Actions = New Action [] {
New Action () {name = " Action1 " , Time = 0 , Position = 0 },
New Action () {name = " Action2 " , Time = 2 , Position = 60 },
New Action () {name = " Action3 " , Time = 4 , Position = 90 }};

VaRTime =3;
VaRIndex = actions. binarysearch (time, item => item. time );

Console. readkey ();

}

First, the new binarysearch () is an extension method. Its Extension object is the ilist <t> interface, which is implemented by both the array and List classes, therefore, they can directly call the new binarysearch () method. In the example, the actions array directly calls the binarysearch () method.

Second, the new binarysearch () method accepts a delegate as the callback method, so you can use a very concise method to avoid constructing the comparator class in the original scheme. The example extracts the item. Time data.

Furthermore, the keywords used for comparison (named as key) in the new binarysearch () method can now be passed in directly, instead of constructing a temporary testaction object.

In addition, the returned values of the new binarysearch () method are the same as those of the C # built-in binary search algorithm. If yes, the corresponding index is returned. If no value is found, returns an index population smaller than 0. The original index value obtained after the population is obtained is a keyword (named key) the location where the sequence should be inserted correctly.

For a detailed description of algorithm implementation, see section 9.2 "major surgical procedures-binary lookup" in programming Pearl II.

In addition, there are some implementation-related details and improvement solutions, which need to be mentioned here:

The first question is: Why does the key in binarysearch () not use generics? This is because two operations are used in code implementation. The comparison between the two objects is less than (<) and not equal (! =), This is certainly a comparison of integers, but for general data types, it must be implemented using the corresponding interface. In addition, for floating point float, unequal comparison (! =) It must be processed according to the comparison precision, so it also needs to be a single write. For the sake of simplicity and speed, only int type is used here. Finally, int and float should cover most cases, right?

The second problem is that binarysearch () extends ilist <t>, but there is room for Speed Optimization for array. As mentioned above, array implements ilist <t>, which is correct. However, if you use the ilist <t> interface to call the list of arrays. if count and list [Mid] are used, the actual method of the class instance is called, respectively:

Callvirt instance int32 class [mscorlib] system. Collections. Generic. icollection '1 <!! T>: get_count ()

Callvirt instance! 0 class [mscorlib] system. Collections. Generic. ilist '1 <!! T>: get_item (int32)

for arrays, the corresponding Assembly commands are used to complete these two operations. Therefore, if you have requirements on the speed, writing the corresponding binarysearch () for the array separately will return.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.