數(shù)據(jù)結(jié)構(gòu)與算法JavaScript描述(12) —— 檢索算法(Search)

1. 順序查找

(1)查找某值

function seqSearch(arr, target) {
    const len = arr && arr.length
    if (!len) return -1
    for (let i = 0; i < len; i++) {
        if (arr[i] === target) {
            return i
        }
    }
    return -1
}

// test
const arr1 = [72, 54, 59, 30, 31, 78, 2, 77, 82, 72]
const result1 = seqSearch(arr1, 82)
console.log(result1)    // 8

(2)查找最小值

function findMin(arr) {
    const len = arr && arr.length
    if (!len) return null
    let min = arr[0]
  for(let i = 1; i < len; i++) {
    if (arr[i] < min) {
        min = arr[i]
    }
  }
  return min
}

// test
const arr2 = [72, 54, 59, 30, 31, 78, 2, 77, 82, 72]
const result2 = findMin(arr2)
console.log(result2)    // 2

(3)查找最大值

function findMax(arr) {
    const len = arr && arr.length
    if (!len) return null
    let max = arr[0]
    for (let i = 1; i < len; i++) {
        if (arr[i] > max) {
            max = arr[i]
        }
    }
    return max
}

// test
const arr3 = [72, 54, 59, 30, 31, 78, 2, 77, 82, 72]
const result3 = findMax(arr3)
console.log(result3)    // 82

(4)包含自組織方式的順序查找

使用自組織(數(shù)據(jù)的位置并非由程序員在執(zhí)行之前就組織好,而是在程序運(yùn)行過程中由程序自動組織的)數(shù)據(jù)
通過將頻繁查找到的元素置于數(shù)據(jù)集的起始位置來最小化查找次數(shù)

a. 包含自組織方式的seqSearch(1):不斷檢查確認(rèn)已找到的數(shù)據(jù)是否已經(jīng)排在最前面。

function seqSearch(arr, target) {
    const len = arr.length
    for (let i = 0; i < len; i++) {
        if (arr[i] === target) {
            if (i > 0) {
                [arr[i - 1], arr[i]] = [arr[i], arr[i - 1]]
            }
            return true
        }
    }
    return false
}

// test
const arr4 =  [72, 54, 59, 30, 31, 78, 2, 77, 82, 72]
for(let i = 1; i <= 4; i++) {
    const result4 =  seqSearch(arr4, 77)
    console.log(arr4)
    // [72, 54, 59, 30, 31, 78, 77, 2, 82, 72]
    // [72, 54, 59, 30, 31, 77, 78, 2, 82, 72]
    // [72, 54, 59, 30, 77, 31, 78, 2, 82, 72]
    // [72, 54, 59, 77, 30, 31, 78, 2, 82, 72]
}

b. 包含自組織方式的seqSearch(2):將找到的元素移動到數(shù)據(jù)集的起始位置,但是如果這個元素已經(jīng)很接近起始位置,則不會對它的位置進(jìn)行交換。

80-20原則:對某一數(shù)據(jù)集執(zhí)行的80%的查找操作都是對其中20%的數(shù)據(jù)元素進(jìn)行查找。

function seqSearch(arr, target) {
    const len = arr.length
    for (let i = 0; i < len; i++) {
        if (arr[i] === target) {
            if (i > (arr.length * 0.2)) {
                // 僅當(dāng)數(shù)據(jù)位于數(shù)據(jù)集的前20%元素之外時(shí),該數(shù)據(jù)才需要被重新移動到數(shù)據(jù)集的起始位置。
                [arr[0], arr[i]] = [arr[i], arr[0]]
            }
            return true
        }
    }
    return false
}

// test
const arr5 =  [72, 54, 59, 30, 31, 78, 2, 77, 82, 72]
for(let i = 1; i <= 4; i++) {
    const result5 =  seqSearch(arr5, 77)
    console.log(arr5)
    // [77, 54, 59, 30, 31, 78, 2, 72, 82, 72]
    // [77, 54, 59, 30, 31, 78, 2, 72, 82, 72]
    // [77, 54, 59, 30, 31, 78, 2, 72, 82, 72]
    // [77, 54, 59, 30, 31, 78, 2, 72, 82, 72]
}

