归并排序

注:元素下标从0开始

递归版本

//将数组a[]的[l1,r2]区间合并为有序区间(此处l2即为r1+1) 
void merge(int a[], int l1, int r1, int l2, int r2){
    int i = l1, j = l2; //i指向a[l1],j指向a[l2] 
    int temp[n], index = 0; //temp存放合并后的数组,index为其下标 
    while(i <= r1 && j <= r2){
        if(a[i] <= a[j]){ //如果a[i] <= a[j] 
            temp[index++] = a[i++]; //将a[i]加入序列temp 
        }else{  //如果a[i] > a[j] 
            temp[index++] = a[j++]; //将a[j]加入序列temp 
        }
    }

    while(i <= r1) temp[index++] = a[i++]; //将[l1,r1]剩余元素加入序列temp 
    while(j <= r2) temp[index++] = a[j++]; //将[l2,r2]剩余元素加入序列temp 

    for(int i = 0; i < index; i++){ //将合并后的序列 
        a[l1+i] = temp[i];
    }
}

//将a数组的[left,right]区间进行归并排序 
void mergeSort(int a[], int left, int right){
    while(left < right){  //只要left小于right 
        int mid = (left+right)/2 ;  //取left和right的中点 
        mergeSort(left,mid);    //递归,将左子区间[left,mid]归并排序 
        mergeSort(mid+1,right); //递归,将右子区间[mid+1,right]归并排序 
        merge(a,left,mid,mid+1,right); //将左子区间和右子区间合并 
    }
} 

非递归版本

void mergeSort(int a[]){
    //step为组内元素个数,step/2为左子区间元素个数,等号可以不取 
    for(int step = 2; step/2 <= n; step *= 2){
        for(int i = 0; i < n; i+=step){ //每step个元素为一组,组内前step/2各元素和后step/2个元素进行合并 
            int mid = i+step/2-1; //左子区间元素个数为step/2 
            if(mid+1 < n){ //右子区间存在元素则合并 
                //左子区间为[i,mid],右子区间为[mid+1,min(n-1,i+step-1)] --> 防止出现右子区间元素个数小于step/2的情况 
                merge(a,i,mid,mid+1,min(n-1,i+step-1)); 
            }
        }
    }
}

你可能感兴趣的:(归并排序,合并,《算法笔记》学习笔记)