排序4-归并排序

来源:互联网 发布:金薇内衣淘宝是真的吗 编辑:程序博客网 时间:2024/05/21 11:17

基本思想

归并排序(Merge Sort)完全遵循上述分治法三个步骤:
1、分解:将要排序的n个元素的序列分解成两个具有n/2个元素的子序列;
2、解决:使用归并排序分别递归地排序两个子序列;
3、合并:合并两个已排序的子序列,产生原问题的解。
所以说归并排序一种分治算法的典型应用。
归并排序过程动态演示
这里写图片描述 这里写图片描述

时间和空间复杂度

时间复杂度是O(NlogN),空间复制度为O(N)(归并排序的最大缺陷)。归并排序在数据量比较大的时候也有较为出色的表现(效率上),但是,其空间复杂度O(n)使得在数据量特别大的时候(例如,1千万数据)几乎不可接受。而且,考虑到有的机器内存本身就比较小。总结来说,归并排序是一种占用内存,但却效率高且稳定的算法。

代码实现

void merge_array(int arr[], int tmp[], int Left, int mid, int Right){    assert(arr && Left >= 0 && Left <= mid && mid <= Right);    int i = Left;    int j = mid + 1;    int index = 0;    while(i <= mid && j <= Right)    {        if(arr[i] <= arr[j])            tmp[index++] = arr[i++];        else            tmp[index++] = arr[j++];    }    while(i <= mid) //拷贝剩下的左半部分        tmp[index++] = arr[i++];    while(j <= Right)  //拷贝剩下的右半部分        tmp[index++] = arr[j++];    memcpy(arr + Left, tmp, (Right - Left + 1) * sizeof(int)); }void merge_sort(int arr[], int tmp[], int Left, int Right){    assert(arr && Left >= 0);    int mid;    if(Left < Right)    {        mid = (Left + Right) / 2;        merge_sort(arr, tmp, Left, mid);        merge_sort(arr, tmp, mid + 1, Right);        merge_array(arr, tmp, Left, mid, Right);    }}void Merge_Sort(int arr[], int len){    assert(arr && len);    int *tmp_arr;    //tmp_arr = (int *)malloc(len * sizeof(int));    tmp_arr = new int[len];    merge_sort(arr, tmp_arr, 0, len - 1);    delete[] tmp_arr;}

测试程序

#include <iostream>#include <cstring>#include <ctime>#include <cmath>using namespace std;#define ArraySize 100000void swap(int *x, int *y){    int temp;    temp = *x;    *x   = *y;    *y   = temp;}void Bubble_sort(int arr[], int len){    for(int i = 0; i < len; i ++)    {        for(int j = i + 1; j < len; j ++)            if(arr[i] > arr[j])                swap(arr[i], arr[j]);    }}void Bubble_sort1(int arr[], int len){    for(int i = 0; i < len; i ++)    {        for(int j = len - 1; j >= i; j --)        {            if(arr[i] > arr[j])                swap(arr[i], arr[j]);        }    }}void Bubble_sort2(int arr[], int len){    bool flag = true;    while(flag)    {        flag = false;        for(int i = 0; i < len; i ++)            for(int j = len - 1; j >= i; j --)                if(arr[i] > arr[j])                    swap(arr[i], arr[j]);    }}void Slect_sort(int arr[], int len){    for(int i = 0; i < len; i ++)    {        int min_index = i ;        for(int j = i + 1; j < len; j ++)        {            if(arr[min_index] > arr[j])                min_index = j;        }        if(i != min_index)            swap(arr[i],arr[min_index]);    }}void Insert_sort(int arr[], int len){    for(int i= 1; i < len; i ++)    {           int key = arr[i];        int j = i;        while(j && arr[j - 1] > key)        {            arr[j] = arr[j - 1];            j --;        }        arr[j] = key;    }}void Shell_sort(int arr[], int len){    int increment = len / 2;    while(increment)    {        for(int i = increment; i < len; i ++)        {            int key = arr[i];            /*int j ;            for(j = i; j >= increment; j -= increment)            {                if(arr[j-increment] > key )                    arr[j] = arr[j-increment];                else                     break;            }*/            int j = i;            while(j >= increment && arr[j-increment] > key)            {                arr[j] = arr[j-increment];                j -= increment;            }            arr[j] = key;        }        increment /= 2;    }}void Shell_sort1(int arr[], int len){    int increment = 0;    for(increment = len/2; increment > 0; increment /=2)    {        for(int i = increment; i < len; i++)        {            int key = arr[i];            int j = 0;            for(j = i; j >= increment; j -=increment)            {                if(arr[j-increment] > key)                    arr[j] = arr[j-increment];                else                     break;            }            arr[j] = key;        }    }}void Shell_sort2(int arr[], int len){    int index = log( 2*len + 1) / log(3.0);    //cout << index << endl;    int increment = ( pow(3.0, index) - 1 ) / 2;    //cout << increment << endl;    while(increment)    {        for(int i = increment; i < len; i ++)        {            int key = arr[i];            /*int j ;            for(j = i; j >= increment; j -= increment)            {                if(arr[j-increment] > key )                    arr[j] = arr[j-increment];                else                     break;            }*/            int j = i;            while(j >= increment && arr[j-increment] > key)            {                arr[j] = arr[j-increment];                j -= increment;            }            arr[j] = key;        }        index -= 1;        increment = ( pow(3.0, index) - 1 ) / 2;    }}void Heap_adjust(int arr[], int index, int len){    while(true)    {        int iMax = index;        int iLeft = 2 * index + 1;        int iRight = 2 * index + 2;        if(iLeft < len && arr[index] < arr[iLeft])            iMax = iLeft;        if(iRight < len && arr[index] < arr[iRight])            iMax = iRight;        if(iMax != index)        {            swap(arr[index], arr[iMax]);            index = iMax;        }        else             break;    }}void Heap_adjust2(int arr[], int index, int len){    int iMax = index;    int iLeft = 2 * index + 1;    int iRight = 2 * index + 2;    if(iLeft < len && arr[index] < arr[iLeft])        iMax = iLeft;    if(iRight < len && arr[index] < arr[iRight])        iMax = iRight;    if(iMax != index)    {        swap(arr[index], arr[iMax]);        Heap_adjust2(arr, iMax, len);    }}void Build_maxheap(int arr[], int len){    for(int i = len / 2; i >= 0; i --)    {        Heap_adjust(arr, i , len);    }}void Heap_Sort(int arr[], int len){    Build_maxheap(arr, len);    for(int i = len - 1; i > 0; i --)    {        swap(arr[0], arr[i]);        Heap_adjust(arr, 0, i);    }}void Print_array(int arr[], int len){    for(int i = 0; i < len; i++)    {        cout << arr[i] << " ";    }    cout << endl;}void merge_array(int arr[], int tmp[], int Left, int mid, int Right){    assert(arr && Left >= 0 && Left <= mid && mid <= Right);    int i = Left;    int j = mid + 1;    int index = 0;    while(i <= mid && j <= Right)    {        if(arr[i] <= arr[j])            tmp[index++] = arr[i++];        else            tmp[index++] = arr[j++];    }    while(i <= mid)        tmp[index++] = arr[i++];    while(j <= Right)        tmp[index++] = arr[j++];    memcpy(arr + Left, tmp, (Right - Left + 1) * sizeof(int)); }void merge_sort(int arr[], int tmp[], int Left, int Right){    assert(arr && Left >= 0);    int mid;    if(Left < Right)    {        mid = (Left + Right) / 2;        merge_sort(arr, tmp, Left, mid);        merge_sort(arr, tmp, mid + 1, Right);        merge_array(arr, tmp, Left, mid, Right);    }}void Merge_Sort(int arr[], int len){    assert(arr && len);    int *tmp_arr;    //tmp_arr = (int *)malloc(len * sizeof(int));    tmp_arr = new int[len];    merge_sort(arr, tmp_arr, 0, len - 1);    delete[] tmp_arr;}int main(int argc, char const *argv[]){    /* code */    int Array[ArraySize];    int Array1[ArraySize];    int Array2[ArraySize];    time_t begin , end;    srand(time(NULL));    for(int i = 0; i < ArraySize; i ++)    {        Array[i] = rand()%ArraySize;        //cout << Array[i] << " ";    }    memcpy(Array1, Array, ArraySize * sizeof(Array1[0]));    memcpy(Array2, Array, ArraySize * sizeof(Array2[0]));//  Print_array(Array, ArraySize);/*  begin = clock();    Bubble_sort2(Array, ArraySize);    end = clock();    cout << "Bubble_sort runtime:   " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;    begin = clock();    Slect_sort(Array1, ArraySize);    end = clock();    cout << "Slect_sort runtime:   " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;    begin = clock();    Insert_sort(Array2, ArraySize);    end = clock();    cout << "Insert_sort runtime:   " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;*/     begin = clock();    Shell_sort2(Array, ArraySize);    end = clock();    cout << "Shell_sort2 runtime:   " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;    begin = clock();    Heap_Sort(Array1, ArraySize);    end = clock();    cout << "Heap_Sort runtime:   " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;    begin = clock();    Merge_Sort(Array2, ArraySize);    end = clock();    cout << "Merge_Sort runtime:   " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;    //Print_array(Array2, ArraySize);    return 0;}

运行结果如下:

Shell_sort2 runtime:   0.026sHeap_Sort runtime:   0.004sMerge_Sort runtime:   0.014s
0 0
原创粉丝点击