2. 二分查找算法【已排序數(shù)據(jù)】

算法描述:
(1)將數(shù)組的第一個位置設(shè)置為下邊界(0)
(2)將數(shù)組最后一個元素所在的位置設(shè)置為上邊界(數(shù)組的長度減1)
(3)若下邊界等于或小于上邊界,則做如下操作:
a. 將中點(diǎn)設(shè)置為(上邊界加上下邊界)除以2
b. 如果中點(diǎn)的元素小于查詢的值,則將下邊界設(shè)置為中點(diǎn)元素所在下標(biāo)加1
c. 如果中點(diǎn)的元素大于查詢的值,則將上邊界設(shè)置為中點(diǎn)元素所在下標(biāo)減1
d. 否則中點(diǎn)元素即為要查找的數(shù)據(jù),可以進(jìn)行返回

實(shí)現(xiàn):

function binSearch(arr, target) {
    const len = arr.length
    let upperBound = len - 1
    let lowBound = 0
    while (lowBound <= upperBound) {
        // 將中點(diǎn)設(shè)置為 (上邊界 + 下邊界) / 2
        let mid = Math.floor((lowBound + upperBound) / 2)
        console.log(`當(dāng)前的中點(diǎn)值:${arr[mid]}`)
        if (arr[mid] < target) {
            // 如果中點(diǎn)的元素小于查詢的值,則將下邊界設(shè)置為中點(diǎn)元素所在的下標(biāo)加一
            lowBound = mid + 1
        } else if (arr[mid] > target) {
            // 如果中點(diǎn)的元素大于查詢的值,則將上邊界設(shè)置為中點(diǎn)元素所在的下標(biāo)減一
            upperBound = mid - 1
        } else {
            // 否則中點(diǎn)元素即為要查找的數(shù)據(jù),可以進(jìn)行返回
            return mid
        }
    }
    return -1
}

// test
const arr6 = [2, 30, 31, 54, 59, 72, 72, 77, 78, 82]
const result6 = binSearch(arr6, 78)
console.log(result6)
// 當(dāng)前的中點(diǎn)值:59
// 當(dāng)前的中點(diǎn)值:77
// 當(dāng)前的中點(diǎn)值:78
// 8

示例:計(jì)算一個數(shù)組中某個數(shù)的重復(fù)次數(shù)

function count(arr, target) {
    const len = arr.length
    let count = 0
    arr.sort((a, b) => { return a - b })
    let pos = binSearch(arr, target)
    if (pos > -1) {
        count++
        // 向下(左)遍歷數(shù)組,統(tǒng)計(jì)找到的值出現(xiàn)的次數(shù),當(dāng)下一個值與要查找的值不匹配時(shí)停止計(jì)數(shù)
        for (let i = pos - 1; i > 0; i--) {
            if (arr[i] === target) {
                count++
            } else {
                break
            }
        }
        // 向上(右)遍歷數(shù)組,統(tǒng)計(jì)找到的值出現(xiàn)的次數(shù),當(dāng)下一個值與要查找的值不匹配時(shí)停止計(jì)數(shù)
        for (let j = pos + 1; j < len; j++) {
            if (arr[j] === target) {
                count++
            } else {
                break
            }
        }
    }
    return count
}

// test
const arr7 = [72, 54, 59, 30, 31, 78, 2, 77, 82, 72]
const result7 = count(arr7, 72)
console.log(`重復(fù)次數(shù)為:${result7}次`)

// 當(dāng)前的中點(diǎn)值:59
// 當(dāng)前的中點(diǎn)值:77
// 當(dāng)前的中點(diǎn)值:72
// 重復(fù)次數(shù)為:2次
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,238評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,430評論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,134評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,893評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,653評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,136評論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,212評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,372評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,888評論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,738評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,939評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,482評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,179評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,588評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,829評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,610評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,916評論 2 372

推薦閱讀更多精彩內(nèi)容