① jave二分算法
import java.util.ArrayList;
import java.util.Random;
public class Test {
public static void main(String[] args) {
ArrayList<Integer> list=new ArrayList<Integer>(50);//创建一个容量50的ArrayList
Random r=new Random(47);
for(int i=0;i<50;i++){
list.add(r.nextInt(200));//添加50个200以内的随机数
}
BinSort(list);//二分插入排序
System.out.println(list);//谨祥唯输出list的内容
}
public static void BinSort(ArrayList<Integer> list){//考虑到有大宴首量的随机访祥培问,用ArrayList较快
int left, right, mid, temp;
for (int i = 1; i < list.size(); i++)
{
left = 0;
right = i - 1;
temp = list.get(i);
while (left <= right)
{
mid = (left + right)/2;
if (temp < list.get(mid)) //升序
right = mid - 1;
else
left = mid + 1;
}
for (int j = i - 1; j >= left; j--)
list.set(j + 1, list.get(j));
list.set(left, temp);
}
}
}
② Java的排序算法有哪些
排序: 插入,冒泡,选择,Shell,快速排序
③ java二分法查找的递归算法怎么实现
什么是二分查找?
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
二分查找优缺点
优点是比较次数少,查找速度快,平均性能好;
其缺点是要求待查表为有序表,且插入删除困难。
因此,折半查找方法适用于不经常变动而查找频繁的有序列表。
使用条件:查找序列是顺序结构,有序。
过程
首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
利用循环的方式实现二分法查找
public class BinarySearch {
public static void main(String[] args) {
// 生成一个随机数组 int[] array = suiji();
// 对随机数组排序 Arrays.sort(array);
System.out.println("产生的随机数组为: " + Arrays.toString(array));
System.out.println("要进行查找的值: ");
Scanner input = new Scanner(System.in);
// 进行查找的目标值 int aim = input.nextInt();
// 使用二分法查找 int index = binarySearch(array, aim);
System.out.println("查找的值的索引位置: " + index);
}
/** * 生成一个随机数组 *
* @return 返回值,返回一个随机数组 */
private static int[] suiji() {
// random.nextInt(n)+m 返回m到m+n-1之间的随机数 int n = new Random().nextInt(6) + 5;
int[] array = new int[n];
// 循环遍历为数组赋值 for (int i = 0; i < array.length; i++) {
array[i] = new Random().nextInt(100);
}
return array;
}
/** * 二分法查找 ---循环的方式实现 *
* @param array 要查找的数组 * @param aim 要查找的值 * @return 返回值,成功返回索引,失败返回-1 */
private static int binarySearch(int[] array, int aim) {
// 数组最小索引值 int left = 0;
// 数组最大索引值 int right = array.length - 1;
int mid;
while (left <= right) {
mid = (left + right) / 2;
// 若查找数值比中间值小,则以整个查找范围的前半部分作为新的查找范围 if (aim < array[mid]) {
right = mid - 1;
// 若查找数值比中间值大,则以整个查找范围的后半部分作为新的查找范围 } else if (aim > array[mid]) {
left = mid + 1;
// 若查找数据与中间元素值正好相等,则放回中间元素值的索引 } else {
return mid;
}
}
return -1;
}}
运行结果演示:
总结:
递归相较于循环,代码比较简洁,但是时间和空间消耗比较大,效率低。在实际的学习与工作中,根据情况选择使用。通常我们如果使用循环实现代码只要不是太繁琐都选择循环的方式实现~
④ 什么叫java中的二分查找法
1、算法概念。
二分查找算法也称为折半搜索、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法。请注意这种算法是建立在有序数组基础上的。
2、算法思想。
①搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;
②如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。
③如果在某一步骤数组为空,则代表找不到。
这种搜索算法每一次比较都使搜索范围缩小一半。
3、实现思路。
①找出位于数组中间的值,并存放在一个变量中(为了下面的说明,变量暂时命名为temp);
②需要找到的key和temp进行比较;
③如果key值大于temp,则把数组中间位置作为下一次计算的起点;重复① ②。
④如果key值小于temp,则把数组中间位置作为下一次计算的终点;重复① ② ③。
⑤如果key值等于temp,则返回数组下标,完成查找。
4、实现代码。
/**
*description:二分查找。
*@paramarray需要查找的有序数组
*@paramfrom起始下标
*@paramto终止下标
*@paramkey需要查找的关键字
*@return
*/
publicstatic<EextendsComparable<E>>intbinarySearch(E[]array,intfrom,intto,Ekey)throwsException{
if(from<0||to<0){
("paramsfrom&lengthmustlargerthan0.");
}
if(from<=to){
intmiddle=(from>>>1)+(to>>>1);//右移即除2
Etemp=array[middle];
if(temp.compareTo(key)>0){
to=middle-1;
}elseif(temp.compareTo(key)<0){
from=middle+1;
}else{
returnmiddle;
}
}
returnbinarySearch(array,from,to,key);
}
⑤ 用java写二分搜索,要求数组是由用户输入,再输入时,数组是无序的,要对数组进行从小到大的排序
二分查找又称折半查找,它是一种效率较高的查找方法。
【二分查找要求】:1.必须采用顺序存储结构 2.必须按关键字大小有序排列。
/**
* 二分查找又称折半查找,它是一种效率较高的查找方法。
【二分查找要求】:1.必须采用顺序存储结构 2.必须按关键字大小有序排列。
* @author Administrator
*
*/
public class BinarySearch {
public static void main(String[] args) {
int[] src = new int[] {1, 3, 5, 7, 8, 9};
System.out.println(binarySearch(src, 3));
System.out.println(binarySearch(src,3,0,src.length-1));
}
/**
* * 二分查找算法 * *
*
* @param srcArray
* 有序数组 *
* @param des
* 查找元素 *
* @return des的数组下标,没找到返回-1
*/
public static int binarySearch(int[] srcArray, int des){
int low = 0;
int high = srcArray.length-1;
while(low <= high) {
int middle = (low + high)/2;
if(des == srcArray[middle]) {
return middle;
}else if(des <srcArray[middle]) {
high = middle - 1;
}else {
low = middle + 1;
}
}
return -1;
}
/**
*二分查找特定整数在整型数组中的位置(递归)
*@paramdataset
*@paramdata
*@parambeginIndex
*@paramendIndex
*@returnindex
*/
public static int binarySearch(int[] dataset,int data,int beginIndex,int endIndex){
int midIndex = (beginIndex+endIndex)/2;
if(data <dataset[beginIndex]||data>dataset[endIndex]||beginIndex>endIndex){
return -1;
}
if(data <dataset[midIndex]){
return binarySearch(dataset,data,beginIndex,midIndex-1);
}else if(data>dataset[midIndex]){
return binarySearch(dataset,data,midIndex+1,endIndex);
}else {
return midIndex;
}
}
}
⑥ JAVA 二分算法只能对数字进行查找吗
2分法查找,前提是要有序,要排序,必然要比较大小,所以只要一个类它实现了Comparable接口的compareTo(To)方法(Comparable在java.lang包中)或是实现一个比较器对象接口Comparator(Comparator在java.util包),都可以进行比较了。不管是String型,计本数据类型,还是其他什么的,都可以用2分发查找了。给你看看API
java.util.Collections中2分法的API
binarySearch
publicstatic<T>intbinarySearch(List<?extendsComparable<?superT>>list,
Tkey)使用二分搜索法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据列表元素的自然顺序对列表进行升序排序(通过灶仔sort(List)方法)。如果没有对列表进行排序,则结果是不确定的。如果列表包含多个等于指定对象的元素,则无法保证找到的是哪一个。
此方法对“随机访问”列表运行log(n)次(它提供接近固定时间的位置访问)。如果指定列表没有实现RandomAccess接口并且是一个大型列表,则此方法将执行基于迭代器的二分搜索,执行O(n)次链接遍历和O(logn)次元素比较。
参数:
list-要搜索的列表。
key-要搜索的键。
返回:
如果搜索键包含在列表中,则返回搜索键的索引;否则返回(-(插入点)-1)。插入点被定义为将键插入列表的那一点:即第一个大于此键的元素索引;如果列表中的所有元素都小于指定的键,则为list.size()。注意,这保证了当且仅当此键被找到时,返回的值将>=0。
抛出:
ClassCastException-如果列表中包含不可相互比较的元素(例如,字符串和整数),或者搜索键无法与列表的元素进行相互比较。
--------------------------------------------------------------------------------
binarySearch
publicstatic<T>intbinarySearch(List<?extendsT>list,
Tkey,
Comparator<?superT>c)使用二分搜索法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据指定的比较器对列表进行升序排序(通过sort(List,Comparator)方法)。如果没有对列表进行排序,则结果是不确定的。如果列表包含多个等于指定对象的元素,则无法保证找到的是哪一个。
此方法对“随机访问”的列表运行log(n)次(它提供接近固定时间的位置访问)。如果指定列表没有实现RandomAccess接口并且是一个大型列表,则此方法将执行基于迭代器的二分搜索,执行O(n)次链接遍历和O(logn)次元素比较。
参数:
list-要搜索的列表。
key-要搜索的键。
c-排序列表的比较器。null值指示应该使用元素的自然顺序。
返回:
如果搜索键码族包含在列表中,则返回搜索键的索引;否则返回(-(插入点)-1)。插入点被定义为将键插入列表的那一点:即第一个大于此键的元素索引;如果列表中的所有元素都小于指定的键,则为list.size()。注意隐模汪,这保证了当且仅当此键被找到时,返回的值将>=0。
抛出:
ClassCastException-如果列表中包含使用指定的比较器不可相互比较的元素,或者使用此比较器无法相互比较搜索键与列表元素。
java.util.Comparator接口。
A>intcompare(To1,To2)比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。
在前面的描述中,符号sgn(expression)表示signum数学函数,根据expression的值为负数、0还是正数,该函数分别返回-1、0或1。
实现程序必须确保对于所有的x和y而言,都存在sgn(compare(x,y))==-sgn(compare(y,x))。(这意味着当且仅当compare(y,x)抛出异常时compare(x,y)才必须抛出异常。)
实现程序还必须确保关系是可传递的:((compare(x,y)>0)&&(compare(y,z)>0))意味着compare(x,z)>0。
最后,实现程序必须确保compare(x,y)==0意味着对于所有的z而言,都存在sgn(compare(x,z))==sgn(compare(y,z))。
虽然这种情况很普遍,但并不严格要求(compare(x,y)==0)==(x.equals(y))。一般说来,任何违背这个条件的Comparator都应该清楚地指出这一事实。推荐的语言是“注意:此Comparator强行进行与equals不一致的排序。”
参数:
o1-要比较的第一个对象。
o2-要比较的第二个对象。
返回:
根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。
抛出:
ClassCastException-如果参数的类型不允许此Comparator对它们进行比较。
B>booleanequals(Objectobj)指示某个其他对象是否“等于”此Comparator。此方法必须遵守Object.equals(Object)的常规协定。此外,仅当指定的对象也是一个Comparator,并且强行实施与此Comparator相同的排序时,此方法才返回true。因此,comp1.equals(comp2)意味着对于每个对象引用o1和o2而言,都存在sgn(comp1.compare(o1,o2))==sgn(comp2.compare(o1,o2))。
注意,不重写Object.equals(Object)方法总是安全的。然而,在某些情况下,重写此方法可以允许程序确定两个不同的Comparator是否强行实施了相同的排序,从而提高性能。
覆盖:
类Object中的equals
参数:
obj-要进行比较的引用对象。
返回:
仅当指定的对象也是一个Comparator,并且强行实施与此Comparator相同的排序时才返回true。
以及java.lang.Comparable
publicinterfaceComparable<T>此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。
实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
对于类C的每一个e1和e2来说,当且仅当e1.compareTo(e2)==0与e1.equals(e2)具有相同的boolean值时,类C的自然排序才叫做与equals一致。注意,null不是任何类的实例,即使e.equals(null)返回false,e.compareTo(null)也将抛出NullPointerException。
建议(虽然不是必需的)最好使自然排序与equals一致。这是因为在使用自然排序与equals不一致的元素(或键)时,没有显式比较器的有序集合(和有序映射表)行为表现“怪异”。尤其是,这样的有序集合(或有序映射表)违背了根据equals方法定义的集合(或映射表)的常规协定。
例如,如果将两个键a和b添加到没有使用显式比较器的有序集合中,使(!a.equals(b)&&a.compareTo(b)==0),那么第二个add操作将返回false(有序集合的大小没有增加),因为从有序集合的角度来看,a和b是相等的。
实际上,所有实现Comparable的Java核心类都具有与equals一致的自然排序。java.math.BigDecimal是个例外,它的自然排序将值相等但精确度不同的BigDecimal对象(比如4.0和4.00)视为相等。
从数学上讲,定义给定类C上自然排序的关系式如下:
{(x,y)|x.compareTo(y)<=0}。
整体排序的商是:
{(x,y)|x.compareTo(y)==0}。
它直接遵循compareTo的协定,商是C的等价关系,自然排序是C的整体排序。当说到类的自然排序与equals一致时,是指自然排序的商是由类的equals(Object)方法定义的等价关系。
{(x,y)|x.equals(y)}。
compareTo
intcompareTo(To)比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
实现类必须确保对于所有的x和y都存在sgn(x.compareTo(y))==-sgn(y.compareTo(x))的关系。(这意味着如果y.compareTo(x)抛出一个异常,则x.compareTo(y)也要抛出一个异常。)
实现类还必须确保关系是可传递的:(x.compareTo(y)>0&&y.compareTo(z)>0)意味着x.compareTo(z)>0。
最后,实现者必须确保x.compareTo(y)==0意味着对于所有的z,都存在sgn(x.compareTo(z))==sgn(y.compareTo(z))。强烈推荐(x.compareTo(y)==0)==(x.equals(y))这种做法,但并不是严格要求这样做。一般来说,任何实现Comparable接口和违背此条件的类都应该清楚地指出这一事实。推荐如此阐述:“注意:此类具有与equals不一致的自然排序。”
在前面的描述中,符号sgn(expression)指定signum数学函数,该函数根据expression的值是负数、零还是正数,分别返回-1、0或1中的一个值。
参数:
o-要比较的对象。
返回:
负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。
抛出:
ClassCastException-如果指定对象的类型不允许它与此对象进行比较。
⑦ 怎么计算java二分法查找的比较次数
您好,我来为您解答:
算法:当数据量很大适宜采用该方法。采用二分法查找时,数据需是有序不重复的。
基本思想:假设数据是按升序排序的,对于给定值
x,从序列的中间位置开始比较,如果当前位置值等于
x,则查找成功;若
x
小于当前位置值,则在数列的前半段中查找;若
x
大于当前位置值则在数列的后半段中继续查找,直到找到为止。
希望我的回答对你有帮助。
⑧ java二分排序算法是不是稳定
稳定
packagecom.guxia;
publicclassTest {
publicstaticvoidmain(String[] args) {
int[]a={4,2,1,6,3,6,0,-5,1,1};
inti,j;
intlow,high,mid;
inttemp;
for(i=1;i<10;i++){
temp=a[i];
low=0;
high=i-1;
while(low<=high){
mid=(low+high)/2;
if(a[mid]>temp)
high=mid-1;
else
low=mid+1;
}
for(j=i-1;j>high;j--)
a[j+1]=a[j];
a[high+1]=temp;
}
for(i=0;i<10;i++){
System.out.printf("%d",a[i]);
}
}
}
⑨ java实现几种常见排序算法
下面给你介绍四种常用排序算法:
1、冒泡排序
特点:效率低,实现简单
思想(从小到大排):每一趟将待排序序列中最大元素移到最后,剩下的为新的待排序序列,重复上述步骤直到排完所有元素。这只是冒泡排序的一种,当然也可以从后往前排。
⑩ 请给出java几种排序方法
java常见的排序分为:
1 插入类排序
主要就是对于一个已经有序的序列中,插入一个新的记录。它包括:直接插入排序,折半插入排序和希尔排序
2 交换类排序
这类排序的核心就是每次比较都要“交换”,在每一趟排序都会两两发生一系列的“交换”排序,但是每一趟排序都会让一个记录排序到它的最终位置上。它包括:起泡排序,快速排序
3 选择类排序
每一趟排序都从一系列数据中选择一个最大或最小的记录,将它放置到第一个或最后一个为位置交换,只有在选择后才交换,比起交换类排序,减少了交换记录的时间。属于它的排序:简单选择排序,堆排序
4 归并类排序
将两个或两个以上的有序序列合并成一个新的序列
5 基数排序
主要基于多个关键字排序的。
下面针对上面所述的算法,讲解一些常用的java代码写的算法
二 插入类排序之直接插入排序
直接插入排序,一般对于已经有序的队列排序效果好。
基本思想:每趟将一个待排序的关键字按照大小插入到已经排序好的位置上。
算法思路,从后往前先找到要插入的位置,如果小于则就交换,将元素向后移动,将要插入数据插入该位置即可。时间复杂度为O(n2),空间复杂度为O(1)
package sort.algorithm;
public class DirectInsertSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int data[] = { 2, 6, 10, 3, 9, 80, 1, 16, 27, 20 };
int temp, j;
for (int i = 1; i < data.length; i++) {
temp = data[i];
j = i - 1;
// 每次比较都是对于已经有序的
while (j >= 0 && data[j] > temp) {
data[j + 1] = data[j];
j--;
}
data[j + 1] = temp;
}
// 输出排序好的数据
for (int k = 0; k < data.length; k++) {
System.out.print(data[k] + " ");
}
}
}
三 插入类排序之折半插入排序(二分法排序)
条件:在一个已经有序的队列中,插入一个新的元素
折半插入排序记录的比较次数与初始序列无关
思想:折半插入就是首先将队列中取最小位置low和最大位置high,然后算出中间位置mid
将中间位置mid与待插入的数据data进行比较,
如果mid大于data,则就表示插入的数据在mid的左边,high=mid-1;
如果mid小于data,则就表示插入的数据在mid的右边,low=mid+1
最后整体进行右移操作。
时间复杂度O(n2),空间复杂度O(1)
package sort.algorithm;
//折半插入排序
public class HalfInsertSort {
public static void main(String[] args) {
int data[] = { 2, 6, 10, 3, 9, 80, 1, 16, 27, 20 };
// 存放临时要插入的元素数据
int temp;
int low, mid, high;
for (int i = 1; i < data.length; i++) {
temp = data[i];
// 在待插入排序的序号之前进行折半插入
low = 0;
high = i - 1;
while (low <= high) {
mid = (low + high) / 2;
if (temp < data[mid])
high = mid - 1;
else
// low=high的时候也就是找到了要插入的位置,
// 此时进入循环中,将low加1,则就是要插入的位置了
low = mid + 1;
}
// 找到了要插入的位置,从该位置一直到插入数据的位置之间数据向后移动
for (int j = i; j >= low + 1; j--)
data[j] = data[j - 1];
// low已经代表了要插入的位置了
data[low] = temp;
}
for (int k = 0; k < data.length; k++) {
System.out.print(data[k] + " ");
}
}
}
四 插入类排序之希尔排序
希尔排序,也叫缩小增量排序,目的就是尽可能的减少交换次数,每一个组内最后都是有序的。
将待续按照某一种规则分为几个子序列,不断缩小规则,最后用一个直接插入排序合成
空间复杂度为O(1),时间复杂度为O(nlog2n)
算法先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组中记录的下标相差d.对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。当增量减到1时,进行直接插入排序后,排序完成。
package sort.algorithm;
public class ShellSort {
public static void main(String[] args) {
int a[] = { 1, 54, 6, 3, 78, 34, 12, 45, 56, 100 };
double d1 = a.length;
int temp = 0;
while (true)
{
//利用这个在将组内倍数减小
//这里依次为5,3,2,1
d1 = Math.ceil(d1 / 2);
//d为增量每个分组之间索引的增量
int d = (int) d1;
//每个分组内部排序
for (int x = 0; x < d; x++)
{
//组内利用直接插入排序
for (int i = x + d; i < a.length; i += d) {
int j = i - d;
temp = a[i];
for (; j >= 0 && temp < a[j]; j -= d) {
a[j + d] = a[j];
}
a[j + d] = temp;
}
}
if (d == 1)
break;
}
for (int i = 0; i < a.length; i++)
System.out.print(a[i]+" ");
}
}
五 交换类排序之冒泡排序
交换类排序核心就是每次比较都要进行交换
冒泡排序:是一种交换排序
每一趟比较相邻的元素,较若大小不同则就会发生交换,每一趟排序都能将一个元素放到它最终的位置!每一趟就进行比较。
时间复杂度O(n2),空间复杂度O(1)
package sort.algorithm;
//冒泡排序:是一种交换排序
public class BubbleSort {
// 按照递增顺序排序
public static void main(String[] args) {
// TODO Auto-generated method stub
int data[] = { 2, 6, 10, 3, 9, 80, 1, 16, 27, 20, 13, 100, 37, 16 };
int temp = 0;
// 排序的比较趟数,每一趟都会将剩余最大数放在最后面
for (int i = 0; i < data.length - 1; i++) {
// 每一趟从开始进行比较,将该元素与其余的元素进行比较
for (int j = 0; j < data.length - 1; j++) {
if (data[j] > data[j + 1]) {
temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
}
}
}
for (int i = 0; i < data.length; i++)
System.out.print(data[i] + " ");
}
}