递归的调用顺序--c实现

 首先说说递归的调用过程,直接上代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int count = 0;
int xtrans(int a[],int left,int right){

    int mid = (left+right)/2;
    int i = 0;
    if(mid <=left || mid >=right) return -1;
    // printf("xtrans mid : %d left : %d,right: %d\n",mid,left,right);
    printf("mid : %.2d ",mid);
    printf("(%.2d)",count);
    /*if(left >=10){
        printf("--");
    }else if(left >0 && left< 10){
        printf("-");
    }*/

    for(i=0;i<left;i++){
        printf("-");
    }
    printf("%d",left);
    for(i =0; i<right-left+1;i++){
        printf("-");
    }
    count++;
    // printf("right : %d\n",right);
    printf("%d\n",right);
    xtrans(a,left,mid);
    xtrans(a,mid+1,right);
}
int main(){
    int a[51],i=0;
    srand((int)time(0));
    for(i=0;i<51;i++){
        a[i] = rand()%50;
        printf("init %d\n",a[i]);
    }
    xtrans(a,0,50);
    return 0;
}

输出:

mid : 25 (00)0---------------------------------------------------50
mid : 12 (01)0--------------------------25
mid : 06 (02)0-------------12
mid : 03 (03)0-------6
mid : 01 (04)0----3
mid : 05 (05)----4---6
mid : 09 (06)-------7------12
mid : 08 (07)-------7---9
mid : 11 (08)----------10---12
mid : 19 (09)-------------13-------------25
mid : 16 (10)-------------13-------19
mid : 14 (11)-------------13----16
mid : 18 (12)-----------------17---19
mid : 22 (13)--------------------20------25
mid : 21 (14)--------------------20---22
mid : 24 (15)-----------------------23---25
mid : 38 (16)--------------------------26-------------------------50
mid : 32 (17)--------------------------26-------------38
mid : 29 (18)--------------------------26-------32
mid : 27 (19)--------------------------26----29
mid : 31 (20)------------------------------30---32
mid : 35 (21)---------------------------------33------38
mid : 34 (22)---------------------------------33---35
mid : 37 (23)------------------------------------36---38
mid : 44 (24)---------------------------------------39------------50
mid : 41 (25)---------------------------------------39------44
mid : 40 (26)---------------------------------------39---41
mid : 43 (27)------------------------------------------42---44
mid : 47 (28)---------------------------------------------45------50
mid : 46 (29)---------------------------------------------45---47
mid : 49 (30)------------------------------------------------48---50

从上面输出可以看到,递归的调用和我猜测的差不多,就是一路向左向下,然后合并右行,然后右行之向左向下。。。。,就是不断的把大问题分解为小问题,小问题分解为更小的问题,直到更更更小的问题可以得到答案。


根据上面的递归调用可以引申到归并排序中的

1)归,就是递归分解的意思

2)并,就是把更更更小的问题答案进行合并

总的意思就是递归分解然后逐项小答案合并最终得到问题的解,其算法策略是分治法,如图:

治:

(上面的两个图都来自于:

https://www.cnblogs.com/chengxiao/p/6194356.html,

作者:dreamcatcher-cx,

文章:图解排序算法(四)之归并排序

归并排序,直接上代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int mergeSort(int a[],int left,int mid,int right,int temp[]){
	int i = left,j=mid+1,k=right;
	int t = 0;
	while(i<=mid && j <= right){
		if(a[i]<=a[j]){
			temp[t++] = a[i++];
		}else{
			temp[t++] = a[j++];
		}
	}
	while(i<=mid){
		temp[t++] = a[i++];
	}
	while(j<=right){
		temp[t++] = a[j++];
	}
	t = 0;
	while(left<=right){
		a[left++] = temp[t++];
	}
}

int divideMerge(int acx[],int left,int right,int temp[]){
	int mid;
	if(left < right){
		mid = (left+right)/2;
		divideMerge(acx,left,mid,temp);
		divideMerge(acx,mid+1,right,temp);
		mergeSort(acx,left,mid,right,temp);
	}
}

int main(){
	const int L = 50;
	int i = 0,ax[L],temp[L];
	srand((int)(time(0)));
	for(i = 0; i < L;i++){
		ax[i] = rand()%L;
		printf("%d ",ax[i]);
		temp[i] = 0;
	}
	printf("\n\n");
	divideMerge(ax,0,L,temp);

	for(i = 0; i < L;i++){
		printf("%d ",ax[i]);
	}
	printf("\n\n");
}

归并排序的列子(见《算法设计与分析基础 第三版》 134p)

归并排序的特点:

1.需要额外的空间,比如上面的代码中的temp[]数组

2.平均,最坏都是nlogn,

3.稳定

4.按照位置进行。(快速排序是按照值进行排序)。合并排序重在合并划分之后的子问题的解,而快速排序算法的主要工作在于划分,在于如何进行划分。切记。

快速排序

快速排序是另一个利用分治法进行排序的方法

猜你喜欢

转载自blog.csdn.net/phoenixcsl/article/details/84337157