排序算法 (国庆计划)

国庆的计划:

  • day01
    • 学习排序算法(完成一半)
    • 复习基础部分的知识点(未完成)
  • day02
    • 完成day01的剩余任务 排序下 基础知识
    • 复习前两周的知识 API部分 IO流部分
  • day03
    • 学习Linux

笔记

  • 冒泡排序
    • 每次外层循环都能确定一个最大数的位置 从i=0开始
    • 次数为总个数-1
    • 内层循环每次进行相邻两数的对比 从j=0开始
    • 次数为总个数-1-i
        Random ran = new Random();
        int numBound = 100;
        int numSub = 5;
        int[] arr = new int[numSub];
        for (int i= 0;i<arr.length; i++){
            arr[i] = ran.nextInt(numBound);
        }
        System.out.println(Arrays.toString(arr));
        for (int i = 0; i < arr.length-1; i++) {
            for (int j = 0; j < arr.length-1-i; j++) {
                if (arr[j]>arr[j+1]){
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
  • 选择排序
    • 外层循环,可以确定一个最小的数 从i=0开始
    • 次数 总个数-1
    • 内层循环,进行第i个数(minIndex)与其他数对比,找出最小的值 从j=i开始
    • 次数 总个数-1-i
        Random ran = new Random();
        int[] arr = new int[5];
        for (int i = 0; i < arr.length; i++) {
            arr[i]=ran.nextInt(100);
        }
        System.out.println(Arrays.toString(arr));
        for (int i = 0; i < arr.length-1; i++) {
            int minIndex = i;
            for (int j = i+1; j < arr.length; j++) {
                if (arr[minIndex]>arr[j]){
                    int temp=arr[minIndex];
                    arr[minIndex]=arr[j];
                    arr[j]=temp;
                }
            }
            System.out.println(Arrays.toString(arr));
  • 插入排序
    • 外层循环 从i=1开始 每次可确定i个数的大小关系
    • 次数 总个数-1 但因为是从1开始的所以判断应是 i<arr.length
    • 内层循环 从j=i开始 与左侧元素对比
    • 次数 不一定(break)方法
        Random ran =new Random();
        int[] arr = new int[5];
        for (int i = 0; i <arr.length ; i++) {
            arr[i] = ran.nextInt(100);
        }
        System.out.println(Arrays.toString(arr));

        for (int i = 1; i < arr.length; i++) {
            for ( int j=i ; j > 0; j--) {
                if (arr[j]<arr[j-1]){
                    int temp = arr[j];
                    arr[j]=arr[j-1];
                    arr[j-1]=temp;
                }else {
                    break;
                }
                System.out.println("j="+j);
                System.out.println(Arrays.toString(arr));
            }
        }
        System.out.println(Arrays.toString(arr));
  • 希尔排序
    • 利用插入排序的概念
    • 并引入了增量的原则,利用三层for循环,进一步缩小了对比的次数
    • 通过多次的相隔gap(增量)的对比 得到最后的有序数组
     Random ran = new Random();
        int[] arr = new int[5];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = ran.nextInt(50);
        }
        System.out.println(Arrays.toString(arr));
        /*
            多轮循环:缩减增量
            初始条件:增量(gap)值为数组长度/2
            循环条件:增量>0
            条件自变:增量自除2
         */
        for (int gap = arr.length/2; gap > 0 ; gap/=2) {
            /*
                与增量大小相同的下标继续向右循环
            */
            for (int i = gap; i < arr.length; i++) {
                /*
                    接下来的循环找左侧“同组”的元素进行对比及符合条件时换位
                    j为同组下标元素 注意不只有一个元素由于增量缩减所以需要向左循环到0
                 */
                for (int j = i-gap; j >=0 ; j-=gap) {
                    /*
                        对比两个元素的大小
                        注意下标分别为 j+gap(i) 和 j 与左侧同组元素对比
                     */
                    if (arr[j+gap]<arr[j]){
                        int temp = arr[j];
                        arr[j] = arr[j+gap];
                        arr[j+gap] = temp;
                    }else {
                        break;
                    }
                }
            }
        }
        System.out.println(Arrays.toString(arr));
  • 归并排序
    • 利用方法递归多次调用方法,mid中间数来进行多次的分组,进行排序,把有序的数组赋值给新的数组,最后返回新数组完成排序。这种效率会更优,同时代码更难理解。
public class MergeSort {
    public static void main(String[] args) {
        Random ran = new Random();
        int[] arr = new int[5];
        for (int i = 0; i < arr.length; i++) {
            arr[i]= ran.nextInt(50);
        }
        System.out.println(Arrays.toString(arr));
        int[] finalArray = mergeSort(arr,0,arr.length-1);
        System.out.println(Arrays.toString(finalArray));



    }

    /**
     * 这是一个自定义的方法,声明参考main方法 公开 静态 有返回值int[]
     * @param array 原数组
     * @param start 需要被拆分的区间的起始元素下标
     * @param end 需要被拆分的区间的结束元素下标
     * @return 合并后的有序的数组
     */
    public static int[] mergeSort(int[] array,int start,int end){
        /*
            中间点:上级数组的第一个下标+(上级数组的最后一个下标-上级数组的第一个下标)/2
            左侧:上级数组的第一个下标 到 中间点
            右侧:中间点+1 到 上级数组的最后一个下标
         */
        //为防止递归出现“死循环”,当end和start相同时(发生在尝试对数组长度为1的数组进行拆分时) 不必再执行
        if (start == end){
            //使用return返回当前片段的新数组
            return new int[]{ array[start] };
        }
        //求中间点
        int mid = start+(end-start)/2;
        //创建两个新数组,分别表示拆分后的左侧区域和右侧区域
        int[] leftArray = mergeSort(array,start,mid);
        int[] rightArray = mergeSort(array,mid+1,end);
        //创建新数组接收合并后的有序结果
        int[] newArray = new int[leftArray.length+rightArray.length];
        //声明变量,分别表示 左数组 右数组 新数组的下标位置
        int l = 0,r = 0, n = 0;
        //当leftArray和rightArray都没有遍历结束之前一直循环
        while (l<leftArray.length && r<rightArray.length){
            //对比两数组元素大小,并给newArray 后置自增+三元表达式
            newArray[n++]=leftArray[l]<=rightArray[r]?  leftArray[l++]:rightArray[r++];
/*            if (leftArray[l]<=rightArray[r]){
                newArray[n++]=leftArray[l++];
            }else {
                newArray[n++]=rightArray[r++];
            }
            if (leftArray[l]<=rightArray[r]){
                newArray[n]=leftArray[l];
                l++;
            }else {
                newArray[n]=rightArray[r];
                r++;
            }
              n++;
*/
        }
        //当有一侧数组中还有剩余,另一侧为空时,可以直接全部依次填充近newArray
        while (l<leftArray.length){
            newArray[n++]=leftArray[l++];
        }
        while (r<rightArray.length){
            newArray[n++]=rightArray[r++];
        }
        //返回新数组
        return newArray;
    }

}

//自己记忆打出的代码 不一定准确 记住熟能生巧
public static void main(String[] args){
	int[] arr = {9,2,5,3,4,1,7,6,8};
	
}
public static int[] mergeSort(int[] array,int start,int end){
	if(start==end){
		return new int[]{array[start]};
	}
	int mid = start+(end+start)/2;
	int[] leftArray = mergeSort(array,start,mid);
	int[] rightArray = mergeSort(array,mid+1,end);
	int[] newArray = new int[leftArray.length+rightArray.length];
	int l = 0,r = 0,n = 0;
	while(l<leftArray.length && r<rightArray.length){
		newArray[n++]=leftArray[l]<=rightArray[r]?leftArray[l++]:rightArray[r++];
	}
	while(l<leftArray.length){
		newArray[n++]=leftArray[l++];
	}
	while(r<rightArray.length){
		newArray[n++]=rightArray[r++];
	}
	return newArray;

}


  • 快速排序
    • 是目前经典内部排序中平均性能最优的算法,优于之前几个算法。
    public static void quickSort(int[] array,int start,int end){
        //使用新的变量来表示枢纽元位置的元素值
        int pivot = array[end];
        //创建新的变量,用于表示左侧区域最大的下标
        int x = start-1;
        //遍历数组 实现分区 左区域 右区域 枢纽元
        for (int i = start; i < end; i++) {
            //判断当前元素是否小于或等于枢纽元
            if (array[i]<=pivot){
                //判断当前元素的左侧是否已存在大于枢纽元的元素
                if (i-x>1){
                    //将下标i 与 下标x+1位置的数据换位
                    // 1 2 3 8 x 5 x 6
                    //     x       i
                    int temp = array[i];
                    array[i] = array[x+1];
                    array[x+1] = temp;
                    //x自增
                    x++;
                }else {
                    //更新x的位置
                    x=i;//(x++效果也相同)
                }
            }
        }
        //将枢纽元放在 左右两个区中间
        //交换枢纽元与第1个大于枢纽元的位置的位置
        if (pivot<array[x+1]){
            array[end] = array[x+1];
            array[x+1] = pivot;
        }
        //如果左侧区域仍有多个元素 则进行递归
        //因为x是左侧区域最大元素下标
        //若比需要处理的数组片段的最左侧元素的下标还大 则左侧区域存在超过1个元素
        if (x>start){
            quickSort(array,start,x);
        }
        //如果右侧区域同理
        if (end-x-1>1){
            quickSort(array,x+2,end);
        }

    }
}

//自己练习
public static void quickSort(int[] array,int start,int end){
		int pivot = array[end];
		int x = start-1;
		for(int i=start;i<end;i++){
			if(array[i]<pivot){
				if(i-x>1){
					int temp = array[i];
					array[i] = array[x+1];
					array[x+1] = temp;
					x++;
				}else{
					x=i;
				}
			}
		}
		if(piovt<array[x+1]){
			array[end]=array[x+1];
			array[x+1]=pivot;
		}
		if(x>start){
			quickSort(array,start,x);
		}
		if(end-x-1>1){
			quickSort(array,x+2,end);
		}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值