现在的位置: 首页 > 综合 > 正文

排序算法复习(2)——合并排序

2013年09月01日 ⁄ 综合 ⁄ 共 2534字 ⁄ 字号 评论关闭

合并排序的重点就是怎么原地(in-place)合并已排序的两个子序列。

 

关于合并子函数:

(1)写了两个,一个是原地合并;

函数void inplace_merge(/*in-out*/int* a,/*in*/int low,/*in*/int q,/*in*/int high)

(2)一个是非原地合并。

详见函数int merge(/*in*/int* a,/*in*/int n,\
          /*in*/int* b,/*in*/int m,\
          /*in-out*/int* c,/*in*/int k)


原地合并的思想就是:

(1)另外创建两个数组,并把已经排好序的两部分分别拷贝进去;

(2)然后就循环的把两个子序列两面的元素比较,选小的元素赋值给数组a;


循环比较又分三种:

(1)子序列left,right都还没有遍历完,那就比较left和right的值大小,拷贝小的值入a;

(2)子序列left已经遍历完了,right都还没有遍历完;直接拷贝right的值到a

(3)子序列right已经遍历完了,left都还没有遍历完;直接拷贝left的值到a

思路清晰了就可以写了。

 

另外

STL里面就有两个算法是将合并已经排序的子序列的:

猛击:merge
 和
inplace_merge

#include <iostream>

#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <vector>
#include <algorithm>


using namespace std;



//int a[N]; n = N
//
void print(/*in*/int* a,/*in*/int n)
{
    assert( a != NULL && n > 0);
    for(int i = 0; i < n; ++i)
    {
        printf("%2d    ",a[i]);
    }
    printf("\n");
}


//sort two sorted list
//
//a[0..n),b[0..m),c[0..k)
int merge(/*in*/int* a,/*in*/int n,\
          /*in*/int* b,/*in*/int m,\
          /*in-out*/int* c,/*in*/int k)
{
    int index_a = 0;
    int index_b = 0;
    int index_c = 0;
    for( ; index_c < k ; ++index_c)
    {
        //
        if( index_a < n && index_b < m )
        {
            if( a[index_a] >= b[index_b] )
            {
                c[index_c] = b[index_b];
                ++index_b;
            }
            else
            {
                c[index_c] = a[index_a];
                ++index_a;
            }
        }
        else if ( index_a >= n && index_b < m)
        {
            c[index_c] = b[index_b];
            ++index_b;
        }
        else if ( index_a < n && index_b >= m )
        {
            c[index_c] = a[index_a];
            ++index_a;
        }
    }//for
}


//a[low..q],a[q+1..r]
//
void inplace_merge(/*in-out*/int* a,/*in*/int low,/*in*/int q,/*in*/int high)
{
    int left_array_size = q - low + 1;//[low,q]
    int left[left_array_size];
    int tmp;
    int i;
    for(tmp = 0,i = low; i <= q; ++i)
    {
        left[tmp++] = a[i];
    }
    //print(left,q-low+1);


    int right_array_size = high - q;//[q+1,high]
    int right[right_array_size];
    for(tmp = 0,i = q + 1; i <= high; ++i)
    {
        right[tmp++] = a[i];
    }
    //print(right,high-q);


    int left_index = 0;
    int right_index = 0;
    int a_index = 0;
    for( a_index = low; a_index <= high ; ++a_index)
    {
        if ( left_index < left_array_size && right_index < right_array_size )
        {
            if ( left[left_index] >= right[right_index])
            {
                a[a_index] = right[right_index];
                right_index++;
            }
            else
            {
                a[a_index] = left[left_index];
                left_index++;
            }
        }
        else if (left_index >= left_array_size && right_index < right_array_size)
        {
            a[a_index] = right[right_index];
            right_index++;
        }
        else if(left_index < left_array_size && right_index >= right_array_size)
        {
            a[a_index] = left[left_index];
            left_index++;
        }
    }


}


//a[low..high]
//if we have an array ,int a[100];
//then call merge_sort(a,0,99),NOT merge_sort(a,0,100)
//
void merge_sort(/*in-out*/int* a,/*in*/int low,/*in*/int high)
{
    if ( low >= high )
        return;
    int q = (low + high)/2;
    merge_sort(a,low,q);
    merge_sort(a,q+1,high);
    inplace_merge(a,low,q,high);
}


int main()
{
    int a[] = {99,-99,63,72,10,24,888,10,89,56,40,17,68};
    const int ARRAY_SIZE = sizeof(a)/sizeof(*a);
    merge_sort(a,0,ARRAY_SIZE-1 );
    print(a,ARRAY_SIZE);
    cout << endl;


    return 0;
}

【上篇】
【下篇】

抱歉!评论已关闭.