简单排序(选择,冒泡,插入,二分查找)

48 篇文章 0 订阅
46 篇文章 0 订阅
本文详细介绍了三种经典的排序算法——选择排序、冒泡排序和插入排序,以及二分查找在有序数组中的应用。针对每种算法,不仅提供了代码实现,还分析了它们的时间复杂度和空间复杂度。此外,还探讨了局部最小值的查找方法。
摘要由CSDN通过智能技术生成

选择排序

arr[0]和其余数字依次比较,得到最小的,确定好arr[0]是最小的数字
再到arr[1]的位置,arr[1]和剩下后面的其余数字比较,比它小就交换,直到比较到最后一个数字,第二小的数字确定下来
再到arr[2],以此类推

private void selectionSort(int[] arr){
	if (null == arr || arr.length <= 1){
		return;
	}
	int minIndex = 0;
	for (int i=0; i<arr.length-1; i++){
		minIndex = i;
		for(int j=i+1; j<arr.length; j++){
			if(arr[minIndex] > arr[j]){
				minIndex = j;
			}
		}
		if(i != minIndex){
			swap(arr, minIndex, i);
		}
	}
}

private void swap(int[] arr, i, j){
	int temp = arr[i];
	arr[i] = arr[j];
	arr[j] = temp;
}

时间复杂度O(N^2),空间复杂度O(1)

冒泡排序

冒泡排序上面有两种循环方式,主要是最外层控制条件的写法的不同,第二种可能更好理解一些

private void bubbleSort1(int[] arr){
	if (null == arr || arr.length <= 1){
		return;
	}
	//外层控制条件是外层循环次数,总共需要循环N-1次
	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]){
				swap(arr, j, j+1);
			}
		}
	}
}

private void bubbleSort2(int[] arr){
	if (null == arr || arr.length <= 1){
		return;
	}
	//0~N-1,第一次循环,需要遍历0~N-1的位置
	//0~N-2,由于最后一个数字已经确定为最大的数字,第二次循环,只需要遍历0~N-2的位置
	//0~N-3,前两次循环已经确定了最大的数字和第二大的数字,第三次循环只需要遍历0~N-3的位置
	//...
	//最外层控制条件,每次循环到哪个位置
	for(int i=arr.length-1; i>0; i--){
		for(int j=0; j<i; j++){
			if(arr[j] > arr[j+1]){
				swap(arr, j, j+1);
			}
		}
	}
}

插入排序

局部有序,再将下一个数字插入进来,排序的过程有点像是倒着的冒泡排序
先保证arr[0]到arr[1]有序
将arr[2]插入进来时,先和arr[1]作比较,如果比arr[1]小,就交换,否则继续插入数据
后面插入进来的数据同理

private void insertionSort(int[] arr){
	if (null == arr || arr.length <= 1){
		return;
	}
	//外层控制的是大循环的次数,也就是除了第一个数字,其他数字插入的位置
	for (int i=1; i<arr.length; i++){
		for (int j=i-1; j>=0; j--){
			if(arr[j] > arr[j+1]){
				swap(arr, j, j+1);
			} else {
				//当前数据已经是有序的了,就没有继续比较的需要
				break;
			}
					
		}
	}
}

插入排序按照最差情况来计算时间复杂度,完全是倒序的情况下的复杂度,O(N^2)

二分查找

在一个有序数组中找某个数是否存在

private boolean idExist(int[] arr, int num){
	if(null == arr || arr.length == 0){
		return false;
	}
	int left = 0;
	int right = arr.length - 1;
	int mid = 0;
	while(left < right){
		mid = left + (right - left)>>1;//防止溢出
		if(arr[mid]>num){
			right = mid - 1;
		} else if(arr[mid]<num){
			left = mid + 1;
		} else {
			return true;
		}
	}
	return arr[left] == num;
}

在一个有序数组中,找>=某个数最左侧的位置

private int nearestIndex(int[] arr, int value){
	int left = 0;
	int right = arr.length-1;
	int index == -1;
	while(left<right){
		int mid = left + (right-left)>>1;
		if(arr[mid]>=value){
			index = mid;
			right= mid - 1;
		} else {
			left = mid  + 1;
		}
	}
	return index;
}

局部最小值
【题目】有一个数组,任意两个相邻的数字都不相同,找出局部最小,找到就返回下标

局部最小,即一个数字既比左侧数字小,也比右侧数字小, 如果是arr[0],则只需比右侧数字小即可,如果是arr[length-1],则只需要比左侧数字小即可

private int getLessIndex(int[] arr){
	if(null == arr || arr.length == 0){
		return -1;
	}
	if (arr.length == 1 || arr[0]<arr[1]){
		return 0;
	}
	int len = arr.length;
	if (arr[len-1]<arr[len-2]){
		return len-1;
	}
	int left = 1;
	int right = len - 2;
	int mid = 0;
	while (left < right){
		int mid = left + (right-left)>>1;
		if (arr[mid] > arr[mid-1]){
			right = mid - 1;
		} else if(arr[mid] > arr[mid+1]){
			left = mid + 1;
		} else {
			return mid;
		}
		
	}
	return left;
}

获取数组中最大值
【要求】递归实现

private int getMax(int[] arr){
	getMax(arr, 0, arr.length-1);
}

private int process(int[] arr, int left, int right){
	if(left == right){
		return arr[left];
	}
	int mid = left + (right-left)>>1;
	int L = process(arr, left, mid);
	int R = process(arr, mid+1, right);
	return Math.max(L, R);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值