js歸併排序算法的原理及簡單demo

最近看了一道「如何給阿里兩萬多名員工按照年齡排序」的面試題後,很想記錄下來本身的解題思路,下面:
綜合考慮到基數較大和穩定性,咱們採起歸併排序的算法;
歸併算法分爲兩個兩個靈魂步驟,即:拆分=>歸併;
咱們先把兩萬多名員工的基數縮小至六名員工的基數,他們的年齡數組未排序前爲[25,18,17,31,25,30],咱們實現第一個靈魂操做,拆分:
歸併算法的拆分思想是將一個數組一分爲二,而後將分出來的數組繼續一分爲二,直至出現單個數組的長度爲1,不可再分爲止; 面試

clipboard.png

如上圖,一個長度爲6的數組按照左右結構一直拆分至6個長度爲1的數組,拆分就完畢了,這時咱們由下往上回溯,將數組歸併,圖解:算法

clipboard.png

六個長度爲一的數組歸併以後又變成了一個長度爲6的數組,可是排序發生了改變,這就是歸併算法,下面是代碼實現:

咱們一步一步來,第一步先來實現拆分的部分:數組

// 拆分
            function mergeSort(arr){
                console.log(`arr=${arr}`)
                if(arr.length==1){//若是數組長度爲1則返回數組
                    return arr
                }
                var mid=Math.floor(arr.length/2);//將數組一拆分爲二
                var left=arr.slice(0,mid);
                var right=arr.slice(mid);
                 mergeSort(left);//若是數組長度不爲1,則繼續遞歸拆分,(由控制檯能夠看出遞歸會先將left執行完後再去執行right)
                 mergeSort(right)
            }
            console.log(mergeSort([25,18,17,31,25,30]))
控制檯打印出結果:

clipboard.png
這個時候咱們能夠看到,咱們已經採用遞歸的方式將數組拆分爲六個長度爲一的數組了,接下來走第二步的合併,合併的思想是左右兩個數組的第一個元素比較大小,而後將大的數(或者小的數)提取出來存放在一個第三方數組,直接上代碼:函數

// 合併
            function merge(left,right){
                var arr=new Array;//新建一個第三方數組
                    if(left[0]<=right[0]){//比較left的第一位和right的第一位誰小,小的提取出來push進第三方數組
                        arr.push(left.shift())
                    }else{
                        arr.push(right.shift())
                    }    
                return arr.concat(left).concat(right)//將提取出來的數組和原數組歸併成一個數組
            };
            console.log(merge([25],[30]))//代碼到這一步只是展現了合併的原理和思路,並不完整,咱們不急,先用簡單的單元素數組進行排序合併,這也是合併的第一層合併

clipboard.png

控制檯打印出[25,30],說明咱們的歸併和排序都是成功的,下面咱們將升級兩個函數,使其可以正式地操做複雜的歸併排序:spa

// 合併
            function merge(left,right){
                var arr=new Array;//新建一個第三方數組
                while(left.length>0&&right.length>0){////比較left的第一位和right的第一位誰小,小的提取出來push進第三方數組
                    if(left[0]<=right[0]){
                        arr.push(left.shift())
                    }else{
                        arr.push(right.shift())
                    }
                };
                return arr.concat(left).concat(right)//將提取出來的數組和原數組歸併成一個數組
            };
            // 拆分
            function mergeSort(arr){
                console.log(`arr=${arr}`)
                if(arr.length==1){//若是數組長度爲1則返回數組
                    return arr
                };
                var mid=Math.floor(arr.length/2);//將數組一拆分爲二
                var left=arr.slice(0,mid);
                var right=arr.slice(mid);
                return merge(mergeSort(left),mergeSort(right))
            };
            console.log(mergeSort([25,18,17,31,25,30]))

控住臺打印:
clipboard.png
至此,咱們的歸併排序成功!
歡迎各位大小神同行予以指正和探討code

相關文章
相關標籤/搜索