排序算法的稳定性(即,两个相同的数在排序前和排序后前后位置相同)堆排序、快速排序、希尔排序、直接选择排序是不稳定的排序算法,而冒泡排序、直接插入排序、折半插入排序、归并排序是稳定的排序算法。
- 直接插入排序比较次数为n*(n-1)/2,最欢情况下交换次数为3*(n-1),3为数值互换时的来回倒。
- 数组中第 k 个最大元素(冒泡排序)
//冒泡、选择都可以
function maopao(array3,bignum){
let temp
let len = array3.length
for(let i =0;i<bignum;i++){
for (let j=0;j<len-i-1;j++){
if(array3[j]>array3[j+1]){
temp=array3[j]
array3[j]=array3[j+1]
array3[j+1]=temp
}
}
}
console.log(array3)
return array3[len-bignum]
}
let array3=[1,5,7,6,2,4,1,2]
//第几大要小于数组长度
let bignum=3
console.log(maopao(array3,bignum))
- 直接插入排序
function quicksort(arr){
for(let i=1;i<arr.length;i++){
//保存最后一个位置的数字
let currentnum=arr[i]
//不断进行移动的元素下标从当前元素前一个开始
let j=i-1
//此处只有两条件都符合才进行循环
while(j>=0 && arr[j]>currentnum){
arr[j+1]=arr[j]
j--
}
//只有进入过循环才有变动
if(j!=i-1){
//最后一次的j已经是正当位置的前一位,所以需要+1
arr[j+1]=currentnum
}
}
return arr
}
let arr=[1,8,7,3,4,5,9]
console.log(quicksort(arr))
- 快速排序
function quicksort(arr){
if(arr.length<=1){
return arr
}
let mid = Math.floor(arr.length/2)-1
let num = arr[mid] //选取中间数字为标准,选第一个也可
arr.splice(mid,1) //换份本次的左右两边数字
let left=[],right=[]
for(let i=0;i<arr.length;i++){
if(arr[i]<num){
left.push(arr[i])
}else{
right.push(arr[i])
}
}
return quicksort(left).concat([num],quicksort(right))
}
let arr=[9,8,7,5,4,9,6,2,8,4,6]
console.log(quicksort(arr))
- 归并排序(先分别对两边进行排序,在将两边进行merge【左边大,push左边,左边坐标+1,右边左边不变,反之亦然】,递归进行)
//归并排序
function merge(left,right){
//赋值要赋完全,都给赋值
let i=0,j=0
let arrall=[]
//需要两组下标都小于长度才push,谁都有可能没有push完
while(i<left.length && j<right.length){
if(left[i]<right[j]){
arrall.push(left[i])
i++
}else{
arrall.push(right[j])
j++
}
}
if(i<left.length){
//arrall.push(...left.slice(i))
//或
//concat:不会操作原数组,所以需要将返回值赋给变量!!!!
arrall = arrall.concat(left.slice(i))
}else{
arrall.push(...right.slice(j))
}
return arrall
}
function mergesort(arr){
if(arr.length<2){
return arr
}
let mid = Math.floor(arr.length/2)
let left = mergesort(arr.slice(0,mid))
let right = mergesort(arr.slice(mid))
return merge(left,right)
}
let arrmerge=[1,8,7,3,4,5,9]
console.log(mergesort(arrmerge))
- 堆排序 click
//堆排序
//小组中交换
function areasort(array,index){
let left = 2*index+1
let right = 2*index+2
//左右孩子较大数字下标
let big=left
if(array[right]){
if(array[right]>array[left]){
big=right
}
}
//js中两位置数字交换方式 [a[i],a[j]] = [a[i],a[j]]
if(array[index]<array[big]){
[array[index],array[big]] = [array[big],array[index]]
}
}
function duisort(array,len){
let result=[]
//共进行len-1次大排序
for(let i =len-1;i>0;i--){
let j = Math.floor(len/2-1)
//每次大排序选出一个最大值
while(j>=0){
//小排序:堆当前组(至少两个元素,由j的计算方式保证)进行排序
areasort(array,j)
j--
}
//每次迭代结束最大值的位置为:array[0]
result.push(array[0])
//将第一个值与最后一个值进行交换,以便下次进行排序的数字不包括最后一个数字
[array[0],array[i]] =[array[i],array[0]]
//最后一个数字已经最大,不需要再进行排序
array=array.slice(0,i)
}
return result
}
//debugger
let arraydui = [1,2,3,8,8,5,6,5,9,1,4,6]
console.log(duisort(arraydui,arraydui.length))
- 二分查找2:查找指定元素的第一个和最后一个位置,给定一个按照升序排列的整数数组nums,和一个目标值target,找出给定目标值在数组中的开始位置和结束位置
function devisionfind(array1,low,high,num){
//debugger
let mid = Math.floor((low+high)/2) //js中数学计算结果该是多少就是多少,没有隐形数据类型转换
if(array1[mid] == num){
return mid
}else if(num>array1[mid] && low <=high){
return devisionfind(array1,mid+1,high,num) //每次都要return!!!,只算不返回怎么会有结果
}else if(num<array1[mid] &&low <=high){
return devisionfind(array1,low,mid-1,num) //每次都要return!!!
}else{
return 'not find' //没有选择的选择在最后一个else中
}
}
let array1 = [1,5,6,7,8,15,25,64,99]
let num = 100
console.log(devisionfind(array1,0,array1.length,num))