1.排序原理
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide andConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。 归并排序核心步骤:
合并的部分代码如下(两个数组合并一个有序数组):
void MergeData(int* arr,int left,int mid,int right,int* tmp){//合并
int begin1=left;
int end1=mid;
int begin2=mid;
int end2=right;
int index=left;
while(begin1<end1&&begin2<end2){
if(arr[begin1]<=arr[begin2]){
tmp[index++]=arr[begin1++];
}else{
tmp[index++]=arr[begin2++];
}
}
while(begin1<end1){
tmp[index++]=arr[begin1++];
}
while(begin2<end2){
tmp[index++]=arr[begin2++];
}
}
原理很简单~~
2.代码实现
1.递归实现
void MergeData(int* arr,int left,int mid,int right,int* tmp){//合并
int begin1=left;
int end1=mid;
int begin2=mid;
int end2=right;
int index=left;
while(begin1<end1&&begin2<end2){
if(arr[begin1]<=arr[begin2]){
tmp[index++]=arr[begin1++];
}else{
tmp[index++]=arr[begin2++];
}
}
while(begin1<end1){
tmp[index++]=arr[begin1++];
}
while(begin2<end2){
tmp[index++]=arr[begin2++];
}
}
void _MergeSort(int* arr,int left,int right,int* tmp){//归并排序
if(right-left>1){
int mid=left+((right-left)>>1);//划分区间
_MergeSort(arr,left,mid,tmp);
_MergeSort(arr,mid,right,tmp);
MergeData(arr,left,mid,right,tmp);
memcpy(arr+left,tmp+left,(sizeof(arr[0])*(right-left)));//考回原区间
}
}
void MergeSort(int* arr,int size){//归并排序
int* tmp=(int*)malloc(sizeof(arr[0])*8);
_MergeSort(arr,0,sizeof(arr)/sizeof(arr[0]),tmp);
free(tmp);
}
2.非递归实现
void MergeData(int* arr,int left,int mid,int right,int* tmp){//合并
int begin1=left;
int end1=mid;
int begin2=mid;
int end2=right;
int index=left;
while(begin1<end1&&begin2<end2){
if(arr[begin1]<=arr[begin2]){
tmp[index++]=arr[begin1++];
}else{
tmp[index++]=arr[begin2++];
}
}
while(begin1<end1){
tmp[index++]=arr[begin1++];
}
while(begin2<end2){
tmp[index++]=arr[begin2++];
}
}
void MergeSortNor(int* arr,int size){//归并排序非递归
int* tmp=(int*)malloc(sizeof(arr[0])*size);
int gap=1;
while(gap<size){
int i=0;
for(i;i<size;i+=gap*2){
int left=i;
int mid=left+gap;
int right=mid+gap;
if(mid>size){//防止越界
mid=size;
}
if(right>size){//防止越界
right=size;
}
MergeData(arr,left,mid,right,tmp);
}
memcpy(arr,tmp,sizeof(arr[0])*size);
gap*=2;
}
free(tmp);
}
我们可以显而易见的发现:非递归的代码更简单更容易理解~~