合并排序
合并排序是应用分治技术的一个例子。
思想:
对一个需要排序的数组,合并排序将其一分为二。并对umeige字数组递归排序,然后把这两个牌号许的字数组合并为一个有序数组。
效率:
当n>1时。C(n)=2C(n/2)+Cmerge(n), C(1)=0
于是我们得到在最坏情况下C=nlogn-n+1;这种情况就是在进行合并的时候被分割出来的数组都不会为空,除非另一个数组只剩下最后一个元素。那么合并排序在最坏情况下的键值比较次数十分接近于任何基于比较排序算法在理论上能够达到的最少次数。
但是依旧是有缺点:他需要额外的空间,就是说不是在位的。但是它是一个稳定的算法。
过程:
比如我们有一个数组为8.3.2.9.7.1.5.4
首先将数组分为8,3,2,9 7,1,5,4,
然后继续分为8,3 2,9 7,1 5,4
分为 8 3 2 9 7 1 5 4
进行合并 3,8 2,9 1,7 4,5
继续合并 2,3,8,9 1,4,5 ,7
最后一个合并 1,2 ,3,4,5,7,8,9
代码:
template<class T>
void MergeSort<T>::MERGE_SORT(T *mergeSortArry,int start,int end)
{
//思想:将数组一分为二,对每个字数组进行排序。然后将这两个数组进行合并。
//end为最后一个元素在数组中的索引,对于这个数组来说为7,那么得到的是前面的5各元素放于第一个数组中
if(end>start)
{
int location=(end+start);
location=(end+start)/2;//获得要分开的位置,若是第一次就是前面的4个元素
MERGE_SORT(mergeSortArry,start,location);//将数组进行继续往下面的分割
MERGE_SORT(mergeSortArry,location+1,end);
MERGE(mergeSortArry,start,end);//对数组进行合并
}
}
template<class T>
void MergeSort<T>::MERGE(T *mergeSortArry,int start,int end)
{
T *tempArray=new T[end-start+1];
int i=start;//作为数组前面元素的索引
int k=0;//作为合并数组的索引
int midIndex=(end+start)/2;//中间的位置
int j=midIndex+1;//作为数组后半部分的索引
while(i<=midIndex&&j<=end)
{
while (*(mergeSortArry+i)<*(mergeSortArry+j)&&i<=midIndex)
{
*(tempArray+k)=*(mergeSortArry+i);
i++;
k++;
}
while(*(mergeSortArry+i)>*(mergeSortArry+j)&&j<=end)
{
*(tempArray+k)=*(mergeSortArry+j);
j++;
k++;
}
}
while (i<=midIndex)//注意这里的while,不是if,若是if的话只有一个元素加入。退出循环的条件是i>midIndex或者j>end
{
*(tempArray+k)=*(mergeSortArry+i);
i++;
k++;
}
while (j<=end)
{
*(tempArray+k)=*(mergeSortArry+j);
j++;
k++;
}
for (int index=start;index<=end;index++)
{
*(mergeSortArry+index)=*(tempArray+index-start);
}
}
结果:
小结:1、灵活的使用while而不是if.增加外面while的执行
2、关键是分别判断两个数组中当前索引位置上的大小,较小的放入新的数组中