當前位置:首頁 » 編程語言 » java二分查找演算法

java二分查找演算法

發布時間: 2024-05-19 21:37:38

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;j<nElems;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(rightPtr>0 && theArray[--rightPtr]>pivot);//空循環,從春禪rightPrt往leftPrt方向開始找一個比pivot小的數,用rightPrt記錄元素的位置,並且rightPtr>0會保證不會數組越界。
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;j<maxSize;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二分法查找的遞歸演算法怎麼實現

publicclass二分法遞歸查找{
publicstaticvoidmain(String[]args){

//定義數組,注意,二分查找數組必須是有序的數組!
int[]arr={1,3,5,7,9,11,13,15,17};

//接受查找後的返回值:索引值,如果沒有則是-1;
//測試查找元素:9
inta=binary(arr,9,0,arr.length-1);
System.out.println("被查找數字索引位置在:"+a);
}
//參數列表依次為:被查找的數組,查找的數字,頭索引,尾索引!
publicstaticintbinary(int[]arr,intkey,intstar,intend)//遞歸
{
//每次進來創建,中間索引值!
intmid=(star+end)/2;
//如果被查找數小於頭,或者尾,或者頭索引大於尾索引,則說明無該數,返回-1;
if(key<arr[star]||key>arr[end]||star>end){
return-1;
}
//如果中間值小於被查找數,則重新定義頭索引移至中間+1位置,篩選掉一半數字!
if(arr[mid]<key){
//開始遞歸!
returnbinary(arr,key,mid+1,end);
//否則如果中間值大於被查找數,則重新尾索引移至中間-1位置,篩選掉一半數字!
}elseif(arr[mid]>key){
//開始遞歸!
returnbinary(arr,key,star,mid-1);
}else{
//否者就是找到了,返回該索引!
returnmid;
}
}
}

③ 用Java語言編寫對整型數組進行二分查找的程序。

public class BinarySearchDemo {

public static void main(String[] args) {
int[] a = new int[]{1,5,7,9,11,18,23,48,69};
int point = new BinarySearchDemo().binarySearch(a, 23);

if(point == -1)
System.out.println("在數組中未查找到數23");
else
System.out.println("數字23是數組中第 " + (point + 1) + " 位數");

}

/**
* 二分法查找一個整數在整型數組中的位置
*
* 演算法思路:首先得到數組a的最小值和最大值的下標,分別是:low和high,接著求出值位於數組中間那個數的下標middle
* 然後再將這個middle對應的數組中的數和待查找的數num進行比較,如果相等,則表示已查找到,如果num < a[middle]
* 則說明num位於a[low]和a[middle]之間,於是將a[middle - 1]設為較大值,繼續求出此時對應的a[middle],
* 再進行比較,其他情況可依次類推。一直到low=high,如果此時還沒有在數組a中查找到,則說明該數組a中沒有值num,返回-1
*
* @param a 給定的整型數組
* @param num 待查找的數 num
*
* @return 返回整數num在數組a中的位置下標,如果未查找到則返回-1
* */
public int binarySearch(int[] a,int num){
int low = 0;
int high = a.length - 1;

while(low <= high){
int middle = (low + high) / 2;
if(num == a[middle])
return middle;
else if(num < a[middle])
high = middle - 1;
else
low = middle + 1;
}

return -1;
}

}

程序基本上就是這樣了,其中注釋中有詳細的解釋說明

④ 怎麼樣利用二分法查找數據中的字串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;
}}
運行結果演示:

總結:

遞歸相較於循環,代碼比較簡潔,但是時間和空間消耗比較大,效率低。在實際的學習與工作中,根據情況選擇使用。通常我們如果使用循環實現代碼只要不是太繁瑣都選擇循環的方式實現~

⑤ 常見查找和排序演算法

查找成功最多要n 次,平均(n+1)/2次, 時間復雜度為O(n)
優點:既適用順序表也適用單鏈表,同時對表中元素順序無要求,給插入帶來方便,只需插入表尾即可。
缺點:速度較慢。

改進:在表尾設置一個崗哨,這樣不用去循環判斷數組下標是否越界,因為最後必然成立。

適用條件:

二分查找的判定樹不僅是二叉排序樹,而且是一棵理想平衡樹。 時間復雜度為O(lbn)

