前面我们探讨了冒泡排序,今天我们接着讲讲选择排序,其实跟冒泡有点像的,但概念上不一样,童鞋,你听我慢慢跟你说。
什么是选择排序?
引言
最近看了一则寓言故事跟童鞋们分享一下,讲的是大山深处的神坑(为了激发大家的想象力,这里我就不画画了,请同学们自行脑补)。事情是这样子的,旁白站在上帝视角抛出一个上帝之问?为什么穷人努力工作还是越来越穷,生活不见起色,而富人却越来越富。一天,他们一同去爬山,这里我们先不考虑“推下去”这个梗,毕竟张东升他没去。当他们快到达山顶的时候,穷人看见前面的大坑,发现自己迈不过去,于是他找来了推车,一车子一车子地推石头子,打算把它填满,推的精疲力竭啊,一不小心脚绊倒了石头,连车带石头都掉进了神坑,这个时候他很苦恼,家里还有老还有小,我要努力我不能放弃啊,于是他又用双手搬石头一块一块地去填。此时,富人推着一个圆滚滚的巨石,将它推入坑中,因为直径比坑大,所有刚好卡在了上面,富人巧妙地通过了神坑。这个故事告诉我们,努力是没有错的,它也很重要,当你努力到一定程度就会由量变引起质变,但很多时候啊,选择大于努力。我们的一生会遇到很多的苦难和险阻,有坑在所难免,面对前方的未知,谁不怕呀!关键是我们要怎样去做好选择,走好每一步,这就引出了我们今天的话题“选择排序”。
定义
上面的故事,穷人和富人做的选择不一样,穷人做了很多次选择,选的都是比坑小的石头,而富人有其得道的见解,选了一块巨石去把坑给堵住了。再理解这个选择以后呢,我们再进一步做个游戏。
结合上面选择的案例思想,给定五块随机排列的石头,请你想一种办法,让他们由小到大排列。
我们是不是可以这样子去做,第一次,我找出了最小的那块石头,我把它和第一个位置的选手交换位置,第二次,我从第二个位置开始找一块最小的石头,找到后和第二个位置交换一下,以此类推,这个问题是不是就解决了啊。
所有,我们给出一个定义,给定一组数据集,对这组数据集进行遍历、每次从对应下标开始往后遍历找出最小的那位,将其与最开始的下标所在元素进行交换位置,形如这样的排序,我们将其称为“选择排序”。
实现一个选择排序
思路: 我们可以先假定那个min为最开始的那个元素,然后记录其下表进行遍历,当找到最小的那个元素之后,我们把min假定为最小元素后面那个,然后更新下标,以此类推,所以其平均复杂度是O(n^2)
code:
export default (arr) => {
let min = arr[0];
let idx = 0;
for (let i = 0; i < arr.length - 1; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (min > arr[j]) {
min = arr[j];
idx = j;
}
}
[arr[i], arr[idx]] = [min, arr[i]];
[min, idx] = [arr[i + 1], i + 1];
}
return arr;
}
test:
这里笔者准备了几个测试用例,测试都通过了,这个排序应该没啥问题。
test case:
import selectSort from '../src/select';
test('select sort: test case 1', () => {
expect(selectSort([2, 4, 3, 1])).toEqual([1, 2, 3, 4]);
});
test('select sort: test case 2', () => {
expect(selectSort([2, 0, 2, 0])).toEqual([0, 0, 2, 2]);
});
test('select sort: test case 3', () => {
expect(selectSort([1, 9, 9, 7])).toEqual([1, 7, 9, 9]);
});
test('select sort: test case 4', () => {
expect(selectSort([0, 6, 1, 3])).toEqual([0, 1, 3, 6]);
});
test result:
PS E:document
eposJavaScript-Tsukukicodesort-study> npm run test:select
> sort-study@1.0.0 test:select E:document
eposJavaScript-Tsukukicodesort-study
> jest test/select.test.js
PASS test/select.test.js
√ select sort: test case 1 (15 ms)
√ select sort: test case 2
√ select sort: test case 3
√ select sort: test case 4
Test Suites: 1 passed, 1 total
Tests: 4 passed, 4 total
Snapshots: 0 total
Time: 7.013 s
Ran all test suites matching /test\select.test.js/i.
PS E:document
eposJavaScript-Tsukukicodesort-study>
emmm, 这里我是测试和开发分开写的,有兴趣可以阅读我之前写的jest的使用https://www.cnblogs.com/cnroadbridge/p/13524099.html
优化选择排序
跟之前讲的冒泡排序一次冒两个泡泡一个道理,你一次选择两个,一个最大一个最小,最大的与最后一个元素换位置,最小的与最前面的换位置,一个道理,有兴趣的童鞋自己实践下。
最后
本文选自Javascript筑基专题文章,项目地址:https://github.com/ataola/JavaScript-Tsukuki
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。