程序逻辑与算法03笔记

小涛 社区会员 2021-11-04 01:24:11

首先上图:

请添加图片描述

请添加图片描述

下面这个图就是,一开始分成了左右两部分,左边是4578,右边是1236,然后分别拿左右两部分的第一个数字进行比较,发现右边的的1小于左边的4,然后右边部分指针右移一个单位,变成了2去和左边的4比较大小,这样以此类推.......

请添加图片描述

0:我们一开始将左边的第一个数字用i来指向,右边第一个数字用j来指向,那么我们可以一开始定义一个方法

​
 /**
     * @arr 排序的原始数组
     * @param left 左边有序序列的初始索引
     * @param mid  中间索引
     * @param right  右边索引
     * @param temp  做中转的数组
     */
​
    public static  void merge(int[] arr,int left, int mid, int right,int[] temp){
        int i = left; // 初始化i,左边这个有序序列的初始索引
        int j = mid +1; //初始化j,右边这个有序序列的初始索引
        int t = 0; // 指向temp数组的当前索引
​

1:然后我们进入到了第一个循环

先把左右两边(有序)的数据按照规则填充到temp数组中,知道左右两边的有序序列有一边处理完毕为止

(1)i和j分别代表左右两部分的第一个数字,然后用他两作比较,将小的那个数字现存放到临时数组temp中,然后temp和较小的左边部分指针都要加一**

   while (i<= mid && j<=right){ //继续
            // 如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素
            // 即将左边的当前元素,拷贝到temp数组
            // 然后t要往后移动一下
            if (arr[i] <= arr[j]){
                temp[t] = arr[i];
                t+=1;
                i+=1;
            }
​
        }

(2)如果是右边的小就是这个情况,使用else

  while (i<= mid && j<=right){ //继续
            // 如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素
            // 即将左边的当前元素,填充到temp数组
            // 然后t要往后移动一下
            if (arr[i] <= arr[j]){
                temp[t] = arr[i];
                t+=1;
                i+=1;
            }else { //反之,将右边有序序列的当前元素填充到temp数组
                temp[t] = arr[j];
                t+=1;
                j+=1;
            }
​
        }

2:我们进入第二大步骤,按照我们的图片所示,我们会出现两个情况就是当右边已经全部填入temp但是左边还留有数字或者左边全部填入temp但是右边还有数字的时候:我们需要做一个循环:

 //把有剩余数据的一边的数据依次全部填充到temp去
        while (i <= mid){ //左边的有序序列还有剩余的元素,就全部填充到temp中
            temp[t] = arr[i];
            t+=1;
            i+=1;
​
        }
        while (j <= right){ //右边的有序序列还有剩余的元素,就全部填充到temp中
            temp[t] = arr[j];
            t+=1;
            j+=1;
​
        }
​

3:进入第三大步骤,也就是我们的拷贝过程,我们要将得到的temp数字拷贝到原来的数组中去,但是这个拷贝不是一下子就把八个数字全部拷贝进去的,他有一个过程,请添加图片描述

首先是我们定义一个新的指针tempLeft,然后初始为0,right是1,然后第二次合并tempLeft变成了2,right变成了3,然后再整体合并一下,tempLeft变成了0,right变成了3,同理,右边也是这样,最后tempLeft成了0right成了7就把全部的数字拷贝进去了。(相当于:01->23-> 03-> 45-> 67-> 47-> 07)

     //(三)
        //将temp数组中的元素拷贝到arr
        // 并不是每一次都拷贝所有
        t = 0;
        int tempLeft = left;
​
        //第一次合并时 tempLeft=0,right = 1  //  tempLeft = 2  right = 3 // tempLeft = 0  right = 3
        // 最后一次 tempLeft = 0 right = 7
        while (tempLeft <= right){
            arr[tempLeft] = temp[t];
            t +=1;
            tempLeft+=1;
        }
​

4:第四大步:我们前面这几步相当于一直是从已经分解好了那个时候开始的,所以我们需要使用递归调用将原数组分解:

  //分加和的方法
    public  static  void  mergeSort(int[] arr, int left,int right,int[] temp){
​
        if (left<right){
            int mid  = (left+right)/2; //中间索引
            // 向左递归进行分解
            mergeSort(arr,left,mid,temp);
            //向右递归分解
            mergeSort(arr,mid+1,right,temp);
​
​
        }
​
    }

5:第五步:编写主方法,主方法中定义初始数组和临时数组,调用方法

public class MergetSort {
    public static void main(String[] args) {
        int arr[] = {8,4,5,7,1,3,6,2};
        int temp[] = new int[arr.length]; // 归并排序需要一个额外空间
        mergeSort(arr,0, arr.length-1,temp);
        System.out.println("归并排序后="+ Arrays.toString(arr));
​
    }

最后需要再递归分解的时候加入合并:

  //分加和的方法
    public  static  void  mergeSort(int[] arr, int left,int right,int[] temp){
​
        if (left<right){
            int mid  = (left+right)/2; //中间索引
            // 向左递归进行分解
            mergeSort(arr,left,mid,temp);
            //向右递归分解
            mergeSort(arr,mid+1,right,temp);
            //合并
            merge(arr,left,mid,right,temp);
​
​
        }
​
    }
​

全部代码:

package 二分法排序;
​
import java.util.Arrays;
​
/**
 * @author ${范涛之}
 * @Description
 * @create 2021-11-04 0:13
 */
public class MergetSort {
    public static void main(String[] args) {
​
        int arr[] = {8,4,5,7,1,3,6,2};
        int temp[] = new int[arr.length]; // 归并排序需要一个额外空间
        mergeSort(arr,0, arr.length-1,temp);
        System.out.println("归并排序后="+ Arrays.toString(arr));
​
    }
​
​
    //分加和的方法
    public  static  void  mergeSort(int[] arr, int left,int right,int[] temp){
​
        if (left<right){
            int mid  = (left+right)/2; //中间索引
            // 向左递归进行分解
            mergeSort(arr,left,mid,temp);
            //向右递归分解
            mergeSort(arr,mid+1,right,temp);
            //合并
            merge(arr,left,mid,right,temp);
​
​
        }
​
    }
​
​
    // 首先写合并的方法
    // 需要四个参数,原数组,左指针,右指针,中间值,还有一个临时数组temp
​
    /**
     * @arr 排序的原始数组
     * @param left 左边有序序列的初始索引
     * @param mid  中间索引
     * @param right  右边索引
     * @param temp  做中转的数组
     */
​
    public static  void merge(int[] arr,int left, int mid, int right,int[] temp){
        System.out.println("xxx");
        int i = left; // 初始化i,左边这个有序序列的初始索引
        int j = mid +1; //初始化j,右边这个有序序列的初始索引
        int t = 0; // 指向temp数组的当前索引
​
​
        // (一)
        //先把左右两边(有序)的数据按照规则填充到temp数组中,知道左右两边的有序序列有一边处理完毕为止
        while (i<= mid && j<=right){ //继续
            // 如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素
            // 即将左边的当前元素,填充到temp数组
            // 然后t要往后移动一下
            if (arr[i] <= arr[j]){
                temp[t] = arr[i];
                t+=1;
                i+=1;
            }else { //反之,将右边有序序列的当前元素填充到temp数组
                temp[t] = arr[j];
                t+=1;
                j+=1;
            }
​
        }
​
        // (二)
        //把有剩余数据的一边的数据依次全部填充到temp去
        while (i <= mid){ //左边的有序序列还有剩余的元素,就全部填充到temp中
            temp[t] = arr[i];
            t+=1;
            i+=1;
​
        }
        while (j <= right){ //右边的有序序列还有剩余的元素,就全部填充到temp中
            temp[t] = arr[j];
            t+=1;
            j+=1;
​
        }
​
​
​
        //(三)
        //将temp数组中的元素拷贝到arr
        // 并不是每一次都拷贝所有
        t = 0;
        int tempLeft = left;
​
        //第一次合并时 tempLeft=0,right = 1  //  tempLeft = 2  right = 3 // tempLeft = 0  right = 3
        // 最后一次 tempLeft = 0 right = 7
        System.out.println("tempLeft="+tempLeft+" right="+right);
        while (tempLeft <= right){
            arr[tempLeft] = temp[t];
            t +=1;
            tempLeft+=1;
        }
​
​
​
    }
}
​

运行结果:

 

 

...全文
463 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

110

社区成员

发帖
与我相关
我的任务
社区描述
训练、训练、训练!
其他 其他
社区管理员
  • 实训001
  • 非鱼up
  • andy421
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

自律训练,自信挑战!

试试用AI创作助手写篇文章吧