一、冒泡排序算法
冒泡排序算法思路:
- 参与比较的数据:9 8 10 7 6 0 11
——第1次循环:
8 9 10 7 6 0 11 (第1次比较:交换)
8 9 10 7 6 0 11 (第2次比较:不交换)
8 9 7 10 6 0 11 (第3次比较:交换)
8 9 7 6 10 0 11 (第4次比较:交换)
8 9 7 6 0 10 11 (第5次比较:交换)
8 9 7 6 0 10 11 (第6次比较:不交换)
最终冒出的最大数据在右边:11- 参与比较的数据:8 9 7 6 0 10
——第2次循环:
8 9 7 6 0 10(第1次比较:不交换)
8 7 9 6 0 10(第2次比较:交换)
8 7 6 9 0 10(第3次比较:交换)
8 7 6 0 9 10(第4次比较:交换)
8 7 6 0 9 10(第5次比较:不交换)- 参与比较的数据:8 7 6 0 9
——第3次循环:
7 8 6 0 9(第1次比较:交换)
7 6 8 0 9(第2次比较:交换)
7 6 0 8 9(第3次比较:交换)
7 6 0 8 9(第4次比较:不交换)- 参与比较的数据:7 6 0 8
——第4次循环:
6 7 0 8(第1次比较:交换)
6 0 7 8(第2次比较:交换)
6 0 7 8(第3次比较:不交换)- 参与比较的数据:6 0 7
——第5次循环:
0 6 7(第1次比较:交换)
0 6 7(第2次比较:不交换)- 参与比较的数据:0 6
——第6次循环:
0 6 (第1次比较:不交换)
public class BubbleSort {
public static void main(String[] args) {
int[] arr = {9, 8, 10, 7, 6, 0, 11};
// 比较次数
int count1 = 0;
// 交换次数
int count2 = 0;
//比较次数(比较次数为arr.length-1,每次比较得出最大元素)
for (int i = 0; i < arr.length - 1; i++) {
boolean flag = false;//通过flag标识位减少没有意义的比较
//比较的元素个数(比较次数+1,比较的元素个数-1)
for (int j = 0; j < arr.length - 1 - i; j++) {
count1++;
//相邻元素判断,如果前面元素大于后面元素,互换位置
if (arr[j] > arr[j + 1]) {
count2++;
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = true;
}
}
//flag还是false,则上面相邻元素判断前面都是小于后面,则证明后面不需要再互换位置了,退出循环
if (flag == false) {
break;
}
}
System.out.println(count1);//比较次数:21
System.out.println(count2);//替换次数:13
System.out.println(Arrays.toString(arr));//[0, 6, 7, 8, 9, 10, 11]
}
}
二、选择排序算法
选择排序比冒泡排序的效率高。高在交换位置的次数上。选择排序的交换位置是有意义的。
循环一次,然后找出参加比较的这堆数据中最小的,拿着这个最小的值和最前面的数据“交换位置”。
选择排序算法思路:
- 参与比较的数据:9 8 10 7 6 0 11 (这一堆参加比较的数据中最左边的元素下标是0)
——第1次循环之后的结果是:
0
8 10 7 69
11- 参与比较的数据:8 10 7 6 9 11(这一堆参加比较的数据中最左边的元素下标是1)
——第2次循环之后的结果是:
6
10 78
9 11- 参与比较的数据:10 7 8 9 11 (这一堆参加比较的数据中最左边的元素下标是2)
——第3次循环之后的结果是:
7 10
8 9 11- 参与比较的数据:10 8 9 11(这一堆参加比较的数据中最左边的元素下标是3)
——第4次循环之后的结果是:
8 10
9 11- 参与比较的数据:10 9 11(这一堆参加比较的数据中最左边的元素下标是4)
——第5次循环之后的结果是:
9 10
11- 参与比较的数据:10 11(这一堆参加比较的数据中最左边的元素下标是5)
——第6次循环之后的结果是:
10 11
public class SelectSort {
public static void main(String[] args) {
int[] arr = {9, 8, 10, 7, 6, 0, 11};
// 比较次数
int count1 = 0;
// 交换次数
int count2 = 0;
for (int i = 0; i < arr.length - 1; i++) {
//最小数的下标
int min = i;
for (int j = i+1; j < arr.length; j++) {
count1++;
if (arr[min] > arr[j]) {
min = j;//求得最小数的下标
}
}
//如果下标i不是最小数的下标,则数组下标i对应的数值替换为最小的值
if (i != min) {
count2++;
int temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
System.out.println(count1);//比较次数:21
System.out.println(count2);//替换次数:5
System.out.println(Arrays.toString(arr));//[0, 6, 7, 8, 9, 10, 11]
}
}
三、二分法查找算法(折半查找)
第一:二分法查找建立在排序的基础之上。
第二:二分法查找效率要高于“一个挨着一个”的这种查找方式。
二分法查找思路:
10(下标为0
) 23 56 89 100 111 222 235 500 600(下标为9
) arr数组
目标:找出 89 的下标
——(0 + 9) / 2 --> 4(中间元素的下标)
arr[4]这个元素就是中间元素:arr[4]是 100
100 > 89
说明被查找的元素在100的左边。
那么此时结束元素下标变成:4 - 1
——(0 + 3) / 2 --> 1(中间元素的下标)
arr[1] 对应的是:23
23 < 89
说明被查找的元素在23的右边。
那么此时开始元素下标变成:1 + 1
——(2 + 3) / 2 --> 2(中间元素的下标)
arr[2] --> 56
56 < 89
说明被查找的元素在56的右边。
那么此时开始元素下标变成:2 + 1
——(3 + 3) / 2 --> 3(中间元素的下标)
arr[3]是89,正好和89相等,此时找到了。
public class ArraySearch {
public static void main(String[] args) {
//创建一个数组
//10(```下标为0```) 23 56 89 100 111 222 235 500 600(```下标为9```)
int[] arr = {10, 23, 56, 89, 100, 111, 222, 235, 500, 600};
//在数组arr查找 89 元素的下标位置
int index = binarySearch1(arr, 89);
System.out.println(index==-1?"给定数组没有要查找的元素":"指定元素在给定数组中的下标位置为"+index);
//指定元素在给定数组中的下标位置为3
}
/**
* 从给定数组中查找指定元素的下标
* @param arr 给定数组
* @param i 指定元素
* @return 返回-1则为此数组没有此元素,返回大于等于0的数则为指定元素在给定数组中的下标
*/
private static int binarySearch1(int[] arr, int i) {
// 开始下标
int begin = 0;
// 结束下标
int end = arr.length - 1;
// 循环判断指定元素是否比中间元素大还是小,直到找到中间元素为指定元素或未找到该元素结束循环
while (begin <= end) {
// 中间元素下标
int mid = (begin + end) / 2;
// 判断指定元素比中间元素大还是小
if (i == arr[mid]) {
// 如果相等中间元素,则返回指定元素在该数组的下标位置
return mid;
} else if (i > arr[mid]) {
// 如果大于中间元素,则在中间元素的右侧,开始下标改为中间元素下标+1
begin = mid + 1;
} else {
// 如果小于中间元素,则在中间元素的左侧,结束下标改为中间元素下标-1
end = mid - 1;
}
}
return -1;
}
}