zoukankan      html  css  js  c++  java
  • JAVA学习之递归与归并排序

     

    从前有座山,山里有座庙,庙里有个老和尚,老和尚正在给小和尚讲故事,
    说”从前有座山,山里有座庙,庙里有个老和尚,老和尚正在给小和尚讲故事,
    说‘从前有座山,山里有座庙,庙里有个老和尚,老和尚正在给小和尚讲故事,
    说”从前有座山,山里有座庙,庙里有个老和尚,老和尚正在给小和尚讲故事,说‘……’“’“
    以上就是递归的一个故事

    递归就是在过程或函数里调用自身
    在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
    递归的典型代码就是求n的阶乘和斐波纳契数列

    //斐波那契数列,在方法中调用自身
    public static int f(int n)
    {
    if (n < 3)
    {
    return 1;
    } else
    {
    return f(n - 1) + f(n - 2);
    }
    }
    //求n的阶乘在,方法中调用自身
    public static int ff(int n)
    {
    if (n < 2)
    {
    return 1;
    } else
    {
    return n * ff(n - 1);
    }
    }

    归并排序


    所谓归并,就是把两个或者两个以上的有序表合并成一个新的有序表的过程。
    归并操作的过程如下:
    1.申请空间,使其大小为两个已经排序串行之和,该空间用来存放合并后的串行
    2.设定两个指针,最初位置分别为两个已经排序串行的起始位置
    3.比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
    4.重复步骤3直到某一指针到达串行尾
    5.将另一串行剩下的所有元素直接复制到合并串行尾

    public static void merge(int[] nums, int low, int mid, int high)
    {
    // 申请空间
    int[] temp = new int[high - low + 1];
    // 设定指针
    int i = low;
    int j = mid + 1;
    int k = 0;
    // 把较小的数先移到新数组中
    while (i <= mid && j <= high)
    {
    if (nums[i] < nums[j])
    {
    temp[k++] = nums[i++];
    } else
    {
    temp[k++] = nums[j++];
    }
    }
    // 把左边剩余的数移入数组
    while (i <= mid)
    {
    temp[k++] = nums[i++];
    }
    // 把右边边剩余的数移入数组
    while (j <= high)
    {
    temp[k++] = nums[j++];
    }
    // 把新数组中的数覆盖nums数组
    for (int k2 = 0; k2 < temp.length; k2++)
    {
    nums[k2 + low] = temp[k2];
    }
    }

    归并排序的原理是,先把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列,
    归并的前提是先把要排序的序列分为若干个字序列,然后才归并。在拆分数列的时候,就要用到拆分,直到不能再拆为止。
    如一个数列{9,8,7,6,5,4,3,2,1}
    先分成{9,8,7,6,5}和{4,3,2,1}
    然后再分成{9,8,7}和{6,5}和{4,3}和{2,1}
    然后再分{9,8}、{6}、{5}、{4}、{3}、{2}、{1}
    然后再合并起来,小在的前面,大的在后面,没有比较的在后面填充数列。

    以下是归并排序的完整代码,其中在排序的时候用到了递归拆分数列,就是在方法sort()里面

    public class MyClass
    {
    public static void main(String[] args)
    {
    int[] arr = new int[] { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
    arr = sort(arr, 0, arr.length - 1);
    for (int i = 0; i < arr.length; i++)
    {
    System.out.print(arr[i] + "");
    }
    }
    // 斐波那契数列
    public static int f(int n)
    {
    if (n < 3)
    {
    return 1;
    } else
    {
    return f(n - 1) + f(n - 2);
    }
    }
    // 求n的阶乘
    public static int ff(int n)
    {
    if (n < 2)
    {
    return 1;
    } else
    {
    return n * ff(n - 1);
    }
    }
    // 排序
    public static int[] sort(int[] nums, int low, int high)
    {
    // 把一个序列从中间的位置分开
    int mid = (low + high) / 2;
    if (low < high)
    {
    // 左边的序列递归
     sort(nums, low, mid);
    // 右边的序列递归
    sort(nums, mid + 1, high);
    // 左右归并
     merge(nums, low, mid, high);
    }
    return nums;
    }
    public static void merge(int[] nums, int low, int mid, int high)
    {
    // 申请空间
    int[] temp = new int[high - low + 1];
    // 设定指针
    int i = low;
    int j = mid + 1;
    int k = 0;
    // 把较小的数先移到新数组中
    while (i <= mid && j <= high)
    {
    if (nums[i] < nums[j])
    {
    temp[k++] = nums[i++];
    } else
    {
    temp[k++] = nums[j++];
    }
    }
    // 把左边剩余的数移入数组
    while (i <= mid)
    {
    temp[k++] = nums[i++];
    }
    // 把右边边剩余的数移入数组
    while (j <= high)
    {
    temp[k++] = nums[j++];
    }
    // 把新数组中的数覆盖nums数组
    for (int k2 = 0; k2 < temp.length; k2++)
    {
    nums[k2 + low] = temp[k2];
    }
    }
    }

    其实整个归并排序,难的不是排序,也不是归并,而是使用递归拆分,而且还是要左右拆分。

  • 相关阅读:
    重要:VC DLL编程
    VC++程序员如何做好界面
    复习二叉搜索树作的几道题
    eclipse JAVA反编译
    秒,毫秒,微秒,纳秒,皮秒,飞秒
    redis实现tomcat集群session共享
    redis启用持久化
    Spring
    Spring scope
    FastJSON 使用
  • 原文地址:https://www.cnblogs.com/fylx/p/3960785.html
Copyright © 2011-2022 走看看