循環實現

遞歸實現

待排序的元素需要實現 Java 的 Comparable 介面,該介面有 compareTo() 方法,可以用它來判斷兩個元素的大小關系。

從數組中選擇最小元素,將它與數組的第一個元素交換位置。再從數組剩下的元素中選擇出最小的元素,將它與數組的第二個元素交換位置。不斷進行這樣的操作,直到將整個數組排序。

選擇排序需要 ~N2/2 次比較和 ~N 次交換,==它的運行時間與輸入無關==,這個特點使得它對一個已經排序的數組也需要這么多的比較和交換操作。

從左到右不斷 交換相鄰逆序的元素 ,在一輪的循環之後,可以讓未排序的最大元素上浮到右側。

在一輪循環中,如果沒有發生交換,那麼說明數組已經是有序的,此時可以直接退出。

每次都 將當前元素插入到左側已經排序的數組中 ,使得插入之後左側數組依然有序。

對於數組 {3, 5, 2, 4, 1},它具有以下逆序:(3, 2), (3, 1), (5, 2), (5, 4), (5, 1), (2, 1), (4, 1),插入排序每次只能交換相鄰元素,令逆序數量減少 1,因此插入排序需要交換的次數為逆序數量。

==插入排序的時間復雜度取決於數組的初始順序,如果數組已經部分有序了,那麼逆序較少,需要的交換次數也就較少,時間復雜度較低==。

對於大規模的數組,插入排序很慢,因為它只能交換相鄰的元素,每次只能將逆序數量減少 1。希爾排序的出現就是為了解決插入排序的這種局限性,它通過交換不相鄰的元素,每次可以將逆序數量減少大於 1。

希爾排序使用插入排序對間隔 h 的序列進行排序。通過不斷減小 h,最後令 h=1,就可以使得整個數組是有序的。

希爾排序的運行時間達不到平方級別,使用遞增序列 1, 4, 13, 40, ... 的希爾排序所需要的比較次數不會超過 N 的若干倍乘於遞增序列的長度。後面介紹的高級排序演算法只會比希爾排序快兩倍左右。

歸並排序的思想是將數組分成兩部分,分別進行排序,然後歸並起來。

歸並方法將數組中兩個已經排序的部分歸並成一個。

將一個大數組分成兩個小數組去求解。

因為每次都將問題對半分成兩個子問題,這種對半分的演算法復雜度一般為 O(NlogN)。

先歸並那些微型數組,然後成對歸並得到的微型數組。

取 a[l] 作為切分元素,然後從數組的左端向右掃描直到找到第一個大於等於它的元素,再從數組的右端向左掃描找到第一個小於它的元素,交換這兩個元素。不斷進行這個過程,就可以保證左指針 i 的左側元素都不大於切分元素,右指針 j 的右側元素都不小於切分元素。當兩個指針相遇時,將切分元素 a[l] 和 a[j] 交換位置。

快速排序是原地排序,不需要輔助數組,但是遞歸調用需要輔助棧。

快速排序最好的情況下是每次都正好將數組對半分,這樣遞歸調用次數才是最少的。這種情況下比較次數為 CN=2CN/2+N,復雜度為 O(NlogN)。

最壞的情況下,第一次從最小的元素切分,第二次從第二小的元素切分,如此這般。因此最壞的情況下需要比較 N2/2。為了防止數組最開始就是有序的,在進行快速排序時需要隨機打亂數組。

因為快速排序在小數組中也會遞歸調用自己,對於小數組,插入排序比快速排序的性能更好,因此在小數組中可以切換到插入排序。

最好的情況下是每次都能取數組的中位數作為切分元素,但是計算中位數的代價很高。一種折中方法是取 3 個元素,並將大小居中的元素作為切分元素。

對於有大量重復元素的數組,可以將數組切分為三部分,分別對應小於、等於和大於切分元素。

三向切分快速排序對於有大量重復元素的隨機數組可以在線性時間內完成排序。

快速排序的 partition() 方法,會返回一個整數 j 使得 a[l..j-1] 小於等於 a[j],且 a[j+1..h] 大於等於 a[j],此時 a[j] 就是數組的第 j 大元素。

可以利用這個特性找出數組的第 k 大的元素。

