JavaScript
递归二分法排序(快速排序)
思想:
1. 将数组的length除以2取整的值作为中间值,左右分别放置两个数组
2. 对于数组中的数据,小于该中间值的数据放左边的数组中, 大于该中间值的数据放右边的数组中
3. 逐层递进
4. 归
步骤1
步骤2
步骤3: ‘递’
步骤4: ‘归’
/*递归二分法排序(快速排序)
1. 准备一个函数,接收一个数组
2. 准备递归
=> 先找停的条件
-> 只要数组的 length <= 1,就停下来,直接返回原数组
=> 停以外的行为
-> 找到一个数组长度一半的取整
-> 从数组里把这个数据拆出来
-> 准备两个新数组,一个表示左边,一个表示右边
-> 循环遍历被拆除一个数字的数组
-> 判断大小,选择一个数组放进去
*/
var arr = [8, 4, 3, 2, 6, 7, 1, 5, 9];
// 1. 准备一个函数
function quickSort(arr){
// arr 就是要排序的数组
// 2-1. 递归停的条件
if(arr.length <= 1){
return arr;
}
// 2-2. 不到停的时候
var centerIndex = parseInt(arr.length / 2);
var center = arr.splice(centerIndex, 1)[0]; // 获取[0]位置上的数字6 而不是数组[6]
// 准备两个数组
var left = []; // 小
var right = []; // 大
// 循环遍历 arr
for(var i = 0; i < arr.length; i++){
// 判断大小,决定放在哪个数组里面
if(arr[i] < center){
left.push(arr[i]);
}else{
right.push(arr[i]);
}
}
// 向里面递归
// concat 不改变原始数组
return quickSort(left).concat(center, quickSort(right));
}
var res = quickSort(arr);
console.log(res);
console.log(arr);
插入排序
可以类比打牌
简单版如下:
/*
插入排序
1. 从 1 开始循环原始数组
=> 因为第一个数字不用比
2. 把当前这个数字复制一份
=> 为了覆盖以后还能有这个数字
3. 留下一个从哪里开始比的索引
=> 开始比较的索引就是当前索引的前一个
4. 向前比较
=> 遇到比我小的,就停下
=> 如果前一个比我大,就用前一个把我覆盖掉
*/
var arr = [8, 4, 3, 2, 6, 7, 1, 5, 9];
// 1. 从 [1] 开始遍历数组
for(var i = 1; i < arr.length; i++){
var tmp = arr[i];
var j = i - 1;
while(arr[j] > tmp){
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = tmp;
}
console.log(arr);
数组去重
去除数组中重复的数据
/*
方案1
1. 循环遍历数组
=> 从 [0] 开始,拿到每一个
=> 向后面去比较,只要后面还有一个和我一样的
=> 把我删除掉
*/
// 1. 准备一个数组
var arr = [1, 2, 3, 5, 6, 4, 3, 2, 1, 1, 2, 3, 4, 5];
// 方案1:
for(var i = 0; i < arr.length; i++){
// 第一个数字开始比较,向后比较
for(var j = i + 1; j < arr.length; j++){
if(arr[i] === arr[j]){
arr.splice(j, 1);
j--; // 删除一个后使索引-1, 不然后面的索引会往前移
}
}
}
console.log(arr);
var arr = [1, 2, 3, 5, 6, 4, 3, 2, 1, 1, 2, 3, 4, 5];
/*
方案2
1. 准备一个新的数组
2. 循环遍历数组
=> 一个一个地向新数组里面添加
=> 只要新数组没有这个数据,那么就加进去
=> 如果新数组里面有这个数据,就算了
*/
// 1. 准备一个新的数组
var newArr = [];
// 2. 遍历原始数组
for(var i = 0; i < arr.length; i++){
// 查看原始数组里面有没有 arr[i] 这个数据
// if(newArr.indexOf(arr[i]) === -1){
// 表示 newArr 里面没有这个数据
if(!newArr.includes(arr[i])){
// 能执行 if 条件,说明!newArr.includes(arr[i]) 是 true
// newArr.includes(arr[i])是 false
// 放进去
newArr.push(arr[i]);
}
}
console.log(newArr);
/*
方案3
+ 对象
-> obj.name = 'xxx';
-> 对象成员名不重名
1. 准备一个空对象
2. 循环遍历数组,把每一个成员当成对象的key来使用
-> 值填充什么无所谓
3. 循环遍历对象,把每个 key 添加到新数组里
*/
// 1. 准备一个空对象
var obj = {};
// 2. 循环遍历数组
for(var i = 0; i < arr.length; i++){
//把数组里面的每一个值当成 obj 的 key 来添加成员
obj[arr[i]] = '值不重要';
}
// 3. 准备一个新数组
var newArr = [];
for(var key in obj){
// key 就是对象里的每一个数据
// key 一定是字符串类型
newArr.push(key - 0);
}
console.log(obj);
console.log(newArr);
练习
/*
逻辑:
1.判断一下这个数字
1-1. 如果我的这个数字小于等于数组的第一个数字,直接unshift()
1-2. 如果我这个数字大于等于数组的最后一个数字,直接push()
2. 判断数组是空的,直接push()
3. 循环遍历数组,找一个合适的位置插入
=> 找到合适的位置
=> 比较,大于前一个数字,并且小于后一个数字,放在前一个的后面(后一个的前面)
-> 大于和小于不合适
-> 换成 >= 和 <,如果这样使用,需要 break
-> 换成 > 和 <=,这样使用可以不加 break
思考:
+ 按照现在的代码思考
+ 有没有一个情况能满足两个 if 条件
=> 有
+ 当出现这个情况以后,会不会插入两次
=> 不会
+ 如果我的数组是空的,会不会报错
=> 不会
=> 如果是空的,到下面的循环也不执行
=> 这个数字插入不进去
+ 判断数组为空的位置,需不需要return
=> 需要 return
小技巧:
+ insert 函数不需要返回值,只是对数组进行操作
+ return 后面有没有内容无所谓
+ 如果 if 条件后面只有一句话,并且需要 return
+ 可以直接写一行
+ 写成 return 你要执行的这句话
*/
var arr = [1, 20, 33, 44, 67, 89, 100];
function insert(arr, num){
// 1. 判断一下数字
// 1-1. 小于等于数组的第一个
// if(num <= arr[0]){
// arr.unshift(num);
// return;
// }
if(num <= arr[0]) return arr.unshift(num);
// 1-2. 大于等于数组的最后一个
if(num >= arr[arr.length - 1]){
arr.push(num);
return;
}
// 2. 判断数组为空
if(!arr.length){
arr.push(num);
return;
}
// 3. 数组遍历
// console.log('循环遍历');
for(var i = 0; i < arr.length; i++){
if(num > arr[i] && num <= arr[i + 1]){
// 放在后一个的前面
// splice 方法,从哪里截取,从哪里插入
// 把后面的数字向后顺延,把插入的数字放进去
arr.splice(i + 1, 0, num);
break;
}
}
}
insert(arr, 20)
console.log(arr);
/*
>= 和 < 死循环
循环第一次 i === 0
num >= arr[0] && num < arr[1];
20 >= 1 && 20 < 20
循环第二次 i === 1
num >= arr[1] && num < arr[2]
20 >= 20 && 20 < 33
把 33 向后顺延一个, 20 插进去
[1, 20, 20, 33, 44, 67, 89, 100]
循环第三次 i === 2
num >= arr[2] && num < arr[3]
20 >= 20 && 20 < 33
[1, 20, 20, 20, 33, 44, 67, 89, 100]
死循环
> 和 <= 死循环
循环第一次 i === 0
num > arr[0] && num <= arr[1];
20 > 1 && 20 <= 20
把 33 向后顺延一个, 20 插进去
[1, 20, 20, 33, 44, 67, 89, 100]
循环第二次 i === 1
num > arr[1] && num <= arr[2]
20 > 20 && 20 <= 20
继续循环
但是因为插入以后,后面的循环已经没必要了
最好还是加一个 break
*/