JavaScript演算法 ,Python演算法,Go演算法,java演算法,系列之【歸併排序】篇

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

常見的內部排序演算法有:插入排序、希爾排序、選擇排序、冒泡排序、歸併排序、快速排序、堆排序、基數排序等。用一張圖概括:

 

 

 

歸併排序(英語:Merge sort,或mergesort),是建立在歸併操作上的一種有效排序演算法,效率為O(n log n)。1945年由約翰·馮·諾伊曼首次提出。該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用,且各層分治遞迴可以同時進行。

 

 

作為一種典型的分而治之思想的演算法應用,歸併排序的實現由兩種方法:

自上而下的遞迴(所有遞迴的方法都可以用迭代重寫,所以就有了第 2 種方法);
自下而上的迭代;
在《資料結構與演算法 JavaScript 描述》中,作者給出了自下而上的迭代方法。但是對於遞迴法,作者卻認為:
However, it is not possible to do so in JavaScript, as the recursion goes too deep for the language to handle.
然而,在 JavaScript 中這種方式不太可行,因為這個演算法的遞迴深度對它來講太深了。
說實話,我不太理解這句話。意思是 JavaScript 編譯器記憶體太小,遞迴太深容易造成記憶體溢出嗎?還望有大神能夠指教。
和選擇排序一樣,歸併排序的效能不受輸入資料的影響,但表現比選擇排序好的多,因為始終都是 O(nlogn) 的時間複雜度。代價是需要額外的記憶體空間。

  1. 演算法步驟

  2. 申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合并後的序列;

  3. 設定兩個指標,最初位置分別為兩個已經排序序列的起始位置;

  4. 比較兩個指標所指向的元素,選擇相對小的元素放入到合并空間,並移動指標到下一位置;

  5. 重複步驟 3 直到某一指標達到序列尾;

  6. 將另一序列剩下的所有元素直接複製到定序序列尾。

  7. 動圖示範

 

 

1、JavaScript 代碼實現

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

function mergeSort(arr) {  

    var len = arr.length;

    if(len < 2) {

        return arr;

    }

    var middle = Math.floor(len / 2),

        left = arr.slice(0, middle),

        right = arr.slice(middle);

    return merge(mergeSort(left), mergeSort(right));

}

 

function merge(left, right){

    var result = [];

 

    while (left.length && right.length) {

        if (left[0] <= right[0]) {

            result.push(left.shift());

        else {

            result.push(right.shift());

        }

    }

 

    while (left.length)

        result.push(left.shift());

 

    while (right.length)

        result.push(right.shift());

 

    return result;

}

 

2、Python 代碼實現

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

def mergeSort(arr):

    import math

    if(len(arr)<2):

        return arr

    middle = math.floor(len(arr)/2)

    left, right = arr[0:middle], arr[middle:]

    return merge(mergeSort(left), mergeSort(right))

 

def merge(left,right):

    result = []

    while left and right:

        if left[0] <= right[0]:

            result.append(left.pop(0));

        else:

            result.append(right.pop(0));

    while left:

        result.append(left.pop(0));

    while right:

        result.append(right.pop(0));

    return result

 

3、Go 代碼實現

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

func mergeSort(arr []int) []int {

        length := len(arr)

        if length < 2 {

                return arr

        }

        middle := length / 2

        left := arr[0:middle]

        right := arr[middle:]

        return merge(mergeSort(left), mergeSort(right))

}

 

func merge(left []int, right []int) []int {

        var result []int

        for len(left) != 0 && len(right) != 0 {

                if left[0] <= right[0] {

                        result = append(result, left[0])

                        left = left[1:]

                else {

                        result = append(result, right[0])

                        right = right[1:]

                }

        }

 

        for len(left) != 0 {

                result = append(result, left[0])

                left = left[1:]

        }

 

        for len(right) != 0 {

                result = append(result, right[0])

                right = right[1:]

        }

 

        return result

}

 

4、Java 實現

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

 public static int[] sort(int[] nums, int low, int high) {

        int mid = (low + high) / 2;

        if (low < high) {

         

            sort(nums, low, mid);

        

            sort(nums, mid + 1, high);

 

            merge(nums, low, mid, high);

        }

        return nums;

    }

 

    /**

     * 將數組中low到high位置的數進行排序

     * nums 待排序數組

     * low 待排的開始位置

     *  mid 待排中間位置

     *  high 待排結束位置

     */

    public static void merge(int[] nums, int low, int mid, int high) {

        int[] temp = new int[high - low + 1];

        int i = low;

        int j = mid + 1;

        int k = 0;

 

        while (i <= mid && j <= high) {

            if (nums[i] < nums[j]) {

                temp[k++] = nums[i++];

            else {

                temp[k++] = nums[j++];

            }

        }

 

        while (i <= mid) {

            temp[k++] = nums[i++];

        }

 

        while (j <= high) {

            temp[k++] = nums[j++];

        }

 

       

        for (int k2 = 0; k2 < temp.length; k2++) {

            nums[k2 + low] = temp[k2];

        }

    }

 

 

登入樂搏學院官網http://www.learnbo.com/

或關注我們的官方微博,還有更多驚喜哦~

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.