九章算法第一课 分治与递归

分治与递归,大体思想就是将整个问题,分解成2个(一般都是)小问题,再对这2个小问题进行同样的策略,1变2,2变4...最终达到肉眼能解决的地步,将这些子子子子问题逐级往上合并,直到最顶端,回到最初的问题,得到解答。

分治与递归适合解决的经典问题有:merge sort(归并排序)、quick sort(快速排序)、二叉树问题,下面就这几个问题进行说明。

归并排序:数组a[1-n],将其划分为两段,1-n/2和n/2+1-n,似乎变得容易了,继续如此划分下去,直到只有一个数,然后往上合并,合并时采用插入排序,代码如下:

//将arr数组中的first-last这段数据排序放到temp中,最后再复制回arr中
void Merge(int *arr,int first,int mid,int last,int *temp)
{
    int i = first,j = mid+1,index = first;
    while(i<=mid && j<=last)
    {
        if(*(arr+i) < *(arr+j))
            *(temp+index++)=*(arr+i++);
        else
            *(temp+index++)=*(arr+j++);
    }
    while(i<=mid)
        *(temp+index++)=*(arr+i++);
    while(j<=last)
        *(temp+index++)=*(arr+j++);

    for(i=first;i<=last;++i)//复制回arr中
        *(arr+i) = *(temp+i);
}
void mergeSort(int arr[],int temp[],int first, int last)
{
    if(first < last)
    {
        int mid = (first + last)>>1;
        mergeSort(arr,temp,first,mid);//分治
        mergeSort(arr,temp,mid+1,last);//分治
        Merge(arr,first,mid,last,temp);//合并
    }
}

快速排序(quick sort),思路和归并排序是一致的,只是分的方式不一样,归并排序分的方式是平分,任何时候都是一半一半,再对2个一半进行相同的操作。而快速排序不同点在于,他随机选择一个数,并将这个数插到数组的合适位置,即使得位于该数左边的都比他小,位于右边的都比他大,但是所有左边的数并没有有序,然后再对左右两边的剩下的子数组进行快速排序。

int adjustArr(int *s, int first, int last)
{
    int temp = s[first];
    int i = first,j = last;
    while(i<j)
    {
       while(i<j && s[j] >= temp)//从后往前找,找到第一个小于temp的
        j--;
       if(i < j)
         s[i++] = s[j];

       while(i<j && s[i]<temp)//从前往后找,找到第一个大于temp的
         i++;
       if(i<j)
         s[j--] = s[i];//交换上面找到的2个元素,继续循环
    }
    s[i] = temp;
    return i;
}
void quickSort(int *arr, int first, int last)
{
    if(first < last)
    {
        int mid = adjustArr(arr,first,last);
        quickSort(arr,first,mid);
        quickSort(arr,mid+1,last);
    }
}


二叉树问题,因为二叉树的定义就是用递归的方式定义的,所以对二叉树进行处理的时候,很适合用递归的方式。如下面这个题目:



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值