归并排序

来源:互联网 发布:中国货币供给量数据 编辑:程序博客网 时间:2024/06/08 04:21

排序算法之归并排序

归并排序算法是用分治策略实现对n个元素进行排序的算法。
其基本思想是:将待排序元素分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终将排好序的子集合合并成所要求的排好序的集合。
1、Java代码实现

import java.util.Random;public class MergeSort {        //覆盖mergeSort方法,p的值为0,r的值为数组长度减1        public static void mergeSort(int[] a){            int len = a.length - 1;            mergeSort(a,0,len);        }    //递归实现归并排序        public static void mergeSort(int[] a,int p, int r)        {            if(p < r){                int q = (p+r)/2;                mergeSort(a,p,q);                mergeSort(a,q+1,r);                merge(a,p,q,r);            }        }        public static void merge(int[] a, int p, int q, int r)        {            final int MAX = 10000;            //MAX是哨兵的值,设为大于排序数组任何值的数值            int n1 = q-p+1;            int n2 = r-q;            //加1是因为要加入哨兵,从而不需要判断数组是否已空            int[] R = new int[n2+1];            for(int i=0; i < n1; i++)            {                L[i] = a[p+i];            }            for(int j=0; j<n2; j++){                R[j] = a[q+j+1];            }            L[n1] = MAX;            R[n2] = MAX;            int i =0,j =0;            for(int k =p; k <r+1; k++){                if(L[i] <= R[j]){                    a[k] = L[i];                    i++;                }                else{                    a[k] = R[j];                    j++;                }                                   }        }        public static void main(String[] args){               Random rand = new Random(47);               int num = 20;               int[] a = new int[num];               System.out.println("排序前");               for(int i = 0; i < num; i++){                 a[i] = rand.nextInt(100);                 System.out.print(a[i] + " ");                }               System.out.println();               mergeSort(a);               System.out.println("排序后:");               for(int j : a)                   System.out.print(j + " ");        }}

2、 c++代码实现
2.1 递归实现,与java实现的思路一致。

#include<iostream>using namespace std;#define MAXMUM  10000;template<class Type>void MergeSort(Type a[], int left, int right){    if (left < right){        int mid = (left + right) / 2;        MergeSort(a, left, mid);        MergeSort(a, mid + 1, right);        Merge(a, left, mid, right);    }}template<class Type>void Merge(Type a[], int left, int mid, int right){    int n1 = mid - left + 1;    int n2 = right - mid;    int *L = new int[n1 + 1];    int *R = new int[n2 + 1];    int i, j, k;    for (i = 0; i < n1; i++){        L[i] = a[left + i];    }    for (j = 0; j < n2; j++){        R[j] = a[mid + j + 1];    }    L[n1] = MAXMUM;    R[n2] = MAXMUM;    for (i = 0, j = 0, k = left; k <= right; k++){        if (L[i] <= R[j]){            a[k] = L[i];            i++;        }        else{            a[k] = R[j];            j++;        }    }    delete[] L;    delete[] R;}int main(){    cout << "Before Sort:";    int num = 100;    int *arr= new int[num];    for (int i = 0; i < num; i++){        arr[i] = rand()%100;        cout << arr[i] << " " ;    }    cout << endl;    MergeSort(arr, 0, num - 1);    cout << "After Sort:";    for (int i = 0; i < num; i++){        cout << arr[i] << " " ;    }    cout << endl;    system("pause");    return 0;}

2.2 非递归实现

从分治策略入手,可以消除算法中的递归。算法MergeSort的递归过程只是将待排序集合一分为二,直至待排序集合只剩下一个元素为止,然后不断合并两个排好序的数组段。按此机制,可以首先将数组a中相邻元素两两配对。用合并算法将它们 排序,构成n/2 的排好序的子数组段,然后再将它们排序成长度为4的排好序的子数组段,如此继续下去,直至整个数组排好序。

 #include<iostream>using namespace std;//消去递归的合并排序算法template<class Type>void MergeSort(Type a[], int n){    Type *b = new Type[n];    int s = 1;    while (s < n){        MergePass(a, b, s, n);//合并到数组b        s += s;        MergePass(b, a, s, n);//合并到数组a        s += s;    }}//用于合并排好序的相邻数组段template<class Type>void MergePass(Type x[], Type y[], int s, int n){    //合并大小为s的相邻子数组    int i = 0;    while (i <= n - 2 * s){        //合并大小为s的相邻2段子数组        Merge(x, y, i, i + s - 1, i + 2 * s - 1);        i = i + 2 * s;    }    //剩下的元素个数少于2s    if (i + s < n) Merge(x, y, i, i + s - 1, n - 1);    else for (int j = i; j <= n - 1; j++)y[j] = x[j];}template<class Type>void Merge(Type c[], Type d[], int l, int m, int r){    //合并c[l:m]和c[m+1,r]到d[l+r]    int i = l;    int j = m + 1;    int k = l;    while ((i <= m) && (j<=r))    if (c[i] <= c[j]) d[k++] = c[i++];    else d[k++] = c[j++];    if (i > m) for (int q = j; q <= r; q++) d[k++] = c[q];    else for (int q = i; q <= m; q++) d[k++] = c[q];}int main(){    cout << "Before Sort:";    const int num = 100;    int  arr[num];    for (int i = 0; i < num; i++){        arr[i] = rand() % 100;        cout << arr[i] << " ";    }    cout << endl;    MergeSort(arr, num);    cout << "After Sort:";    for (int i = 0; i < num; i++){        cout << arr[i] << " ";    }    cout << endl;    delete[] arr;    system("pause");    return 0;}

3、 python语言的递归实现

#coding:utf-8import randomdef merge_sort(array):    length = len(array)    if length <= 1:return array    m = length/2    left = array[:m]    right = array[m:]    left = merge_sort(left)    right = merge_sort(right)    return merge(left, right)def merge(left, right):    result = []    while len(left)>0 and len(right)>0:        if left[0] <= right[0]:            result.append(left.pop(0))        else:            result.append(right.pop(0))    result.extend(left)    result.extend(right)    return resultif __name__ == '__main__':    num = 100    arr = []    for i in range(num):        arr.append(random.randint(0,100))    print "BeforeSort: ",arr    print "AfterSort: ",merge_sort(arr)
0 0