本文目錄一覽:
- 1、java泛型 二分查找
- 2、JAVA二分查找
- 3、用二分法查找(折半查找)java
- 4、用java寫二分搜索,要求數組是由用戶輸入,再輸入時,數組是無序的,要對數組進行從小到大的排序
- 5、JAVA 二分算法只能對數字進行查找嗎
java泛型 二分查找
以下代碼是關於對象的 二分查找 的例子,已經測試通過,執行即可。
Student 是基本比較對象類
Dichotomy 是二分法執行類
Test 是測試類
package com.dichotomy;
public class Student implements ComparableStudent {
private int id;
private String name;
private String idCard;
private String sex;
private String mobile;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
/**
* 排序控制
* @param o1 Student
* @param o2 Student
* @return int 返回 -1 向前移動, 1 向後移動, 0 不移動
* 這個方法需要自己進行調整,排序比較和二分查找時均使用此方法進行位置調整
* 比較時使用的key自己可以進行修改,不過要保證唯一性,否則查詢出來的值會不準確
*/
public int compareTo(Student o) {
//不同的執行次序決定排序和查找次序不同,可以同下面的調換一下
if(this.getId() o.getId()){
return -1;
} else if(this.getId() == o.getId()){
;
} else {
return 1;
}
//不同的執行次序決定排序和查找次序不同
int c = this.getIdCard().compareTo(o.getIdCard());
if(c != 0){
return c;
}
//不同的執行次序決定排序和查找次序不同
int n = this.getName().compareTo(o.getName());
if(n != 0){
return n;
}
return 0;
}
public String toString(){
StringBuffer sb = new StringBuffer();
sb.append(this.getId()).append(“\t”);
sb.append(this.getName()).append(“\t”);
sb.append(this.getIdCard()).append(“\t”);
sb.append(this.getMobile()).append(“\t”);
sb.append(this.getSex());
return sb.toString();
}
}
JAVA二分查找
//*******二分查找,都注釋了,複製所有代碼,保存成QuickSortApp.java*************//
class ArrayIns
{
private long theArray[];
private int nElems;
//——————–
public ArrayIns(int max){ //構造方法,初始化成員屬性。
theArray = new long[max];
nElems = 0;
}
//———————–
public void insert(long value){ //insert方法用於給數組賦值,並用nElems記錄數組元素的個數。
theArray[nElems] = value;
nElems++;
}
//—————————-
public void display(){ //display方法用於顯示數組的所有元素到控制台。
System.out.println(“A= “);
for(int j=0;jnElems;j++)
System.out.print(theArray[j]+” “);
System.out.println(“”);
}
//——————————
public void quickSort(){ //ArrayIns對象調用quickSort方法可以為其成員屬性theArray數組中的元素排序(從小到大)
recQuickSort(0,nElems-1); //調用recQuickSort方法開始排序,初始範圍從第一個到最後一個開始。
}
//——————————-
private void recQuickSort(int left,int right){ //recQuickSort方法進行數組元素的排序。left,right表示排序的範圍.
if(right-left = 0)
return; //如果right小於left,則第歸返回。此處是第歸的出口。
else {
long pivot = theArray[right]; //每次把排序範圍中的最後一個數作為排序時的參照數。
int partition = partitionIt(left,right,pivot); //調用prititionIt方法,參數列表中指明排序的範圍和參照數,並將方法的返回值賦給pritition變量(用來指明下一次排序時的範圍。)
//System.out.print(” “+1); //數字1代表第一次第歸的調用。
recQuickSort(left,partition-1); //第歸調用本方法,排序右範圍由partition-1來決定。
//System.out.print(” “+2); //數字2代表第二次第歸的調用。
recQuickSort(partition+1,right); //第歸調用本方法,排序左範圍由partition-1來決定。
}
}
//———————————–
private int partitionIt(int left,int right,long pivot){ //partitionIt方法完成left和right範圍內元素間排序的具體過程。
int leftPtr = left-1; //leftPrt表示左標識位,從left-1開始。
int rightPtr = right; //rightPrt表示右表識位,到right。 while(true){//永真循環。
while(theArray[++leftPtr] pivot); // 空循環,從leftPrt開始往rightPrt方向開始找一個比pivot大的數,用leftPtr記錄元素的位置。
while(rightPtr0 theArray[–rightPtr]pivot);//空循環,從rightPrt往leftPrt方向開始找一個比pivot小的數,用rightPrt記錄元素的位置,並且rightPtr0會保證不會數組越界。
if(leftPtr = rightPtr) //永真循環的出口,表示本次排序結束。
break;//跳出循環。
else
swap(leftPtr,rightPtr);//將leftPtr和rightPtr所在位置的元素進行交換。
}
swap(leftPtr,right); //調用swap方法。
return leftPtr; //將leftPtr返回到本方法被調用的位置。用來指明下一次排序時的範圍.
}
//———————————————
private void swap(int dex1,int dex2){ //swap方法用來將數組中的兩個元素進行交換,dex1和dex2分別表示兩個數組元素的位置。
long temp = theArray[dex1]; //temp變量作為兩個數組元素交換時的臨時中轉變量。
theArray[dex1] = theArray[dex2];
theArray[dex2] = temp;
}
}//////////////////////////////////////////////////////////////////////////////////////class QuickSortApp
{
public static void main(String[] args)
{
int maxSize = 10; //定義變量maxSize,並賦初值10.
ArrayIns arr;
arr = new ArrayIns(maxSize);//創建ArrayIns類的對象arr for(int j=0;jmaxSize;j++){
long n = (int)(java.lang.Math.random()*99);//產生隨機數。
arr.insert(n); //用insert方法為arr中的成員數組變量賦值。
}
arr.display(); //用display方法顯示arr中成員變量數組中的所有元素。
arr.quickSort(); //用quickSort方法為arr成員變量數組中的元素按從小到大排序。
arr.display(); //顯示。
}
}
用二分法查找(折半查找)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;
}}
運行結果演示:
由以上運行結果我們得知,如果要查找的數據在數組中存在,則輸出該數據在數組中的索引;如果不存在則輸出 -1 ,也就是打印 -1 則該數在數組中不存在,反之則存在。
四、利用遞歸的方式實現二分法查找
public class BinarySearch2 {
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, 0, array.length – 1);
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 要查找的值 * @param left 左邊最小值 * @param right 右邊最大值 * @return 返回值,成功返回索引,失敗返回-1 */
private static int binarySearch(int[] array, int aim, int left, int right) {
if (aim array[left] || aim array[right]) {
return -1;
}
// 找中間值 int mid = (left + right) / 2;
if (array[mid] == aim) {
return mid;
} else if (array[mid] aim) {
//如果中間值大於要找的值則從左邊一半繼續遞歸 return binarySearch(array, aim, left, mid – 1);
} else {
//如果中間值小於要找的值則從右邊一半繼續遞歸 return binarySearch(array, aim, mid + 1, array.length-1);
}
}}
運行結果演示:
總結:
遞歸相較於循環,代碼比較簡潔,但是時間和空間消耗比較大,效率低。在實際的學習與工作中,根據情況選擇使用。通常我們如果使用循環實現代碼只要不是太繁瑣都選擇循環的方式實現~
用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]||datadataset[endIndex]||beginIndexendIndex){
return -1;
}
if(data dataset[midIndex]){
return binarySearch(dataset,data,beginIndex,midIndex-1);
}else if(datadataset[midIndex]){
return binarySearch(dataset,data,midIndex+1,endIndex);
}else {
return midIndex;
}
}
}
JAVA 二分算法只能對數字進行查找嗎
2分法查找,前提是要有序,要排序,必然要比較大小,所以只要一個類它實現了Comparable接口的compareTo(T o)方法(Comparable在java.lang包中)或是實現一個比較器對象接口Comparator(Comparator在java.util包),都可以進行比較了。不管是String型,計本數據類型,還是其他什麼的,都可以用2分發查找了。給你看看API
java.util.Collections中2分法的API
binarySearch
public static T int binarySearch(List? extends Comparable? super T list,
T key)使用二分搜索法搜索指定列表,以獲得指定對象。在進行此調用之前,必須根據列表元素的自然順序對列表進行升序排序(通過 sort(List) 方法)。如果沒有對列表進行排序,則結果是不確定的。如果列表包含多個等於指定對象的元素,則無法保證找到的是哪一個。
此方法對“隨機訪問”列表運行 log(n) 次(它提供接近固定時間的位置訪問)。如果指定列表沒有實現 RandomAccess 接口並且是一個大型列表,則此方法將執行基於迭代器的二分搜索,執行 O(n) 次鏈接遍歷和 O(log n) 次元素比較。
參數:
list – 要搜索的列表。
key – 要搜索的鍵。
返回:
如果搜索鍵包含在列表中,則返回搜索鍵的索引;否則返回 (-(插入點) – 1)。插入點 被定義為將鍵插入列表的那一點:即第一個大於此鍵的元素索引;如果列表中的所有元素都小於指定的鍵,則為 list.size()。注意,這保證了當且僅當此鍵被找到時,返回的值將 = 0。
拋出:
ClassCastException – 如果列表中包含不可相互比較 的元素(例如,字符串和整數),或者搜索鍵無法與列表的元素進行相互比較。
——————————————————————————–
binarySearch
public static T int binarySearch(List? extends T list,
T key,
Comparator? super T c)使用二分搜索法搜索指定列表,以獲得指定對象。在進行此調用之前,必須根據指定的比較器對列表進行升序排序(通過 sort(List, Comparator) 方法)。如果沒有對列表進行排序,則結果是不確定的。如果列表包含多個等於指定對象的元素,則無法保證找到的是哪一個。
此方法對“隨機訪問”的列表運行 log(n) 次(它提供接近固定時間的位置訪問)。如果指定列表沒有實現 RandomAccess 接口並且是一個大型列表,則此方法將執行基於迭代器的二分搜索,執行 O(n) 次鏈接遍歷和 O(log n) 次元素比較。
參數:
list – 要搜索的列表。
key – 要搜索的鍵。
c – 排序列表的比較器。null 值指示應該使用元素的自然順序。
返回:
如果搜索鍵包含在列表中,則返回搜索鍵的索引;否則返回 (-(插入點) – 1)。插入點 被定義為將鍵插入列表的那一點:即第一個大於此鍵的元素索引;如果列表中的所有元素都小於指定的鍵,則為 list.size()。注意,這保證了當且僅當此鍵被找到時,返回的值將 = 0。
拋出:
ClassCastException – 如果列表中包含使用指定的比較器不可相互比較 的元素,或者使用此比較器無法相互比較搜索鍵與列表元素。
java.util.Comparator接口。
A int compare(T o1,T o2)比較用來排序的兩個參數。根據第一個參數小於、等於或大於第二個參數分別返回負整數、零或正整數。
在前面的描述中,符號 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 boolean equals(Object obj)指示某個其他對象是否“等於”此 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
public interface ComparableT此接口強行對實現它的每個類的對象進行整體排序。這種排序被稱為類的自然排序,類的 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
int compareTo(T o)比較此對象與指定對象的順序。如果該對象小於、等於或大於指定對象,則分別返回負整數、零或正整數。
實現類必須確保對於所有的 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 – 如果指定對象的類型不允許它與此對象進行比較。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/259488.html