該演算法是線性級別的,假設每次能將數組二分,那麼比較的總次數為 (N+N/2+N/4+..),直到找到第 k 個元素,這個和顯然小於 2N。

堆中某個節點的值總是大於等於其子節點的值,並且堆是一顆完全二叉樹。

堆可以用數組來表示,這是因為堆是完全二叉樹,而完全二叉樹很容易就存儲在數組中。位置 k 的節點的父節點位置為 k/2,而它的兩個子節點的位置分別為 2k 和 2k+1。這里不使用數組索引為 0 的位置,是為了更清晰地描述節點的位置關系。

在堆中,當一個節點比父節點大,那麼需要交換這個兩個節點。交換後還可能比它新的父節點大,因此需要不斷地進行比較和交換操作,把這種操作稱為上浮。

類似地,當一個節點比子節點來得小,也需要不斷地向下進行比較和交換操作,把這種操作稱為下沉。一個節點如果有兩個子節點,應當與兩個子節點中最大那個節點進行交換。

將新元素放到數組末尾,然後上浮到合適的位置。

從數組頂端刪除最大的元素,並將數組的最後一個元素放到頂端,並讓這個元素下沉到合適的位置。

把最大元素和當前堆中數組的最後一個元素交換位置,並且不刪除它,那麼就可以得到一個從尾到頭的遞減序列,從正向來看就是一個遞增序列,這就是堆排序。

一個堆的高度為logN,因此在堆中插入元素和刪除最大元素的復雜度都為 logN。

對於堆排序,由於要對 N 個節點進行下沉操作,因此復雜度為 NlogN。

堆排序是一種原地排序,沒有利用額外的空間。

現代操作系統很少使用堆排序,因為它無法利用局部性原理進行緩存,也就是數組元素很少和相鄰的元素進行比較和交換。

計數排序的核心在於將輸入的數據值轉化為鍵存儲在額外開辟的數組空間中。作為一種線性時間復雜度的排序,==計數排序要求輸入的數據必須是有確定范圍的整數==。

當輸入的元素是 n 個 0 到 k 之間的整數時,它的==運行時間是 O(n + k)==。計數排序不是比較排序,排序的速度快於任何比較排序演算法。由於用來計數的數組C的長度取決於待排序數組中數據的范圍(等於待排序數組的最大值與最小值的差加上1),這使得計數排序對於數據范圍很大的數組,需要大量時間和內存。比較適合用來排序==小范圍非負整數數組的數組==。

桶排序是計數排序的升級版。它利用了函數的映射關系,高效與否的關鍵就在於這個映射函數的確定。為了使桶排序更加高效,我們需要做到這兩點:

同時,對於桶中元素的排序,選擇何種比較排序演算法對於性能的影響至關重要。

當輸入數據均勻分配到每一個桶時最快,當都分配到同一個桶時最慢。

實間復雜度N*K

快速排序是最快的通用排序演算法,它的內循環的指令很少,而且它還能利用緩存,因為它總是順序地訪問數據。它的運行時間近似為 ~cNlogN,這里的 c 比其它線性對數級別的排序演算法都要小。

使用三向切分快速排序,實際應用中可能出現的某些分布的輸入能夠達到線性級別,而其它排序演算法仍然需要線性對數時間。

熱點內容
稅盤密碼忘了去改需要帶什麼 發布:2024-11-27 15:41:10 瀏覽:276
拉筋要加密 發布:2024-11-27 15:38:51 瀏覽:323
電腦當伺服器怎麼降低功耗 發布:2024-11-27 15:30:45 瀏覽:641
蘋果手機誇克緩存的視頻怎麼轉為本地視頻 發布:2024-11-27 15:24:05 瀏覽:810
linuxm4 發布:2024-11-27 15:15:12 瀏覽:321
演算法交易現狀 發布:2024-11-27 15:05:49 瀏覽:825
搜同網伺服器為什麼登錄不上 發布:2024-11-27 15:05:41 瀏覽:287
如何讓無線網速變快華為安卓手機 發布:2024-11-27 15:04:13 瀏覽:595
cod17編譯著色器卡住c盤滿了 發布:2024-11-27 14:55:56 瀏覽:386
鎖機軟體反編譯 發布:2024-11-27 14:36:02 瀏覽:148