归并排序是排序算法中相对稍微复杂一些的排序算法,其时间复杂度为nlogn,空间复杂度为n,稳定性属于比较稳定的排序算法,其排序的思想采用的是分治法,比如说有一组数据,取出中间的索引值,然后进行递归的分割,最后分割完成的数据块,元素只有一个或者两个,两个元素进行相互比较,然后将这些块元素进行合并。
举个简单的案例,一组数据为2,1,3,5,4,进行第一次分割,分成两块左侧为2,1,3,右侧为5,4,然后继续怼左侧分割,分割后左侧为2,1后侧为3,这个时候进行比较下,将2,1调换位置变成1,2,然后右侧只有3所以不需要修改,这个时候将左侧的12和3合并变成1,2,3一个新的数组,最外层的右侧为5,4,然后进行比较需要调换位置修改为4,5,这时候经过以上操作后,为两块左侧为1,2,3右侧为4,5,然后再将其合并为1,2,3,4,5,具体合并的过程我们可以借助一个新的数组长度为n的空间,然后通过索引下标的移动想数组中拷贝,具体的细节可以通过代码查看,归并排序需要注意边界值的处理,否则会影响排序结果。
void Merge(int m_nBuffer[],int m_nLeft_,int m_nRight_,int m_nResult[])
{
if ( 1 == m_nRight_ - m_nLeft_) //证明两个元素需要比较调换位置
{
if (m_nBuffer[m_nLeft_] > m_nBuffer[m_nRight_])
{
int Temp = m_nBuffer[m_nLeft_];
m_nBuffer[m_nLeft_] = m_nBuffer[m_nRight_];
m_nBuffer[m_nRight_] = Temp;
}
return;
}
else if (0 == m_nRight_ -m_nLeft_) //证明只要一个元素 直接返回
{
return;
}
else //有多个元素 需要进行拆分
{
Merge(m_nBuffer,m_nLeft_,(m_nRight_ - m_nLeft_)/2 +m_nLeft_,m_nResult);
Merge(m_nBuffer,(m_nRight_ - m_nLeft_)/2 +m_nLeft_+1,m_nRight_,m_nResult);
MergeSort(m_nBuffer,m_nLeft_,m_nRight_,m_nResult);
for (int i = 0; i <= m_nRight_;i++)
{
m_nBuffer[i] = m_nResult[i];
}
}
}
下面是合并的代码
void MergeSort(int m_nBuffer[],int m_nLeft_,int m_nRight_,int m_nResult[])
{
//左侧的长度 确保左侧长度>1
int LeftLen = (m_nRight_ - m_nLeft_)/2 +1;
int LeftIndex = m_nLeft_;
int RightIndex = LeftIndex +LeftLen;
int ResIndex = m_nLeft_;
// 这里的边界值要处理好 右侧索引已经减过1了 所以要加上 或者改成<=
while(LeftIndex < m_nLeft_ + LeftLen && RightIndex < m_nRight_ +1)
{
if (m_nBuffer[LeftIndex] <= m_nBuffer[RightIndex])
{
m_nResult[ResIndex++] = m_nBuffer[LeftIndex++];
}
else
{
m_nResult[ResIndex++] = m_nBuffer[RightIndex++];
}
}
//同上面一样 继续比较没有合并剩下的数据
while(LeftIndex < m_nLeft_ + LeftLen)
{
m_nResult[ResIndex++] = m_nBuffer[LeftIndex++];
}
while(RightIndex < m_nRight_ +1 )
{
m_nResult[ResIndex++] = m_nBuffer[RightIndex++];
}
}