目录
add( (open([6]),open([5])),open([1,87]))
add( ([1,5,6,87]),([2,7,16,24,37])),进行最后一次add操作,得到最终结果[1,2,5,6,7,16,24,37,87]
①思想:在数组中取一个参照值(第0位)然后将他与后面的数值相比较,创建两个数组;比他小的放到左面数组,比他大的放到右面数组
1.排序:
一:冒泡排序:
时间复杂度
①内层i:第一个数与后面的数相比较,将大的数交换到最后面。一共比较-1-j次
-1:内层循环两两比较,比较次数为长度-1次;
-j:内层循环后无需拿此次最大数与后j个数重复比较;因为上一层已经判断他们为最大数;
②外层j:每次把最大的放到最后面,一共放了i次;最后一次不用放,因为剩余的最后一个数肯定是最小的。
外层-1与外层没-1的区别:
<script>
let a = [9, 3, 4, 5, 7, 8, 6, 2, 1];//length = 9
for (let j = 0; j < a.length - 1; j++) { //-1是因为当另外八个数排好后剩余的数肯定是最小的,无需再比较
for (let i = 0; i < a.length - 1 - j; i++) {//内层:将最大的数排到最后面
//取前一个数和后一个数两两相比较,一共比较了8次所以-1
//外层第二次循环,内层后两个数不用再比较。第三次,后三个数,第四次后四个数,每层应该少比较i次所以j < a.length - 1 - i
if (a[i] > a[i + 1]) {
[a[i],a[i+1]] = [a[i+1],a[i]]
}
}
}
console.log(a)
</script>
二:选择排序:
时间复杂度
①找到数组中的最小值,选中它并将其放在第一位
②找到数组中第2小的值,放在第2位
③以此类推,执行n-1轮
<script>
let a = [6,5,9,87,2,2,0]
let y; //位置
for(let j = 0 ;j<a.length-1;j++){
y = j //0
for(let i = j+1; i<a.length;i++){
y = a[y]>a[i]?i:y
}
let x = a[y]
a.splice(y,1)
a.splice(j,0,x)
}
console.log(a)
</script>
三:插入排序
时间复杂度
循环比较,把数字向前按顺序插入他应该在的大小位置上
<body>
[6,5,1,87,2]
i = 0 以6为基准,如果a(1) < a(0),两数交换位置 → [5,6 1 87 2]
[5,6 1 87 2] i= 1 如果a[2] < a[1] ,换位置 → [5,1,6 87 2]
内层循环,再向前循环比较1次(i次),
如果a[1]< a [0]
符合交换条件 → [1,5,6 87 2]
[1,5,6 87 2] i = 2 如果a[3] < a[2] ,交换位置, 不符合条件不交换, i++
[1,5,6 87 2] i = 3 如果a[4] < a[3] ,交换位置 → [1,5,6,2,87]
内层循环,再向前循环比较3次,
如果a[3]< a[2] ,交换位置 → [1,5,2,6,87]
如果a[2] < a[1] ,交换位置 → [1,2,5,6,87]
如果a[1] < a[0] ,交换位置,
不满足 循环结束 输出 [1,2,5,6,87]
<script>
let a = [6,5,1,87,2];
for(let i = 0; i < a.length; i++){
for(let j = i ; j >= 0 ;j--){
if(a[j]>a[j+1]){
[a[j],a[j+1]] = [a[j+1],a[j]]
}
}
}
console.log(a)
</script>
</body>
四:归并排序(递归):
时间复杂度
<script>
let a = [6,5,1,87,2,16,37,24,7]; //9
function open(arr){
if(arr.length === 1){
return arr
}else{
let mid = parseInt(arr.length/2) //4
let left = arr.slice(0,mid)
let right = arr.slice(mid,a.length)
return add( open(left) , open(right) )
}
}
function add(a,b){
let res = []
while(a.length>0&&b.length>0){
if(a[0]>b[0]){
res.push(b.shift())
}else{
res.push(a.shift())
}
}
return res.concat(a,b)
}
console.log(open(a))
</script>
①分:先把数组[6,5,1,87,2,16,37,24,7]分成两半left [6,5,1,87]和 right [2,16,37,24,7],再递归的对子数组进行“分”的操作,直到分成一个个单独的数。比如对左面的[6,5,1,87]分成[6,5]和[1,87]此时再进行合的操作就是
add( (open([6]),open([5])),open([1,87]))
外层左 拆成的 内层左和内层有右 ,外层右
②合:然后去 add方法中 先带入 外层左中的内层左和右进行比较,比较成功后return给外层左的res是[5,6] , 此时是:
add( ([5,6]),open([1,87]))
然后在对把外层右进行open并进行内层1和87之间的add,比较成功后给外层右的res是[1,87] ,此时是:
add( ([5,6]),([1,87]))
进行add后得到(1,5,6,87,) 此时最大的左外层比较完毕。同样方法比较最大的右外层,得到(2,7,16,24,37),此时是:
add( ([1,5,6,87]),([2,7,16,24,37])),进行最后一次add操作,得到最终结果[1,2,5,6,7,16,24,37,87]
五:快速排序(递归):
时间复杂度
①思想:在数组中取一个参照值(第0位)然后将他与后面的数值相比较,创建两个数组;比他小的放到左面数组,比他大的放到右面数组
②代码
③优化
2.搜索
一:顺序搜索:
①遍历数组
②找到跟目标值相等的元素,就返回他的下标
③遍历结束后,如果没有搜索到就返回-1
let a = [6,5,1,87,2]
let x = 1
function order(a){
for(let i = 0 ;i < a.length ;i++){
if(a[i] === x){
return i
}
}
return -1
}
console.log(order(a,x))
二:二分搜索(前提必须是有序数组,无重复元素):
①从数组的中间元素开始,如果中间元素正好是目标值,则搜索结束。
②如果目标值大于或者小于中间元素,则在大于或小于中间元素的那一半数组中搜索
创建一个可变动的搜索范围low为第0位,high为a.length-1位。
let a = [6,5,1,87,2]
a.sort() //[1, 2, 5, 6, 87]
let x = 6
function fn(){
let low = 0 //0
let high = a.length-1 //4
while(low <= high){
let mid = Math.floor((low+high)/2) //2
if(a[mid] < x ){
low = mid + 1 //3
}else if(a[mid] > x){
high = mid - 1
}else{
return a[mid]
}
}
return -1
}
console.log(fn(a))