当前位置:网站首页>【js】-【排序-相关】-笔记
【js】-【排序-相关】-笔记
2022-07-04 22:58:00 【有趣的学习】
【js】-【排序-相关】-笔记
API相关
在javascript中, sort方法用于根据一定条件对数组元素进行排序。如果调用sort()方法时没有传递参数,则按字母顺序对数组中的元素进行排序;如果提供一个函数参数,则根据该函数提供的顺序来对数组中的元素进行排序。
sort使用的是插入排序和快速排序结合的排序算法。
数组长度不超过10时,使用插入排序。
长度超过10使用快速排序。
在数组较短时插入排序更有效率
function swap(arr, i, j) {
[arr[i], arr[j]] = [arr[j], arr[i]]
}
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
降序
const findKthLargest = function(nums, k) {
// 将数组逆序
const sorted = nums.sort((a,b)=> {
return b-a
})
# 取第k大的元素
return sorted[k-1]
};;
1 冒泡排序(稳定,O(n2))

- 就是从第一个元素开始,重复比较相邻的两个项,若第一项比第二项更大,则交换两者的位置;反之不动。
- 每一轮操作,都会将这一轮中最大的元素放置到数组的末尾。假如数组的长度是 n,那么当我们重复完 n 轮的时候,整个数组就有序了。
外层length次,内层length-i-1次
var sortArray = function (nums) {
for (let i = 0; i < nums.length; i++) {
for (let j = 0; j < nums.length - i -1; j++) {
if (nums[j] > nums[j + 1]) {
//swap(nums, j, j + 1);
[nums[j],nums[j+1]]=[nums[j+1],nums[j]];
}
}
}
return nums;
};
改进,加一个标志符,标志位可以帮助我们在第一次冒泡的时候就定位到数组是否完全有序,进而节省掉不必要的判断逻辑,将最好情况下的时间复杂度定向优化为 O(n)
var sortArray = function (nums) {
for (let i = 0; i < nums.length; i++) {
#1 区别在这里,我们加了一个标志位
let flag = false;
for (let j = 0; j < nums.length - i -1; j++) {
if (nums[j] > nums[j + 1]) {
#2 标志位
flag=true;
[nums[j],nums[j+1]]=[nums[j+1],nums[j]];
}
}
if(flag==false) return;
}
return nums;#3 若一次交换也没发生,则说明数组有序,直接放过
};
2 选择排序(不稳定,O(n2))

选择排序的关键字是“最小值”:循环遍历数组,每次都找出当前范围内的最小值,把它放在当前范围的头部;然后缩小排序范围,继续重复以上操作,直至数组完全有序为止。
- 先遍历1-n范围内最小的,和第一个位置的交换
- 再从2-n范围内最小的,和第二个交换
- 全部遍历完,就排好序了
var sortArray = function (nums) {
for (let i = 0; i < nums.length; i++) {
let minIndex = i;
// 已排序区间 [0, i) ,未排序区间 [i+1 , len)
# 遍历 i+1 之后的元素找到最小元素的索引
for (let j = i + 1; j < nums.length; j++) {
if (nums[j] < nums[min]) {
minIndex = j;
}
}
if(minIndex!=i)
[nums[i],nums[minIndex]]=[mums[minIndex],mums[i]];
}
return nums;
};
3 插入排序(稳定,O(n2))

插入排序的核心思想是“找到元素在它前面那个序列中的正确位置”
var sortArray = function (nums) {
// 从下标为1的元素开始选择合适的位置插入,因为下标为0的只有一个元素,默认是有序的
// 已排序区间 [0, i) ,未排序区间 [i , len)
// 将 nums[i] 插入到区间 [0, i) 使之成为有序数组
for (let i = 1; i < nums.length; i++) {
// 从右往左遍历
for (let j = i; j > 0 && nums[j] < nums[j - 1]; j--) {
// 只要nums[j]比前一个元素nums[j-1]小,就交换这两个元素
[nums[j],nums[j-1]]=[nums[j-1],nums[j]];
}
}
return nums;
};
4 归并排序(稳定,O(nlog(n)))

function mergeSort(arr) {
// 处理边界情况
if(arr.length <= 1) return arr
# 计算分割点
const mid = Math.floor(arr.length/ 2)
#1 递归分割左、右子数组,然后合并为有序数组
const leftArr = mergeSort(arr.slice(0, mid))
const rightArr = mergeSort(arr.slice(mid,arr.length))
#2 合并左右两个有序数组
arr = mergeArr(leftArr, rightArr)
return arr
}
# 这部分就是合并有序数组
function mergeArr(arr1, arr2) {
# 初始化两个指针,分别指向 arr1 和 arr2
let i = 0, j = 0
const res = []
# 合并两个子数组,哪个小,先添加哪个
while(i < arr1.length && j < arr2.length ) {
if(arr1[i] < arr2[j]) {
res.push(arr1[i])
i++
} else {
res.push(arr2[j])
j++
}
}
# 哪个还剩余,直接拼接剩余部分
if(i<len1) {
return res.concat(arr1.slice(i))
} else {
return res.concat(arr2.slice(j))
}
}
5 快速排序(不稳定,O(nlog(n)))

