提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
后续可能用到的 swap() 交换方法
//交换
public static void swap(int a[], int i, int j) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
提示:以下是本篇文章正文内容,下面案例可供参考
@Test
public void test01() {
int[] arr = {1, 2, 3, 5, 7, 8, 9, 12, 23, 34, 45, 56, 67, 90};
int target = 67;
int i = binarySerch(arr, target);
if (i != -1) {
System.out.println("找到了,在第" + i + "位");
} else System.out.println("未找到!");
}
//二分查找
public static int binarySerch(int[] a, int t) {
int l = 0;
int r = a.length - 1;
int m;
while (l <= r) {
m = (l + r) / 2;//如果遇到整数溢出问题 需要解决
// m = (l + r) >>> 1;//使用无符号右移的方式 效率更高 而且不会溢出
if (a[m] == t) {
return m;
} else if (a[m] > t) {//要查找的值比中间值小,去左边找 将右边界点设置成a[m-1]
r = m - 1;
} else if (a[m] < t) {//要查找的值比中间值大,去右边找 将左边界点设置成a[m+1]
l = m + 1;
}
}
return -1;
}
整数溢出
: //冒泡
@Test
public void test02() {
int a[] = {0, 1, 67, 456, 3, 23, 64, 63, 75, 767, 123, 12828, 25236};
// int a[] = {1,2,3,4,5,6,7,8,9,10};
bubble(a);
}
public static void bubble(int a[]) {
for (int i = 0; i < a.length - 1; i++) {
for (int j = 0; j < a.length - 1 - i; j++) {//冒出的泡 所以需要-i
System.out.println("比较次数:" + j);
if (a[j] > a[j + 1]) {
swap(a, j, j + 1);
}
}
System.out.println("第" + i + "轮冒泡排序:" + Arrays.toString(a));
}
}
设置一个boolean类型,当不再冒泡时break跳出
//冒泡优化一 没有比较就跳出
public static void bubble(int a[]) {
for (int i = 0; i < a.length - 1; i++) {
boolean swapped = false;//省去多余的冒泡,因为有些数组原本就是有序的
for (int j = 0; j < a.length - 1 - i; j++) {
System.out.println("比较次数:" + j);
if (a[j] > a[j + 1]) {
swap(a, j, j + 1);
swapped = true;//发生了交换
}
}
System.out.println("第" + i + "轮冒泡排序:" + Arrays.toString(a));
if (!swapped) {//如果没有发生交换,则进行break跳出
break;
}
}
}
内轮循环比较时记录最后比较的下标,在下一外轮时从下标数开始
//冒泡优化2 原数组中大数在后时,可以跳过当次冒泡
//所以记录最后一次冒泡的下标位置 下一次冒泡即可按下标位置作为冒泡次数
public static void bubble2(int a[]) {
int length = a.length - 1;
int s = 0;//记录交换轮数,可不用
while (true) {
int last = 0;//表示最后一次交换索引位置
for (int j = 0; j < length; j++) {
System.out.println("比较次数:" + j);
if (a[j] > a[j + 1]) {
swap(a, j, j + 1);
last = j;
}
}
length = last;
System.out.println("第"+(s++)+"轮冒泡排序:" + Arrays.toString(a));
if (length == 0) {//当最后一次比较的下标为0时 结束
break;
}
}
}
@Test
public void test03() {
//选择排序
int a[] = {1, 45, 12, 34, 42, 14, 31, 76, 58, 94};
select(a);
}
//选择排序
public static void select(int[] a) {
//i 代表每轮选择最小的元素要替换的位置下标索引
for (int i = 0; i < a.length; i++) {
int s = i;//代表最小的元素
for (int j = s + 1; j < a.length; j++) {//需要比较的下一位
if (a[j] < a[s]) {
s = j;
}
}
if (s!=i) {//当每轮最开始比较的数是当轮最小值时,不交换,减少交换次数
swap(a, i, s);
}
System.out.println("第" + i + "次排序后:" + Arrays.toString(a));
}
}
选择排序的交换次数大幅度减少
@Test
public void test04() {
//插入排序
int a[] = {1, 45, 12, 34, 42, 14, 31, 76, 58, 94};
// int a[] = {1,2,3,4,5,6,7,8,9,10};
insert(a);
}
private void insert(int[] a) {
// i 代表待插入元素的索引
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--;//确保每比较一个就往左更新下标 直到为0或者已排序区域的值都比待插入的值小
}
a[j+1] = t;
System.out.println(Arrays.toString(a));
}
}
使用插入排序时,如果数组前半部分有多个大数,且数组长度很长时,插排会将大数移动到数组后半部分,此时移动次数会大大增加,所以提出了希尔排序
将原本插排中相邻间隔为1的两个数进行比较 优化成相邻间隔为n的两个数进行比较,n可根据长度调整
如n为5
能够快速的将大数移动到数组后半部分