* by 沈东良/良少 * @param array
* @param start
* @param end 这是最后一个元素的索引,第一次调用应该是array.length-1
* @param value
* @return
*/
public static int binarySearch(int[] array,int start,int end,int value){
int middle=(start+end)/2;
if(end<start){
return -1;
}
if(end==(start+1)){
if(array[start]==value){
return start;
}else if(array[end]==value){
return end;
}
}else if(array[middle]==value){
return middle;
}else if(value>array[middle]){
return binarySearch(array,middle+1,end,value);
}else if(value<array[middle]){
return binarySearch(array,start,middle-1,value);
}
return -1;
}
上述代码稍加改变,就可以排序任意类型。如使用泛型,然后加上对Comparable接口的实现,即可。
快速排序算法
二分搜索算法确实非常快,但是它只能用于已排序数组。如果数组未排序呢,该怎么办呢?简单,先用快速排序算法进行排序,然后再用二分搜索进行搜索。
二分搜索算法确实非常快,但是它只能用于已排序数组。如果数组未排序呢,该怎么办呢?简单,先用快速排序算法进行排序,然后再用二分搜索进行搜索。
先排序再搜索,要比匹配每一个元素快得多。搜索引擎,数据库索引也都使用了对数据集合的排序技术,这样搜索数据才会快速。
理论:
最慢,也是最容易想到的排序算法是插入排序算法:
最慢,也是最容易想到的排序算法是插入排序算法:
1, 遍历数组,找出最小的元素,把它放到第一个元素。
2, 循环查找未排序的数组,直到整个数组排序。
这需要2个嵌套的循环,意味着它的效率是O(n^2);
之所以插入排序的效率如此之地,是因为要找出整个数组中最小的数据,需要遍历整个数组的元素。
而插入排序聪明就聪明在它不查找整个数组最小、次小…的元素,而是每次仅仅把小于某个元素的值移到一边,通过迭代最终自动实现排序。这就大大节约了排序所需的计算步骤。
快速排序算法的理论:
1, 如果S中的元素个数是0或者1,那么返回。
2, 选取S中的任一元素v,称为中心点。
3, 将S集合中的元素分为2个部分:L={小于pivot 的元素+ pivot }和R={大于或者等于pivot的元素}。
4, 返回L和R。
我们使用Java使用的是就地排序的方式,因此不需要返回值。
因为Java是一种可以修改变量的语言,用函数式语言的术语来说,就是有“副作用”。我们利用这个副作用直接修改作为参数的Array,不需要返回值。
代码:
/** by 沈东良/良少
/** by 沈东良/良少
* 快速排序,有副作用 从小到大
* @param array
* @param start
* @param end这是最后一个元素的索引,第一次调用应该是array.length-1
*/
public static void quickSort(int[] array,int start,int end){
//有可能造成start>end 因为递归调用时j+1,可能引起j比end还大1。 另外如果数组是空的,或者输入错误也会出现这种情况
if(end<=start){
return;
}else {
//取中间元素为中心点,然后移到最右边
int sign=(start+end)/2;
int tmp=array[end];
array[end]=array[sign];
array[sign]=tmp;
int j=start;
for(int i=start;i<=end-1;i++){
//小于的元素和标记互换,等于的不能互换,否则会形成死循环
if(array[i]<array[end]) {
tmp=array[i];
array[i]=array[j];
array[j]=tmp;
j=j+1;
}
}
//把标记元素和第一个>=它的元素位置互换,这样数组就分成2个部分,一个部分比中心值小,一个部分比中心值大。
tmp=array[j];
array[j]=array[end];
array[end]=tmp;
quickSort(array,start,j);
quickSort(array,j+1,end);
}
}