2017-08-28 47 views
1

我試着在我的代碼示例中使用二分搜索算法,但它沒有像我期望的那樣運行。我不知道爲什麼。請解釋我二進制搜索未運行?

var array = [1, 4, 6, 8, 9, 12, 15, 17, 19, 34, 55, 78, 80]; 

function binarySearch (array, numberToSearch) { 
var firstIndex = 0; 
var lastIndex = array.length - 1; 
var currentIndex; 
var currentElement; 

currentIndex = (lastIndex + firstIndex)/2 | 2; 
currentElement = array[currentIndex]; 

while (firstIndex <= lastIndex) { 
    if (numberToSearch === currentElement) { 
     // found 
     console.log(currentIndex); 
     return currentIndex; 
    } else if (numberToSearch < currentElement) { 
     lastIndex = currentIndex - 1; 
     currentIndex = (lastIndex + firstIndex)/2 | 2; 
     currentElement = array[currentIndex]; 
    } else if (numberToSearch > currentElement) { 
     firstIndex = currentIndex + 1; 
     currentIndex = (lastIndex + firstIndex)/2 | 2; 
     currentElement = array[currentIndex]; 
    } 
} 
return -1; 
} 
binarySearch(array, 12); 

我應該打印:5,但沒有happend

+1

我想,你的意思二進制搜索不是二進制排序優化? – abhishekkannojia

+0

我認爲你不允許循環運行完全使用那些返回-1。我認爲你正在迭代迭代解決方案和遞歸解決方案。 – 82Tuskers

+0

@ 82Tuskers我沒有結果條件返回-1。但我認爲這不是問題 –

回答

1

什麼是你的代碼錯誤:

  1. 應該var currentIndex = (lastIndex + firstIndex)/2 | 0; (不| 2);

  2. currentIndexcurrentElement應該在循環內的每個 迭代計算。

所以,這是你的代碼的修正版本:

var array = [1, 4, 6, 8, 9, 12, 15, 17, 19, 34, 55, 78, 80]; 
 

 
function binarySearch (array, numberToSearch) { 
 
var firstIndex = 0; 
 
var lastIndex = array.length - 1; 
 

 
while (firstIndex <= lastIndex) { 
 
    var currentIndex = (lastIndex + firstIndex)/2 | 0; 
 
    var currentElement = array[currentIndex]; 
 
    if (numberToSearch === currentElement) { 
 
     return currentIndex; 
 
    } else if (numberToSearch < currentElement) { 
 
     lastIndex = currentIndex - 1; 
 
    } else if (numberToSearch > currentElement) { 
 
     firstIndex = currentIndex + 1; 
 
    } 
 
} 
 
return -1; 
 
} 
 

 
console.log(binarySearch(array, 99)); // -1 
 
console.log(binarySearch(array, 12)); // 5

順便說一句,這var currentIndex = (lastIndex + firstIndex)/2 | 0;看起來相當不尋常。常見的方式是var currentIndex = Math.floor((lastIndex + firstIndex)/2);

+1

儘管'var currentIndex =(lastIndex + firstIndex)/ 2 | 0;'對你來說似乎並不熟悉,它是[最優](https://jsperf.com/jsfvsbitnot/8)。你不應該阻礙良好的做法。 –

+1

我相信你是對的,但它在JS的這種背景下並不常用 - 我的意思是這不是每個人都知道和理解的東西,而且優化本身幾乎不可感知。所以,我更喜歡使用更清晰的東西。 – curveball

+0

順便說一句,一旦我觀看了道格拉斯克羅克福德的視頻,他警告人們來自C++等,在JS位操作員有不同的成本,他不建議使用它們,除非他們是你真正想要執行的。 – curveball

1

首先,什麼是按位OR這裏的一點:

currentIndex = (lastIndex + firstIndex)/2 | 2; 

我覺得應該是:

currentIndex = (lastIndex + firstIndex)/2; 

有一個在搜索基本缺陷空間更新。 當numberToSearch < currentElementmiddle element(位於索引CURRENTINDEX元件)大於將要搜索數目,因此,正確新邊界是

lastIndex = currentIndex - 1; 

而且當numberToSearch > currentElement指在索引CURRENTINDEX的middle element元件)小於要搜索的數量,因此,正確的新的邊界是

firstIndex = currentIndex + 1; 

因此,正確的代碼是:

var array = [1, 4, 6, 8, 9, 12, 15, 17, 19, 34, 55, 78, 80]; 

function binarySearch (array, numberToSearch) { 
var firstIndex = 0; 
var lastIndex = array.length - 1; 
var currentIndex; 
var currentElement; 

currentIndex = (lastIndex + firstIndex)/2; 
currentElement = array[currentIndex]; 

while (firstIndex <= lastIndex) { 
    if (numberToSearch === currentElement) { 
     // found 
     console.log(currentIndex); 
     return currentIndex; 
    } else if (numberToSearch < currentElement) { 
     lastIndex = currentIndex - 1; 
     currentIndex = (lastIndex + firstIndex)/2 | 2; 
     currentElement = array[currentIndex]; 
    } else if (numberToSearch > currentElement) { 
     firstIndex = currentIndex + 1; 
     currentIndex = (lastIndex + firstIndex)/2 | 2; 
     currentElement = array[currentIndex]; 
    } 
} 
return -1; 
} 
binarySearch(array, 12); 
+0

哦,我在邏輯代碼中看到我的錯誤:)。我編輯它,但你知道,仍然沒有得到結果。您可以嘗試在您的計算機上運行此代碼。邏輯是真的。 –

+1

他最初在不使用'Math.floor()'時是正確的。他使用的方法[有時更快](https://jsperf.com/jsfvsbitnot/8),但應該是0,而不是2. –

1

這裏是你的答案更正與所有我更新的地方。你非常接近!看起來好像你在合併二進制搜索的iterative版本和recursive解決方案。

CodePen Demo

var array = [1, 4, 6, 8, 9, 12, 15, 17, 19, 34, 55, 78, 80]; 

function binarySearch (array, numberToSearch) { 
    var firstIndex = 0; 
    var lastIndex = array.length - 1; 
    var currentIndex; 
    var currentElement; 

    while (firstIndex <= lastIndex) { 
    currentIndex = (lastIndex + firstIndex)/2 | 0; //should default to zero, not Two! 
    currentElement = array[currentIndex];//These should both update every iteration so it does not infinitely loop! 
    if (numberToSearch === currentElement) { 
     // found 
     console.log(currentIndex); 
     return currentIndex; 
    }else if (numberToSearch < currentElement) { 
     lastIndex = currentIndex - 1; //If current is too big, move right pointer to the left 
    }else if (numberToSearch > currentElement) { 
     firstIndex = currentIndex + 1;//If current is too small, move left pointer to the right 
    } 
    } 
    return -1;//When condition of while it broken and no solution has been found, return -1 to indicate it is not in the array 
} 
binarySearch(array, 12) //5 

進一步利用Math.floor()作爲number | 0is sometimes faster.

+0

非常乾淨!感謝您花費時間解決我的問題:) –