选择排序
选择排序的原理:每次挑出最小的那个数字,放在第一位,然后在比较剩余的数字
//伪代码(使用递归)
let sort = (numbers) => {
if(numbers.length > 2){
numbers.splice(minIndex,1)
return minNumbers + sort(numbers)
}else{
return sort2(numbers)
}
}
// 辅助函数
let sort2 = (numbers) => {
return numbers[0] > numbers[1] ? numbers.reverse() : numbers
}
let min = (numbers) =>
numbers.length > 2 ? min(
[numbers[0],min(numbers.slice(1))]
) : Math.min.apply(null,numbers)
let index = (numbers) => numbers.indexOf(min(numbers))
//代码
let sort = (numbers) => {
if(numbers.length > 2){
console.log('----')
let minIndex = index(numbers)
let minNumbers = min(numbers)
console.log(`minIndex : ${minIndex}`)
console.log(`minNumbers : ${minNumbers}`)
numbers.splice(minIndex,1)
return [minNumbers].concat(sort(numbers))
}else{
return sort2(numbers)
}
}
//(不使用递归)
let sort = (numbers) => {
for(let i = 0; i < numbers.length - 1; i++){
let minIndex = index(numbers.slice(i)) + i
if (minIndex !== i){
swap(numbers,minIndex,i)
}
}
return numbers
}
//辅助代码、
let min = (numbers) =>
numbers.length > 2 ? min(
[numbers[0],min(numbers.slice(1))]
) : Math.min.apply(null,numbers)
let index = (numbers) => numbers.indexOf(min(numbers))
let swap = (numbers,a,b)=>{
let temp = numbers[a]
numbers[a] = numbers[b]
numbers[b] = temp
}
let swap = (numbers,a,b) => {
[numbers[a],numbers[b]] = [numbers[b],numbers[a]]
}
快速排序
原理:选择一个基准,比基准小的,排在左边,比基准大的排在右边,重复length-1次 快速排序需要使用splice取pivot,因为splice会改变原数组,删去pivot,否则会重复获取pivot,导致爆栈。
//伪代码
let quickSort = numbers =>
numbers[i] < pivot ? numbers[i] + left : numbers[i] + right
quicksort(left) + pivot + quickSort(right)
//辅助函数
let pivotIndex = numbers =>
Math.floor(numbers.length/2)
let pivot = numbers =>
numbers.splice(pivotIndex(numbers),1)[0]
//代码
let quickSort = numbers =>{
if (numbers.length <= 1){return numbers}
let left = []
let right = []
let pivotNumbers = pivot(numbers)
for (let i = 0; i < numbers.length; i++){
if (numbers[i] < pivotNumbers){
left.push(numbers[i])
}else{
right.push(numbers[i])
}
console.log(`----`)
console.log(`left: ${left}`)
console.log(`right: ${right}`)
console.log(`pivotNumbers : ${pivotNumbers}`)
console.log(`numbers : ${numbers}`)
}
return quickSort(left).concat([pivotNumbers],quickSort(right))
}
归并排序
原理:将数组完全拆分,在比较各个数组的大小
//伪代码
let mergeSort = (numbers) => {
merge(mergeSort(left),mergeSort(right))
}
let merge = (a,b) => {
if (a.length === 0){return b}
if (b.length === 0){return a}
if (a[0] > b[0]){return [b[0]].concat(merge(a,b.slice[1]))
}
if (a[0] < b[0]){
return [a[0]].concat(merge(a.slice(1),b))
}
}
//代码
let mergeSort = (numbers) => {
let k = numbers.length
if (k === 1){return numbers}
let left = numbers.slice(0,Math.floor(k/2))
let right = numbers.slice(Math.floor(k/2))
return merge(mergeSort(left),mergeSort(right))
}
let merge = (a,b) => {
if (a.length === 0){return b}
if (b.length === 0){return a}
if (a[0] > b[0]){return [b[0]].concat(merge(a,b.slice(1)))
}else{
return [a[0]].concat(merge(a.slice(1),b))
}
}
计数排序
原理: 利用哈希表,遍历数组,使其变为哈希表,在遍历哈希表,从小到大排序
//伪代码
let countSort = (numbers) => {
if (! i in hashTable){
hashTable[numbers[i]] = 1
}else{
hashTable[numbers[i]] += 1
}
let max = max.numbers[i]
for (let i = 0; i <= max; i++){
if (i in hashTable){
result.push(i) + countNumber i
}
}
return result
}
let countSort = numbers => {
let result = []
let hashTable = {}
let max = 0
for (let i = 0; i < numbers.length; i++){
if (! (numbers[i] in hashTable)){
hashTable[numbers[i]] = 1
}else{
hashTable[numbers[i]] += 1
}
console.log(`----`)
console.log(`hashTable : ${Object.entries(hashTable)}`)
if(numbers[i] > max) {max = numbers[i]}
console.log(`max : ${max}`)
}
for(let j = 0; j <= max; j++){
// 因为j=0 所以 无法排序负数
if(j in hashTable){
for(let k = 0 ; k < hashTable[j]; k++){
result.push(j)
console.log(`j:${j}`)
}
}
}
return result
}
时间复杂度
- 选择排序 : O(n**2)
- 快速排序 : O(n log2 n)
- 归并排序 : O(n log2 n)
- 计数排序 : O(n + max)