一、简介
基本思想:归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
最坏时间复杂度:O( NlogN )
最好时间复杂度:O( NlogN )
平均时间复杂度:O( NlogN )
二、归并排序操作
合并操作:取两个输入数组 A 和 B ( 两数组已排序 ),一个输出数组 C ,以及3个计数器 Actr , Bctr , Cctr , 它们初始置于对应数组的开始端。A[ Actr ] 和 B[ Bctr ] 中的较小者被复制到 C 中的下一个位置,相关的计数器向前推进一步。当两个输入表有一个用完的时候,则将另一个表中剩余部分复制到 C 中 。
代码:
/**
* @description: 治 合并数组
* @param {type} a 要排序数组 tmpArray 放置归并结果的数组
* leftPos 前半部分起始元素的下标 rightPos 后半部分起始元素的下标
* rightEnd 后半部分末尾元素的下标
* @return: null
*/
template < typename Comparable >
void merge( std::vector<Comparable> & a, std::vector<Comparable> & tmpArray,
int leftPos, int rightPos, int rightEnd )
{
int leftEnd = rightPos - 1;
int tmpPos = leftPos;
int numElements = rightEnd - leftPos + 1;
// 主循环
while( leftPos <= leftEnd && rightPos <= rightEnd )
if( a[ leftPos ] <= a[ rightPos ] )
tmpArray[ tmpPos++ ] = std::move( a[ leftPos++ ] );
else
tmpArray[ tmpPos++ ] = std::move( a[ rightPos++ ] );
// 复制前半部分的剩余元素
while( leftPos <= leftEnd )
tmpArray[ tmpPos++ ] = a[ leftPos++ ];
while( rightPos <= rightEnd )
tmpArray[ tmpPos++ ] = a[ rightPos++ ];
// 将tmpArray复制回原数组a
for( int i = 0; i < numElements; ++i, --rightEnd )
a[ rightEnd ] = std::move( tmpArray[ rightEnd ] );
}
递归操作:递归地将前半部分数据和后半部分数据各自归并排序,得到排序后的两部分数组,然后使用上面的合并算法再将这两部分合并到一起。
代码:
/**
* @description: 分
* @param {type} a 要排序数组 tmpArray 放置归并结果的数组
* left 子数组最左边元素的下标 right 子数组最右边元素的下标
* @return: null
*/
template < typename Comparable >
void mergeSort( std::vector<Comparable> & a, std::vector<Comparable> & tmpArray,
int left, int right )
{
if( left < right )
{
int center = ( left + right ) / 2;
mergeSort( a, tmpArray, left, center );
mergeSort( a, tmpArray, center + 1, right );
merge( a, tmpArray, left, center + 1, right );
}
}
/**
* @description: 归并排序
* @param {type} a 要排序数组
* @return: null
*/
template < typename Comparable >
void mergeSort( std::vector<Comparable> & a )
{
std::vector< Comparable > tmpArray( a.size( ) );
mergeSort( a, tmpArray, 0, a.size( ) - 1 );
}
三、代码实现
/*
* @Author: lsyy
* @Date: 2020-02-24 10:41:45
* @LastEditTime: 2020-02-24 16:53:18
* @LastEditors: Please set LastEditors
* @Description: 归并排序
* @FilePath: \merge sort\Src\main.cpp
*/
#include <iostream>
#include <string>
#include <functional>
#include <queue>
#include <vector>
/**
* @description: 治 合并数组
* @param {type} a 要排序数组 tmpArray 放置归并结果的数组
* leftPos 前半部分起始元素的下标 rightPos 后半部分起始元素的下标
* rightEnd 后半部分末尾元素的下标
* @return: null
*/
template < typename Comparable >
void merge( std::vector<Comparable> & a, std::vector<Comparable> & tmpArray,
int leftPos, int rightPos, int rightEnd )
{
int leftEnd = rightPos - 1;
int tmpPos = leftPos;
int numElements = rightEnd - leftPos + 1;
// 主循环
while( leftPos <= leftEnd && rightPos <= rightEnd )
if( a[ leftPos ] <= a[ rightPos ] )
tmpArray[ tmpPos++ ] = std::move( a[ leftPos++ ] );
else
tmpArray[ tmpPos++ ] = std::move( a[ rightPos++ ] );
// 复制前半部分的剩余元素
while( leftPos <= leftEnd )
tmpArray[ tmpPos++ ] = a[ leftPos++ ];
while( rightPos <= rightEnd )
tmpArray[ tmpPos++ ] = a[ rightPos++ ];
// 将tmpArray复制回原数组a
for( int i = 0; i < numElements; ++i, --rightEnd )
a[ rightEnd ] = std::move( tmpArray[ rightEnd ] );
}
/**
* @description: 分
* @param {type} a 要排序数组 tmpArray 放置归并结果的数组
* left 子数组最左边元素的下标 right 子数组最右边元素的下标
* @return: null
*/
template < typename Comparable >
void mergeSort( std::vector<Comparable> & a, std::vector<Comparable> & tmpArray,
int left, int right )
{
if( left < right )
{
int center = ( left + right ) / 2;
mergeSort( a, tmpArray, left, center );
mergeSort( a, tmpArray, center + 1, right );
merge( a, tmpArray, left, center + 1, right );
}
}
/**
* @description: 归并排序
* @param {type} a 要排序数组
* @return: null
*/
template < typename Comparable >
void mergeSort( std::vector<Comparable> & a )
{
std::vector< Comparable > tmpArray( a.size( ) );
mergeSort( a, tmpArray, 0, a.size( ) - 1 );
}
int main( )
{
int a[] = {1,8,7,5,90,8,4,2,7,6};
std::vector<int> iv(a,a+sizeof(a)/sizeof(int));
mergeSort( iv );
return 0;
}