数据结构与算法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)包含自组织方式的顺序查找

使用自组织(数据的位置并非由程序员在执行之前就组织好,而是在程序运行过程中由程序自动组织的)数据
通过将频繁查找到的元素置于数据集的起始位置来最小化查找次数

a. 包含自组织方式的seqSearch(1):不断检查确认已找到的数据是否已经排在最前面。

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):将找到的元素移动到数据集的起始位置,但是如果这个元素已经很接近起始位置,则不会对它的位置进行交换。

80-20原则:对某一数据集执行的80%的查找操作都是对其中20%的数据元素进行查找。

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)) {
                // 仅当数据位于数据集的前20%元素之外时,该数据才需要被重新移动到数据集的起始位置。
                [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. 二分查找算法【已排序数据】

算法描述:
(1)将数组的第一个位置设置为下边界(0)
(2)将数组最后一个元素所在的位置设置为上边界(数组的长度减1)
(3)若下边界等于或小于上边界,则做如下操作:
a. 将中点设置为(上边界加上下边界)除以2
b. 如果中点的元素小于查询的值,则将下边界设置为中点元素所在下标加1
c. 如果中点的元素大于查询的值,则将上边界设置为中点元素所在下标减1
d. 否则中点元素即为要查找的数据,可以进行返回

实现:

function binSearch(arr, target) {
    const len = arr.length
    let upperBound = len - 1
    let lowBound = 0
    while (lowBound <= upperBound) {
        // 将中点设置为 (上边界 + 下边界) / 2
        let mid = Math.floor((lowBound + upperBound) / 2)
        console.log(`当前的中点值:${arr[mid]}`)
        if (arr[mid] < target) {
            // 如果中点的元素小于查询的值,则将下边界设置为中点元素所在的下标加一
            lowBound = mid + 1
        } else if (arr[mid] > target) {
            // 如果中点的元素大于查询的值,则将上边界设置为中点元素所在的下标减一
            upperBound = mid - 1
        } else {
            // 否则中点元素即为要查找的数据,可以进行返回
            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)
// 当前的中点值:59
// 当前的中点值:77
// 当前的中点值:78
// 8

示例:计算一个数组中某个数的重复次数

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++
        // 向下(左)遍历数组,统计找到的值出现的次数,当下一个值与要查找的值不匹配时停止计数
        for (let i = pos - 1; i > 0; i--) {
            if (arr[i] === target) {
                count++
            } else {
                break
            }
        }
        // 向上(右)遍历数组,统计找到的值出现的次数,当下一个值与要查找的值不匹配时停止计数
        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(`重复次数为:${result7}次`)

// 当前的中点值:59
// 当前的中点值:77
// 当前的中点值:72
// 重复次数为:2次
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • 一、顺序查找(线性查找) 从列表的第一个元素开始对列表元素逐个进行判断,直到找到了想要的结果,或者直到列表结尾也没...
    一只dororo阅读 1,257评论 0 1
  • 9.3.3 快速排序   快速排序将原数组划分为两个子数组,第一个子数组中元素小于等于某个边界值,第二个子数组中的...
    RichardJieChen阅读 1,839评论 0 3
  • 雅美婚庆策划文化传播公司,雅美婚礼服务团队以专业的素质、暖心的服务、顶尖的设备、极具创意的婚礼策划为您打造完美婚礼...
    阿廖_2a59阅读 148评论 0 0
  • "知乎上关于思维导图的提问不下几万条?也有人向上图一样问…有人说思维导图是世纪最有价值的发明,也有人也许会不屑的说...
    Miss伊柚阅读 589评论 1 3