调用代码
var sortArray = function (nums) {
const N = nums.length;
quickSort(nums, 0, N - 1);
return nums;
};
快排
function quickSort(nums, left, right) {
if (right <= left) {
return;
}
let pIndex = partition(nums, left, right);
quickSort(nums, left, pIndex - 1);
quickSort(nums, pIndex + 1, right);
}
以基准值为轴心,划分左右子数组的过程
function partition(nums, left, right) {
let pivot = nums[left];
// 为两个数组分别定义一个指针
let i = left + 1;
let j = right;
while (true) {
while (i <= right && nums[i] <= pivot) {
i++;
}
while (j > left && nums[j] > pivot) {
j--;
}
if (i >= j) {
break;
}
swap(nums, i, j);
i++;
j--;
}
swap(nums, left, j);
return j;
}
6 堆排序(稳定,O(nlog(n)))
/** * 堆排序 * @param {*} nums * @returns */
function sortArray(nums) {
const N = nums.length;
// 建堆 找到第一个非叶子节点,向上遍历
for (let i = Math.floor(N / 2 - 1); i >= 0; i--) {
// 对 i位置节点 调整堆
heapify(nums, i, N);
}
// 排序过程 每一次循环都找出当前最大值(根节点),数组长度减一
for (let i = N - 1; i > 0; i--) {
// 根节点与最后一个节点交换位置(将此时最大元素移动到数组末尾)
swap(nums, 0, i);
// 对 此时的根节点 调整堆 最后的元素不用参与调整
heapify(nums, 0, i);
}
return nums;
}
/** * 对节点i进行 调整堆 * 满足:i节点以下的子堆是一个大顶堆 * 调整范围 [i, length) * @param {*} nums * @param {*} i * @param {*} length */
function heapify(nums, i, length) {
// 将i节点的值保存,这个过程就是给temp找到一个合适的位置
let temp = nums[i]
// j指向i的左孩子节点
let j = 2 * i + 1;
// 循环遍历[i, length)
while (j < length) {
if (j + 1 < length && nums[j] < nums[j + 1]) {
// 父节点有右孩子 并且 左孩子小于右孩子 将j指向右孩子
j++;
}
// 此时 j 指向 i 的孩子节点中较大的那个节点
if (temp < nums[j]) {
// 如果 父节点小于 j节点
// 交换i,j的元素
swap(nums, i, j);
// 将i和j都下移一位
i = j;
j = 2 * i + 1;
} else {
// 父节点 大于 孩子节点中最大的元素,就退出循环
break;
}
}
}
边栏推荐
- Redis入門完整教程:Pipeline
- Redis introduction complete tutorial: Collection details
- Header file duplicate definition problem solving "c1014 error“
- VIM editor knowledge summary
- 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先
- 推荐收藏:跨云数据仓库(data warehouse)环境搭建,这货特别干!
- 企业如何跨越数字化鸿沟?尽在云原生2.0
- ECS settings SSH key login
- Redis: redis message publishing and subscription (understand)
- QT drawing network topology diagram (connecting database, recursive function, infinite drawing, dragging nodes)
猜你喜欢

Redis:Redis的事务
![[Jianzhi offer] 6-10 questions](/img/73/5974068008bcdc9a70b3f5f57f1eb0.png)
[Jianzhi offer] 6-10 questions

phpcms付费阅读功能支付宝支付

qt绘制网络拓补图(连接数据库,递归函数,无限绘制,可拖动节点)

Install the gold warehouse database of NPC

Excel 快捷键-随时补充

The small program vant tab component solves the problem of too much text and incomplete display

Redis入门完整教程:Bitmaps

Redis入门完整教程:HyperLogLog

智力考验看成语猜古诗句微信小程序源码
随机推荐
Advantages of Alibaba cloud international CDN
Redis:Redis的事务
Redis introduction complete tutorial: detailed explanation of ordered collection
[Taichi] change pbf2d (position based fluid simulation) of Taiji to pbf3d with minimal modification
[roommate learned to use Bi report data processing in the time of King glory in one game]
How can enterprises cross the digital divide? In cloud native 2.0
Sword finger offer 68 - I. nearest common ancestor of binary search tree
剑指Offer 68 - II. 二叉树的最近公共祖先
【ODX Studio编辑PDX】-0.2-如何对比Compare两个PDX/ODX文件
The difference between cout/cerr/clog
ETCD数据库源码分析——处理Entry记录简要流程
【爬虫】数据提取之JSONpath
Redis入门完整教程:Redis Shell
MariaDB的Galera集群-双主双活安装设置
Redis getting started complete tutorial: Key Management
Notepad++--编辑的技巧
VIM editor knowledge summary
Basic knowledge of database
Redis introduction complete tutorial: client communication protocol
剑指 Offer 68 - I. 二叉搜索树的最近公共祖先