public class A01_BasicSearchDemo1 {
    	public static void main(String[] args) {
        //基本查找/顺序查找
        //核心:
        //从0索引开始挨个往后查找

        //需求:定义一个方法利用基本查找,查询某个元素是否存在
        //数据如下:{131, 127, 147, 81, 103, 23, 7, 79}


        int[] arr = {131, 127, 147, 81, 103, 23, 7, 79};
        int number = 82;
        System.out.println(basicSearch(arr, number));

		}



		//参数:
		//一:数组
		//二:要查找的元素

		//返回值:
		//元素是否存在
		public static boolean basicSearch(int[] arr, int number){
			//利用基本查找来查找number在数组中是否存在
			for (int i = 0; i < arr.length; i++) {
				if(arr[i] == number){
					return true;
				}
			}
			return false;
		}
		}
        
        
            
		public class A01_BasicSearchDemo2 {
    	public static void main(String[] args) {
        //课堂练习1:
        //需求:定义一个方法利用基本查找,查询某个元素在数组中的索引
        //要求:不需要考虑数组中元素是否重复


        //课堂练习2:
        //需求:定义一个方法利用基本查找,查询某个元素在数组中的索引
        //要求:需要考虑数组中元素有重复的可能性
        //{131, 127, 147, 81, 103, 23, 7, 79, 81}
        //我要查找81,想要返回的是所有索引 3 8
		}

		//参数:
		//一:数组
		//二:要查找的元素

		//返回值:
		//元素是否存在

		//心得:
		//如果我们要返回多个数据的话,可以把这些数据放到数组或者集合中。
		}
        
        
            
		public class A02_BinarySearchDemo1 {
    	public static void main(String[] args) {
        //二分查找/折半查找
        //核心:
        //每次排除一半的查找范围

        //需求:定义一个方法利用二分查找,查询某个元素在数组中的索引
        //数据如下:{7, 23, 79, 81, 103, 127, 131, 147}



        int[] arr = {7, 23, 79, 81, 103, 127, 131, 147};
        System.out.println(binarySearch(arr, 150));


    	}


    	public static int binarySearch(int[] arr, int number){
        //1.定义两个变量记录要查找的范围
        int min = 0;
        int max = arr.length - 1;

        //2.利用循环不断的去找要查找的数据
        while(true){
            if(min > max){
                return -1;
            }
            //3.找到min和max的中间位置
            int mid = (min + max) / 2;
            //4.拿着mid指向的元素跟要查找的元素进行比较
            if(arr[mid] > number){
                //4.1 number在mid的左边
                //min不变,max = mid - 1;
                max = mid - 1;
            }else if(arr[mid] < number){
                //4.2 number在mid的右边
                //max不变,min = mid + 1;
                min = mid + 1;
            }else{
                //4.3 number跟mid指向的元素一样
                //找到了
                return mid;
            }

        }
    	}

		}
        
        
            
		public class A03_BlockSearchDemo {
    	public static void main(String[] args) {
        /*
            分块查找
            核心思想:
                块内无序,块间有序
            实现步骤:
                1.创建数组blockArr存放每一个块对象的信息
                2.先查找blockArr确定要查找的数据属于哪一块
                3.再单独遍历这一块数据即可
        */
        int[] arr = {16, 5, 9, 12,21, 18,
                     32, 23, 37, 26, 45, 34,
                     50, 48, 61, 52, 73, 66};

        //创建三个块的对象
        Block b1 = new Block(21,0,5);
        Block b2 = new Block(45,6,11);
        Block b3 = new Block(73,12,17);

        //定义数组用来管理三个块的对象(索引表)
        Block[] blockArr = {b1,b2,b3};

        //定义一个变量用来记录要查找的元素
        int number = 37;

        //调用方法,传递索引表,数组,要查找的元素
        int index = getIndex(blockArr,arr,number);

        //打印一下
        System.out.println(index);



    	}

		//利用分块查找的原理,查询number的索引
		private static int getIndex(Block[] blockArr, int[] arr, int number) {
        //1.确定number是在那一块当中
        int indexBlock = findIndexBlock(blockArr, number);

        if(indexBlock == -1){
            //表示number不在数组当中
            return -1;
        }

        //2.获取这一块的起始索引和结束索引   --- 30
        // Block b1 = new Block(21,0,5);   ----  0
        // Block b2 = new Block(45,6,11);  ----  1
        // Block b3 = new Block(73,12,17); ----  2
        int startIndex = blockArr[indexBlock].getStartIndex();
        int endIndex = blockArr[indexBlock].getEndIndex();

        //3.遍历
        for (int i = startIndex; i <= endIndex; i++) {
            if(arr[i] == number){
                return i;
            }
        }
        return -1;
		}


		//定义一个方法,用来确定number在哪一块当中
		public static int findIndexBlock(Block[] blockArr,int number){ //100


        //从0索引开始遍历blockArr,如果number小于max,那么就表示number是在这一块当中的
        for (int i = 0; i < blockArr.length; i++) {
            if(number <= blockArr[i].getMax()){
                return i;
            }
        }
        return -1;
    }



	}

	class Block{
		private int max;//最大值
		private int startIndex;//起始索引
		private int endIndex;//结束索引


		public Block() {
		}

		public Block(int max, int startIndex, int endIndex) {
			this.max = max;
			this.startIndex = startIndex;
			this.endIndex = endIndex;
		}

		/**
		 * 获取
		 * @return max
		 */
		public int getMax() {
			return max;
		}

		/**
		 * 设置
		 * @param max
		 */
		public void setMax(int max) {
			this.max = max;
		}

		/**
		 * 获取
		 * @return startIndex
		 */
		public int getStartIndex() {
			return startIndex;
		}

		/**
		 * 设置
		 * @param startIndex
		 */
		public void setStartIndex(int startIndex) {
			this.startIndex = startIndex;
		}

		/**
		 * 获取
		 * @return endIndex
		 */
		public int getEndIndex() {
			return endIndex;
		}

		/**
		 * 设置
		 * @param endIndex
		 */
		public void setEndIndex(int endIndex) {
			this.endIndex = endIndex;
		}

		public String toString() {
			return "Block{max = " + max + ", startIndex = " + startIndex + ", endIndex = " + endIndex + "}";
		}
		}
        
        
            
		public class A01_BubbleDemo {
    	public static void main(String[] args) {
        /*
            冒泡排序:
            核心思想:
            1,相邻的元素两两比较,大的放右边,小的放左边。
            2,第一轮比较完毕之后,最大值就已经确定,第二轮可以少循环一次,后面以此类推。
            3,如果数组中有n个数据,总共我们只要执行n-1轮的代码就可以。
        */


        //1.定义数组
        int[] arr = {2, 4, 5, 3, 1};

        //2.利用冒泡排序将数组中的数据变成 1 2 3 4 5

        //外循环:表示我要执行多少轮。 如果有n个数据,那么执行n - 1 轮
        for (int i = 0; i < arr.length - 1; i++) {
            //内循环:每一轮中我如何比较数据并找到当前的最大值
            //-1:为了防止索引越界
            //-i:提高效率,每一轮执行的次数应该比上一轮少一次。
            for (int j = 0; j < arr.length - 1 - i; j++) {
                //i 依次表示数组中的每一个索引:0 1 2 3 4
                if(arr[j] > arr[j + 1]){
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }

        printArr(arr);

		}

		private static void printArr(int[] arr) {
			//3.遍历数组
			for (int i = 0; i < arr.length; i++) {
				System.out.print(arr[i] + " ");
			}
			System.out.println();
		}
		}
        
        
            
		public class A02_SelectionDemo {
    	public static void main(String[] args) {

        /*
            选择排序:
                1,从0索引开始,跟后面的元素一一比较。
                2,小的放前面,大的放后面。
                3,第一次循环结束后,最小的数据已经确定。
                4,第二次循环从1索引开始以此类推。

         */


        //1.定义数组
        int[] arr = {2, 4, 5, 3, 1};


        //2.利用选择排序让数组变成 1 2 3 4 5
       /* //第一轮:
        //从0索引开始,跟后面的元素一一比较。
        for (int i = 0 + 1; i < arr.length; i++) {
            //拿着0索引跟后面的数据进行比较
            if(arr[0] > arr[i]){
                int temp = arr[0];
                arr[0] = arr[i];
                arr[i] = temp;
            }
        }*/

        //最终代码:
        //外循环:几轮
        //i:表示这一轮中,我拿着哪个索引上的数据跟后面的数据进行比较并交换
        for (int i = 0; i < arr.length -1; i++) {
            //内循环:每一轮我要干什么事情?
            //拿着i跟i后面的数据进行比较交换
            for (int j = i + 1; j < arr.length; j++) {
                if(arr[i] > arr[j]){
                    int temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
        }


        printArr(arr);


		}
		private static void printArr(int[] arr) {
			//3.遍历数组
			for (int i = 0; i < arr.length; i++) {
				System.out.print(arr[i] + " ");
			}
			System.out.println();
		}
		}
        
        
            
		public class A03_InsertDemo {
    	public static void main(String[] args) {
        /*
            插入排序:
                将0索引的元素到N索引的元素看做是有序的,把N+1索引的元素到最后一个当成是无序的。
                遍历无序的数据,将遍历到的元素插入有序序列中适当的位置,如遇到相同数据,插在后面。
                N的范围:0~最大索引

        */
        int[] arr = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};

        //1.找到无序的哪一组数组是从哪个索引开始的。  2
        int startIndex = -1;
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] > arr[i + 1]){
                startIndex = i + 1;
                break;
            }
        }

        //2.遍历从startIndex开始到最后一个元素,依次得到无序的哪一组数据中的每一个元素
        for (int i = startIndex; i < arr.length; i++) {
            //问题:如何把遍历到的数据,插入到前面有序的这一组当中

            //记录当前要插入数据的索引
            int j = i;

            while(j > 0 && arr[j] < arr[j - 1]){
                //交换位置
                int temp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = temp;
                j--;
            }

        }
        printArr(arr);
		}

		private static void printArr(int[] arr) {
			//3.遍历数组
			for (int i = 0; i < arr.length; i++) {
				System.out.print(arr[i] + " ");
			}
			System.out.println();
		}
		}
        
        
            
		public class A04_RecursionDemo1 {
		public static void main(String[] args) {
			method();
		}


		public static void method(){
			method();
		}
		}
        
        
            
		public class A04_RecursionDemo2 {
    	public static void main(String[] args) {
        //需求:利用递归求1-100之间的和
        //100 + 99 + 98 + 97 + 96 + 95 .... + 2 + 1

        //大问题拆解成小问题
        //1~100之间的和 = 100 + (1~99之间的和)
        //1~99之间的和 = 99 + (1~98之间的和)
        //1~98之间的和 = 98 + (1~97之间的和)
        //。。。
        //1~2之间的和 = 2 + (1~1之间的和)
        //1~1之间的和 = 1(递归的出口)

        //核心:
        //1.找出口
        //2.找规律

        System.out.println(getSum(100));//5050

		}


		public static int getSum(int number){//99
			if(number == 1){
				return 1;
			}

			//如果numbert不是1呢?
			return number + getSum(number -1);

		}
		}
        
        
            
		public class A04_RecursionDemo3 {
    	public static void main(String[] args) {
        //需求:利用递归求5的阶乘
        //5! = 5 * 4 * 3 * 2 * 1;

        //核心:
        //1.找出口
        //2.找规律
        //心得:
        //方法内部再次调用方法的时候,参数必须要更加的靠近出口
        //第一次调用:5
        //第二次调用:4


        //5! = 5 * 4!;
        //4! = 4 * 3!;
        //3! = 3 * 2!;
        //2! = 2 * 1!;
        //1! = 1;

        System.out.println(getFactorialRecursion(5));//120


		}

		public static int getFactorialRecursion(int number){//5 !
			if(number == 1){
				return 1;
			}

			return number * getFactorialRecursion(number - 1);
		}
		}
        
        
            
		import java.util.Arrays;

		public class A05_QuickSortDemo {
    	public static void main(String[] args) {
        System.out.println(Integer.MAX_VALUE);
        System.out.println(Integer.MIN_VALUE);
		/*
			快速排序:
				第一轮:以0索引的数字为基准数,确定基准数在数组中正确的位置。
				比基准数小的全部在左边,比基准数大的全部在右边。
				后面以此类推。
		*/

        int[] arr = {1,1, 6, 2, 7, 9, 3, 4, 5, 1,10, 8};


        //int[] arr = new int[1000000];

        /* Random r = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = r.nextInt();
        }*/


        long start = System.currentTimeMillis();
        quickSort(arr, 0, arr.length - 1);
        long end = System.currentTimeMillis();

        System.out.println(end - start);//149

        System.out.println(Arrays.toString(arr));
        //课堂练习:
        //我们可以利用相同的办法去测试一下,选择排序,冒泡排序以及插入排序运行的效率
        //得到一个结论:快速排序真的非常快。

       /* for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }*/

		}


		/*
		 *   参数一:我们要排序的数组
		 *   参数二:要排序数组的起始索引
		 *   参数三:要排序数组的结束索引
		 * */
		public static void quickSort(int[] arr, int i, int j) {
        //定义两个变量记录要查找的范围
        int start = i;
        int end = j;

        if(start > end){
            //递归的出口
            return;
        }



        //记录基准数
        int baseNumber = arr[i];
        //利用循环找到要交换的数字
        while(start != end){
            //利用end,从后往前开始找,找比基准数小的数字
            //int[] arr = {1, 6, 2, 7, 9, 3, 4, 5, 10, 8};
            while(true){
                if(end <= start || arr[end] < baseNumber){
                    break;
                }
                end--;
            }
            System.out.println(end);
            //利用start,从前往后找,找比基准数大的数字
            while(true){
                if(end <= start || arr[start] > baseNumber){
                    break;
                }
                start++;
            }



            //把end和start指向的元素进行交换
            int temp = arr[start];
            arr[start] = arr[end];
            arr[end] = temp;
        }

        //当start和end指向了同一个元素的时候,那么上面的循环就会结束
        //表示已经找到了基准数在数组中应存入的位置
        //基准数归位
        //就是拿着这个范围中的第一个数字,跟start指向的元素进行交换
        int temp = arr[i];
        arr[i] = arr[start];
        arr[start] = temp;

        //确定6左边的范围,重复刚刚所做的事情
        quickSort(arr,i,start - 1);
        //确定6右边的范围,重复刚刚所做的事情
        quickSort(arr,start + 1,j);
    	}
		}
        
        
单词