js數(shù)據(jù)結(jié)構(gòu)排序示例教程(全網(wǎng)精簡(jiǎn)版)
冒泡排序
function BubbleSort(){
const{length}=array
for(let i=0;i<length;i++)
{
for (let j=0;j<length-1-i;j++){
if(arr[j]>arr[j+1]){
swap(arr,j,j+1)
}
}
}
console.log(arry);
}
function swap(arry, a, b) {
const temp = arry[a]
arry[a] = arry[b]
arry[b] = temp
//或者用 [arry[b],arry[a]]=[arry[a],arry[b]]//es6中數(shù)組解構(gòu)
}
var arr= [1,2,3,4,5]
選擇排序
記錄并不斷更改索引值,找到最小的數(shù)后替換
假設(shè)數(shù)組為 [5, 3, 8, 4, 2]:
- 第一輪外部循環(huán)(
i = 0):- 內(nèi)部循環(huán)找到最小元素
2在索引4,交換后數(shù)組變?yōu)?nbsp;[2, 3, 8, 4, 5]。
- 內(nèi)部循環(huán)找到最小元素
- 第二輪外部循環(huán)(
i = 1):- 內(nèi)部循環(huán)找到最小元素
3在索引1(未移動(dòng)),數(shù)組保持不變。
- 內(nèi)部循環(huán)找到最小元素
- 第三輪外部循環(huán)(
i = 2):- 內(nèi)部循環(huán)找到最小元素
4在索引3,交換后數(shù)組變?yōu)?nbsp;[2, 3, 4, 8, 5]。
- 內(nèi)部循環(huán)找到最小元素
- 第四輪外部循環(huán)(
i = 3):- 內(nèi)部循環(huán)找到最小元素
5在索引4,交換后數(shù)組變?yōu)?nbsp;[2, 3, 4, 5, 8]。
- 內(nèi)部循環(huán)找到最小元素
排序完成,最終數(shù)組為 [2, 3, 4, 5, 8]。
插入排序
記錄索引對(duì)于元素的值,就是把大的數(shù)往后面覆蓋,最后肯定右兩個(gè)重復(fù)的大數(shù),直接把當(dāng)前的temp覆蓋到排在前面的大數(shù)就行
function insertSort(){
const {length}=arr
let temp
for(let i=1;i<length;i++){
temp=arr[i]
j=i
while(j>0&&arr[j-1]>temp){
arr[j]=arr[j-1]
j--
}
arr[j]=temp
}
console.log(arr);
}
insertSort=[5, 4, 3, 3, 1]
具體用實(shí)例說(shuō)明
第一輪循環(huán)(i = 1):
temp = arr[1] = 4j = 1- 比較
arr[j-1] (5)和temp (4),因?yàn)?nbsp;5 > 4,所以進(jìn)入 while 循環(huán)。 - 將
arr[j-1](5) 后移一位,數(shù)組變?yōu)?nbsp;[5, 5, 3, 3, 1] j--,現(xiàn)在j = 0- while 循環(huán)結(jié)束,因?yàn)?nbsp;
j = 0 - 將
temp (4)插入到arr[j],數(shù)組變?yōu)?nbsp;[4, 5, 3, 3, 1]
第二輪循環(huán)(i = 2):
temp = arr[2] = 3j = 2- 比較
arr[j-1] (5)和temp (3),因?yàn)?nbsp;5 > 3,所以進(jìn)入 while 循環(huán)。 - 將
arr[j-1](5) 后移一位,數(shù)組變?yōu)?nbsp;[4, 5, 5, 3, 1] j--,現(xiàn)在j = 1- 比較
arr[j-1] (4)和temp (3),因?yàn)?nbsp;4 > 3,所以繼續(xù) while 循環(huán)。 - 將
arr[j-1](4) 后移一位,數(shù)組變?yōu)?nbsp;[4, 4, 5, 3, 1] j--,現(xiàn)在j = 0- while 循環(huán)結(jié)束,因?yàn)?nbsp;
j = 0 - 將
temp (3)插入到arr[j],數(shù)組變?yōu)?nbsp;[3, 4, 5, 3, 1]
第三輪循環(huán)(i = 3):
temp = arr[3] = 3j = 3- 比較
arr[j-1] (5)和temp (3),因?yàn)?nbsp;5 > 3,所以進(jìn)入 while 循環(huán)。 - 將
arr[j-1](5) 后移一位,數(shù)組變?yōu)?nbsp;[3, 4, 5, 5, 1] j--,現(xiàn)在j = 2- 比較
arr[j-1] (4)和temp (3),因?yàn)?nbsp;4 > 3,所以繼續(xù) while 循環(huán)。 - 將
arr[j-1](4) 后移一位,數(shù)組變?yōu)?nbsp;[3, 4, 4, 5, 1] j--,現(xiàn)在j = 1- 比較
arr[j-1] (3)和temp (3),因?yàn)?nbsp;3 == 3,所以 while 循環(huán)結(jié)束。 - 將
temp (3)插入到arr[j],數(shù)組變?yōu)?nbsp;[3, 3, 4, 5, 1]
第四輪循環(huán)(i = 4):
temp = arr[4] = 1j = 4- 比較
arr[j-1] (5)和temp (1),因?yàn)?nbsp;5 > 1,所以進(jìn)入 while 循環(huán)。 - 將
arr[j-1](5) 后移一位,數(shù)組變?yōu)?nbsp;[3, 3, 4, 5, 5] j--,現(xiàn)在j = 3- 比較
arr[j-1] (4)和temp (1),因?yàn)?nbsp;4 > 1,所以繼續(xù) while 循環(huán)。 - 將
arr[j-1](4) 后移一位,數(shù)組變?yōu)?nbsp;[3, 3, 4, 4, 5] j--,現(xiàn)在j = 2- 比較
arr[j-1] (3)和temp (1),因?yàn)?nbsp;3 > 1,所以繼續(xù) while 循環(huán)。 - 將
arr[j-1](3) 后移一位,數(shù)組變?yōu)?nbsp;[3, 3, 3, 4, 5] j--,現(xiàn)在j = 1- 比較
arr[j-1] (3)和temp (1),因?yàn)?nbsp;3 > 1,所以繼續(xù) while 循環(huán)。 - 將
arr[j-1](3) 后移一位,數(shù)組變?yōu)?nbsp;[3, 3, 3, 4, 5] j--,現(xiàn)在j = 0- while 循環(huán)結(jié)束,因?yàn)?nbsp;
j = 0 - 將
temp (1)插入到arr[j],數(shù)組變?yōu)?nbsp;[1, 3, 3, 4, 5]
歸并排序
火狐瀏覽器的sort就是基于這種排序,chrome用到快速排序
function mergeSort(array){
if(array.length>1){
const {length}=array
const middle=Math.floor(length/2)
const left=mergeSort(array.slice(0,middle))
const right=mergeSort(array.slice(middle,length))
array=merge(left,right)
}
}
function merge(left,right){
let i=0;
let j=0;
const result=[]
while(i<left.length&&i<right.length){
result.push(left[i]<right[i]?left[i++]:right[i++])
}
result.concat(i<left.length?left.slice(i):right.slice(j))
}
mergeSort([5,4,3,2,1])
用具體例子解釋一下執(zhí)行過(guò)程
第一次調(diào)用 mergeSort:
- 數(shù)組長(zhǎng)度大于 1,繼續(xù)執(zhí)行。
middle是 2。left是[5, 4],right是[3, 2, 1]。- 遞歸調(diào)用
mergeSort對(duì)left和right進(jìn)行排序。
merge中執(zhí)行過(guò)程
第一輪比較:left[i] (4)與right[j] (1)比較,因?yàn)?nbsp;1 < 4,所以將1添加到result中。
第二輪比較:j增加 1,現(xiàn)在j = 1。left[i] (4)與right[j] (2)比較,因?yàn)?nbsp;2 < 4,所以將2添加到result中。
第三輪比較:j增加 1,現(xiàn)在j = 2。left[i] (4)與right[j] (3)比較,因?yàn)?nbsp;3 < 4,所以將3添加到result中。
第四輪比較:j增加 1,現(xiàn)在j = 3。left[i] (4)與right[j] (不存在)比較,因?yàn)?nbsp;right數(shù)組已經(jīng)沒(méi)有更多元素,所以將left數(shù)組剩余的元素[4, 5]添加到result中。
快速排序
以一個(gè)元素為基準(zhǔn)(可以是middle,0,length-1)把比它小的放一堆,比它大的放一堆,在以第一堆的元素中挑一個(gè)基準(zhǔn),比它大的挑一堆,比它小的調(diào)一堆,分到最后把這幾堆和一起。
function quickStore(){
const {length}=arr
if(length<2){
return arr
}
let base=arr[0]
let minArr=arr.slice(1).filter(item=>item>=base)
let maxArr=arr.slick(1).filter(item=>item<base)
return quickStore(minArr).contact(base).contact(quickStore(maxArrft))
}
計(jì)數(shù)排序
但是會(huì)占據(jù)空間
找到最大值
const maxValue = findMax(arr) // const maxValue = Math.max(...arr)
- 調(diào)用
findMax函數(shù)來(lái)找到數(shù)組中的最大值。 findMax函數(shù)遍歷數(shù)組,比較每個(gè)元素,找到最大值。
:初始化計(jì)數(shù)數(shù)組
const counts = new Array(maxValue + 1)
- 創(chuàng)建一個(gè)長(zhǎng)度為
maxValue + 1的數(shù)組counts,用于存儲(chǔ)每個(gè)元素的出現(xiàn)次數(shù)。 - 由于最大值是 9,所以
counts的長(zhǎng)度為 10。: 計(jì)數(shù)每個(gè)元素的出現(xiàn)次數(shù)
例如遍歷到數(shù)組中數(shù)字5出現(xiàn)2次,就把counts計(jì)數(shù)數(shù)組的下標(biāo)為5的位置計(jì)為1,再白能力一遍還有就++計(jì)為2。所以count數(shù)組中索引值為5的地方數(shù)值為2,意思是5出現(xiàn)了兩次。
arr.forEach(item => { if(!counts[item]){ counts[item] = 0 } counts[item]++ })構(gòu)建新的排序數(shù)組
let newarr = [] let sortIndex = 0 counts.forEach((item, index) => { while(item > 0){ newarr[sortIndex++] = index item-- } })- 初始化一個(gè)新的空數(shù)組
newarr。 - 遍歷
counts數(shù)組,根據(jù)計(jì)數(shù)構(gòu)建新的排序數(shù)組。 - 對(duì)于
counts中的每個(gè)非零元素,將其索引(即原數(shù)組中的元素值)添加到newarr中相應(yīng)次數(shù)。例如:遍歷到5前面數(shù)字都沒(méi)有出現(xiàn)就不會(huì)進(jìn)入while循環(huán),知道索引值index為5時(shí),就將newarr中sortIndex=0索引值為0的位置計(jì)為index5,sortIndex++變?yōu)?,迎接下一個(gè)元素,counts數(shù)組中索引值5的item減一也就是減少出現(xiàn)次數(shù)后再遍歷是否還出現(xiàn),如果還有就把count下標(biāo)1的位置再計(jì)為5.出現(xiàn)次數(shù)減一。 - 完整代碼
var arr=[5,7,5,4,9,1] function countSort(arr){ if(arr.length<2){ return arr } const maxValue=findMax(arr) // const maxValue=Math.max(...arr)也可以用js內(nèi)置方法 const counts=new Array(maxValue+1) arr.forEach(item => { if(!counts[item]){ counts[item]=0 } counts[item]++ }) let newarr=[] let sortIndex=0 counts.forEach((item,index)=>{ while(item>0){ newarr[sortIndex++]=index item-- } }) } countSort(arr) function findMax(arr){ let max=arr[0] for(let i=0;i<length;i++){ if(arr[i]>max){ maax=arr[i] } } return newarr }桶排序
- 數(shù)據(jù)稀疏桶會(huì)少,數(shù)據(jù)龐大桶多
function bucketSort(arr, bucketSize=3){ if(arr.length<2){ return arr } //創(chuàng)建幾個(gè)小桶 const buckets=createBucket(arr,buckdetSize) //小桶排序(插入算法)合并concat return sortBucket(buckets) } function createBucket(arr,buckdetSize){ //找最大值和最小值 let minValue=Math.min(...arr) let maxValue=Math.max(...arr) //桶數(shù)量 const bucetCount=Math.floor((maxValue-minValue)/ buckdetSize)+1//+1是為了如果最大值正好等于某個(gè)桶的邊界值, // 那么按照簡(jiǎn)單的除法計(jì)算,最大值可能會(huì)被分配到超出桶的范圍之外。 // //創(chuàng)建桶子 // const buckets = [] // for (let i = 0; i < bucketCount; i++) { // buckets[i] = [] // } // ES6 const buckets=[...Array(bucetCount)].map(()=>[]) //判斷每個(gè)元素應(yīng)該進(jìn)哪個(gè)桶子 for (let i = 0; i < arr.length; i++) { const index = Marh.floor((arr[i] - minValue) / bucketSize) buckets[index].push(arr[i]) } return buckets } function sortBucket(){ const sortArr=[] for(let i=0;i<arr.length;i++){ if(arr[i]){ insertSort(arr[i]) sortArr.push(...arr[i]) } } } function insertSort() { const { length } = arr let temp for (let i = 1; i < length; i++) { temp = arr[i] j = i while (j > 0 && arr[j - 1] > temp) { arr[j] = arr[j - 1] j-- } arr[j] = temp } console.log(arr); } bucketSort([5,4,3,2,6,1,7,10,9,8])缺點(diǎn)是如果最大數(shù)為100,中間會(huì)創(chuàng)造很多無(wú)效桶
基數(shù)排序
填補(bǔ)了計(jì)數(shù)排序和桶排序的缺點(diǎn)
給定桶子的數(shù)量。一般是10,將數(shù)組里的數(shù)字先按照個(gè)位排序,再按十位,再百位~
再掌握這個(gè)思想
//Math.floor(x/diveder)%base //divider*=base以35舉例:x是35,diveder事先定義為1,base為10
得到十位35/1=35%10=5,得到個(gè)位35/10=3%10=3
let maxVal=Math.max(...arr) while(divider<=maxVal){ //構(gòu)建二維數(shù)組 const buckets = [...Array(10)].map(() => []) for (let val of arr) { buckets[Math.floor(val / divider) % base].push(val) //把取得個(gè)位數(shù),十位數(shù)百位數(shù)推到bukets中 } arr = [].concat(...buckets) divider *= base }去最大值作為循環(huán)結(jié)束的條件
用array和map的方法創(chuàng)建10個(gè)空數(shù)組。遍歷arr中元素,用Math方法取出個(gè)十百位數(shù),推到buckets中,如:bucket[3]=3
arr = [].concat(...buckets) divider *= base表示將arr數(shù)組中所有個(gè)位數(shù)取出來(lái)排好后,用concat連成數(shù)組,再排新數(shù)組中每個(gè)元素的十位數(shù),divider*10后變成10.....
完整代碼
const arr=[35,2,26,2,5,8,34,1,56,99,33] function radixSort(arr){ const base=10 let divider=1 //Math.floor(x/diveder)%base//得到十位35/1=35%10=5,得到個(gè)位35/10=3%10=3 //divider*=base let maxVal=Math.max(...arr) while(divider<=maxVal){ //構(gòu)建二維數(shù)組 const buckets = [...Array(10)].map(() => []) for (let val of arr) { buckets[Math.floor(val / divider) % base].push(val)//把取得個(gè)位數(shù),十位數(shù)百位數(shù)推到bukets中 } arr = [].concat(...buckets) divider *= base } return arr }
總結(jié)
到此這篇關(guān)于js數(shù)據(jù)結(jié)構(gòu)排序的文章就介紹到這了,更多相關(guān)js數(shù)據(jù)結(jié)構(gòu)排序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript動(dòng)態(tài)生成樹形菜單的方法
這篇文章主要介紹了javascript動(dòng)態(tài)生成樹形菜單的方法,涉及JavaScript針對(duì)頁(yè)面元素與屬性的動(dòng)態(tài)操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
javascript Slip.js實(shí)現(xiàn)整屏滑動(dòng)的手機(jī)網(wǎng)頁(yè)
Slip.js能做什么?Slip.js可以讓你的手機(jī)網(wǎng)站像原生手機(jī)軟件一樣慣性滾動(dòng),手觸圖片輪換等等,對(duì)Slip.js感興趣的小伙伴們可以參考一下2015-11-11
Bootstrap編寫一個(gè)兼容主流瀏覽器的受眾巨幕式風(fēng)格頁(yè)面
這篇文章主要介紹了Bootstrap編寫一個(gè)兼容IE8、谷歌等主流瀏覽器的受眾巨幕式風(fēng)格頁(yè)面,感興趣的小伙伴們可以參考一下2016-07-07
JS 實(shí)現(xiàn) ajax 異步瀏覽器兼容問(wèn)題
本文通過(guò)實(shí)例代碼給大家講解了js實(shí)現(xiàn)ajax異步瀏覽器兼容問(wèn)題,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-01-01
JavaScript中使用Spread運(yùn)算符的八種方法總結(jié)
這篇文章主要給大家介紹了JavaScript中使用Spread運(yùn)算符的八種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用JavaScript具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
PPK 談 JavaScript 的 this 關(guān)鍵字 [翻譯]
在 JavaScript 中 this 是最強(qiáng)的關(guān)鍵字之一。這篇貼文就是要告訴你如何用好 this。2009-09-09

