排序与查找

查找

顺序查找

private static int search(int[] x, int target) {
		int res = -1;
		for (int i = 0; i < x.length; i++) {
			if(x[i]==target) {
				res = i;
				break;
			}
		}
		return res;//其实隐含着一个else,就是如果上面没有找到的话,res就不会更新,就直接返回res = -1;
	}

二分查找

image-20210322105713821
  • 递归版本:

    public static int binarySearch2(int arr[], int left, int right, int key) {
    		int mid = right + ((left - right) >> 1);// 比如1,7 。(1+7)/2 = 4;1+(7—1)>>1 = 1+3 = 4 【[110]>>1->011】
    //		1,8 1 + 7>>1 = 1+4= 5;
    		int midVal = arr[mid];
    
    		if (key == arr[mid]) {
    			return mid;
    		} else if (key < midVal) {
    			return binarySearch2(arr, left, mid - 1, key);
    		} else {
    			return binarySearch2(arr, mid + 1, right, key);
    		}
    
    	}
    
  • 非递归版本:

    // 非递归版本
    	public static int binarySearch3(int[] arr, int target) {
    		//定义左右标尺
            int start = 0;
    		int end = arr.length - 1;
    		//标尺不相错,一直循环;根据中值(a.算中值b.和中值比较)调整标尺或返回结果
    		while (start <= end) {//擦肩而过,就退出循环
    			int mid = start + ((end - start) >> 1);
    			int midVal = arr[mid];
    			if (target > midVal) {
    				start = mid + 1;
    			} else if (target < midVal) {
    				end = mid - 1;
    			} else {
    				return mid;
    			}
    		}
    		return -1;
    	}
    

    注意mid和midVal是不断在变化的,所以下面两句话需要写在while循环的里面

    int mid = start + ((end - start) >> 1);
    			int midVal = arr[mid];
    

    排序

    冒泡排序

    image-20210322105511945

谁更高谁就往前冲,矮的就不动,天塌下来个子高的顶着

天花板一直变化,完成一轮天花板降低。

public static void BubbleSort(int []arr) {
		/*这一层好比控制天花板*/
		for (int tianhuaban = arr.length-1; tianhuaban >=0; tianhuaban--) {
			/*这一层好比在天花板范围内将最大*/
			for (int i = 0; i < tianhuaban; i++) {			
				if(arr[i]>arr[i+1]) {
					int temp = arr[i];
					arr[i] = arr[i+1];
					arr[i+1] = temp;
				}
			}
		}
		//一趟
		
		
	}

选择排序

与冒泡相似,每一趟找到自i到末端最小的数index,然后与i交换,一趟秩序一次交换所以比冒泡快。

可以类比为地板在上升

image-20210322110843611
	public static void selectSort(int[] arr) {
		/* 这一层好比控制天花板 */
		for (int tianhuaban = arr.length - 1; tianhuaban >= 0; tianhuaban--) {
			/* 在天花板范围内选一个最大的 */
			int indexOfMax = 0;
			int max = arr[0];// 假设第一个就是最大的
			// 在天花板范围内进行寻找
			for (int i = 0; i <= tianhuaban; i++) {

				if (arr[i] > max) {// 如果当前位置更大
					indexOfMax = i;
					max = arr[i];
				}

			}
			// 内层for循环完成之后,天花板范围内的最大值及其下标就确定了
			// 找到了就把找到的元素和天花板元素进行换一换
			Util.swap(arr, indexOfMax, tianhuaban);
			// 天花板越降越低最后变为0
		}

	}

插入排序

image-20210316140513730

要把7放入:首先我前面的已经排好序了,拿到一个新的7。

先与10比,比十小肯定插在十的前面。再和5比,比5大肯定插在5的后面。

从小到大,遇到比我大的就往前走,直到遇到比我小的我就在这个后面。"欺小怕大"

代码:

	private static void insertSort(int[] arr) {
		// TODO Auto-generated method stub
		//开始摸牌,从上到小一张一张的去摸
		for (int i = 0; i < arr.length; i++) {
//			这张牌的点数是arr[i];
//			手上的牌0~i-1
			int lastIndex = i -1;//原有手牌最后一张的位置
			int v = arr[i]; //新手牌,因为往后挪动会覆盖掉原有的值
			while(lastIndex>=0&&v<arr[lastIndex]) {
				arr[lastIndex+1] = arr[lastIndex];
				lastIndex--;//比完之后最末的一张要往前挪
			}
            //lastIndex ==-1 或者新手牌更大了
			//新手牌插入
			arr[lastIndex+1] = v;
			
		}
	}

总结:

1.Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1

while(v<arr[lastIndex]) {
				arr[lastIndex+1] = 		arr[lastIndex];
				lastIndex--;//比完之后最末的一张要往前挪
			}

因为我们有一次会很不幸的把这个lastIndex赋值为-1,比如下面当比到第一项2的时候,此时lastIndex = 0,然而计算机并不知道前面没有了,所以lastIndex - 1 = -1。

image-20210316200003855

添加约束条件lastIndex>=0

2.检验每个语句中是否下标越界

int v = arr[i]; //新手牌,因为往后挪动会覆盖掉原有的值

这里i的范围是0~length-1,不会越界。

int lastIndex = i -1;//原有手牌最后一张的位置

lastIndex不停在减少,要限制它大于等于0。

	//最后一个手牌的位置+1才是新手牌插入的位置
			arr[lastIndex+1] = v;

进入这一句话说明lastIndex ==-1 或者新手牌更大了。因为while循环(while(lastIndex>=0&&v<arr[lastIndex]))之后说明已经不满足前面的那个大于新插入的这个。将其插入到不满足的后边那个即可

image-20210316201223207


posted @ 2021-03-22 11:43  记录学习Blog  阅读(38)  评论(0编辑  收藏  举报