1.二分查找
1.前提:有已排序数组A(假设已经做好)
2.定义左边界left、右边界 right,确定搜索范围,循环执行二分查找(3、4两步)
3.获取中间索引mid=Floor((left+right) /2)
4.中间索引的值 A[mid]与待搜索的值T进行比较
4.1 A[mid]==T表示找到,返回中间索引
4.2 A[mid>T,中间值右侧的其它元素都大于T,无需比较,中间索引左边去找,mid-1设置为右边界,重新查找
4.3 A[mid]<T,中间值左侧的其它元素都小于T,无需比较,中间索引右边去找,mid+1设置为左边界,重新查找
5.当left>right时,表示没有找到,应结束循环
public static int binarySearch(int[]a,int p){
int left=0,right=a.length,mid;//定义边界值,步骤2
while(left<=right){//跳出循环的清空 步骤5
mid=(left+right)/2;//定义mid值 步骤3
if(a[mid]==p){//步骤4.1
return mid;
}else if(a[mid]>p){//4.2
right=mid-1;
}else {//4.3
left=mid+1;
}
}
return -1;//没找到返回-1
}
其中步骤3还可以优化一下,比如说 left+right 超过了限制 则会出现错误,byte 的最大值就是128 超过了就出错了。
优化方法如下:(left+right)/2 ==> left+(right-left/2);或者是(left+right)>>>2
上述2种都可以解决错误
在做选择填空题时,奇数个二分取中间,偶数个二分取中间靠左
2.冒泡排序
1.依次比较数组中相邻元素大小,若A[j]>A[j+1],则交换两个元素,两两都比较一边称之为一轮冒泡,结果是让最大的元素排至最后
2.重复以上步骤,直至整个数组有序
public static void bubble(int []a){
for (int j = 0; j < a.length-1; j++) {//n轮冒泡
for (int i = 0; i < a.length-1; i++) {//1轮冒泡
if (a[i] > a[i + 1]) {
int t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;
}
}
}
}
上面的算法还可以优化,比如说 有部分的数据本来就有次序,就不用比较了
public static void bubble(int[]a) {
for (int j = 0; j < a.length - 1; j++) {
boolean flag=false;//flag在这里的作用是如果下面交换数据没有执行,则跳出循环,
//没有执行则意味着后面已经排好序了
for (int i = 0; i < a.length - 1-j; i++) {
if (a[i] > a[i + 1]) {
int t=a[i];
a[i]=a[j];
a[j]=t;
flag=true;
}
}
if (!flag){
break;
}
}
}
还可以继续优化 ,上面是优化排序的轮数,下面的就是优化一轮排序的比较次数
public static void bubble2(int[]a) {
int n=a.length-1;//n是要比较的长度就是一轮冒泡两两比较的次数
do {
int last = 0;//last 就是最后一个不用比较的位置的索引
/*
比如说 2 1 3 4 7 5 8 9 10
第一层冒泡后 8 9 10 都是不用排序的 所以此时 下一次冒泡要比较的此时 也就是for循环中的n就会变成了
此时5的索引,下一次只需要两两比较到5的位置即可
*/
for (int i = 0; i < n; i++) {//比较一次
if (a[i] > a[i + 1]) {
int t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;
last = i;
}
}
n = last;
} while (n != 0);
}
3.选择排序
1.将数组分为两个子集,排序的和未排序的,每一轮从未排序的子集中选出最小的元素,放入排序子集
2.重复以上步骤,直至整个数组有序
public static void selection(int[]a){
for (int i = 0; i <a.length-1 ; i++) {
int s=i;
for (int j = s+1; j < a.length; j++) {
if (a[s]>a[j]){
s=j;
}
}
if (s!=i){
int t=a[s];
a[s]=a[i];
a[i]=t;
}
}
}
选择排序与冒泡排序相比较,
1.两者的时间复杂度都是O(n^2);
2.选择排序一般要快于冒泡,因为其交换次数少
3.但如果集合有序度高,冒泡则会优于选择
4.冒泡属于稳定排序算法,而选择属于不稳定排序算法
4.插入排序
1.将数组分为两个区域,排序区域和未排序区域,每一轮从未排序区域中去出第一个元素,插入到排序区域,需要保证顺序
2.重复以上步骤,直至整个数组有序
public static void InsertSort(int[]a){
for (int i = 1; i < a.length; i++) {
int t=a[i];
int j=i-1;
while (j>=0){
if (t<a[j]){
a[j+1]=a[j];
}else {
break;
}
j--;
}
a[j+1]=t;
}
}
插入排序与选择排序比较
1.两者平均时间复杂度都素O(n^2)
2.大部分清空下,插入都优于选择,
3.有序集合插入的时间复杂度为O(n)
4.插入属于稳定排序算法,而选择属于不稳定排序