幾種基本的排序演算法總結
阿新 • • 發佈:2018-12-18
準備函式
var arr = []
function swap(arr, a, b) { //交換函式
var temp = arr[a]
arr[a] = arr[b]
arr[b] = temp
}
function random_arr (){ //生成隨機陣列的函式
let long = Math.floor(Math.random()*100+1)
for(var x = 0; x < long; x++) {
arr.push(Math.floor(Math.random()*100))
}
console.log(arr)
}
random_arr ()
氣泡排序
演算法思路:
遍歷陣列, 將相鄰兩個數之間兩輛比較, 如果前面的數比後面的數大, 就交換位置, 然後繼續將這個數跟後面相鄰的數比較如果前面的數比後面的數小, 就用下一個數跟後面相鄰的數繼續比較
function bubble(arr) {
for(var i = arr.length-1; i >= 0; i--) {
for(var j = 0; j <= i; j++) {
if(arr[j] > arr[j+1]) {
swap(arr, j, j+1)
}
}
}
console.log(arr)
}
bubble (arr)
選擇排序
演算法思路:
將第一個數與後面的沒一個數進行比較, 如果有存在比第一個數小的數, 則交換位置, 然後用這個較小數繼續之前的位置向後比較, 經過一圈遍歷後, 陣列第一位的數就是跟個數組的最小值, 然後在用第二個數跟後面的所有數一次比較進行上述操作
function chose(arr) {
for(var i = 0; i<arr.length; i++) {
for(var j = i+1; j<arr.length; j++) {
if(arr[i] > arr[j]) {
swap(arr, i, j)
}
}
}
console.log(arr)
}
chose(arr)
插入排序
演算法思路:
遍歷整個陣列, 將遍歷項與其之前的項從後往前做比較, 如果他前面的數大於遍歷項, 則交換位置, 直到他前面的數小於遍歷項為止
function fuck_sort(arr) {
for(var i = 1; i < arr.length; i++) {
for (var j = i; j > 0; j--) {
if(arr[j]<arr[j-1]) {
swap(arr, j, j-1)
}
}
}
console.log(arr)
}
fuck_sort(arr)
歸併排序
演算法思路:
將一個數組, 對半分割, 遞迴執行, 直到被分割後的陣列只剩下一個數, 然後利用外排的方式將分割好的陣列進行排序然後複寫到原陣列中
function guibing(arr,low,height) {
var mid = low+Math.floor((height-low)/2)
if(low === height) {
return
}
guibing(arr, low, mid)
guibing(arr, mid+1, height)
sort(arr, low, height, mid)
}
function sort(arr, low, height, mid) {
var temp = []
var p1 = low
var p2 = mid+1
while (true){
if (arr[p1] >= arr[p2]) {
temp.push(arr[p2++])
}else {
temp.push(arr[p1++])
}
if(p1 > mid) {
for(var j = p2; j <= height; j++) {
temp.push(arr[j])
}
break
}
if(p2 > height) {
for(var j = p1; j < mid+1; j++) {
temp.push(arr[j])
}
break
}
}
for(var i = 0; i <= temp.length-1; i++) {
arr[i+low] = temp[i]
}
}
guibing(arr, 0, arr.length-1)
console.log(arr)
或者
function guibing2(arr) {
if(arr.length === 1) {
return arr
}
var mid = Math.floor(arr.length/2)
var left = arr.slice(0,mid) //slice()是陣列擷取方法
var right = arr.slice(mid, arr.length)
return sort2(guibing2(left), guibing2(right))
}
function sort2(left, right) {
var temp = []
while(left.length > 0 && right.length > 0) {
if(left[0] <= right[0]) {
temp.push(left.shift())
}else {
temp.push(right.shift())
}
}
return temp.concat(left).concat(right) //concat()是陣列拼接方法
}
console.log(guibing2(arr))
快速排序
演算法思路:
在陣列中隨便找一個數做基準數, 將比這個基準數大的數放到這個數的右側, 將比這個基準數小的數, 放到這個數的左側, 然後在基準數的小於區和大於區繼續遞迴執行上述操作
function range(arr, l, r) {
var less = l - 1
var more = r
while( l < more ) {
if(arr[l] > arr[r]) {
swap(arr, l, --more)
}else if(arr[l] < arr[r]) {
swap(arr, l++, ++less)
}else {
l++
}
}
swap(arr, r, more)
return [less+1,more]
}
function quick(arr, l, r) {
if(l < r) {
var scale = range(arr, l, r)
quick(arr, l, scale[0]-1)
quick(arr, scale[1]+1, r)
}
}
quick(arr, 0, arr.length-1)
console.log(arr)
或者
function quick2(arr) {
if(arr.length === 0 ) {
return []
}
var left = []
var right = []
var middle = []
var index =Math.round(Math.random()*(arr.length-1))
for(var i = 0; i<arr.length; i++) {
if(arr[i] < arr[index]) {
left.push(arr[i])
}else if(arr[i] > arr[index]) {
right.push(arr[i])
}else {
middle.push(arr[i])
}
}
return quick2(left).concat(middle).concat(quick2(right))
}
console.log(quick2(arr))
堆排序
演算法思路:
因為堆的結構就是一個完全二叉樹, 所以我們可以把陣列的結構也想象成一個完全二叉樹, 首先將陣列變成一個大根堆, 然後將陣列的第一位與陣列的最後一位進行交換, 將陣列的遍歷範圍減少一位, 此時陣列的最後一位就是最大值了, 然後再將二叉樹的頭節點, 跟其左右兩孩子最大的那個作比較, 如果孩子節點大於父節點, 就交換位置, 然後利用原來的那個父節點繼續跟左右孩子作比較,比較結束後, 又形成了一個大根堆, 繼續將二叉樹的頭結點跟二叉樹的倒數第二位作交換, 將陣列的遍歷範圍再減少一位, 重複執行上述操作.
function dui_sort(arr) {
dui(arr)
var long = arr.length
swap(arr, 0, --long)
while(long > 0) {
var j = 0
var left = j*2+1
while(left<long) {
largest = left+1<long && arr[left+1] >arr[left] ? left+1 : left
largest = arr[largest] > arr[j] ? largest : j
if(largest === j) {
break
}
swap(arr, largest, j)
j = largest
left = j*2+1
}
swap(arr, 0, --long)
}
}
function dui(arr) {
for(var i = 0; i < arr.length; i++) {
var j = i
while (arr[j] > arr[Math.floor((j-1)/2)]) {
swap(arr, j, Math.floor((j-1)/2))
j = Math.floor((j-1)/2)
}
}
}
dui_sort(arr)
console.log(arr)