下面我们来进行冒泡排序,它的原理就像小鱼吐泡泡,依次相邻的进行比较,将最大的向上交换 时间复杂度是O(N^2),空间复杂度是O(1),稳定。
图片的直观展示:
相关的代码:
public static void main(String[] args) {
int[] nums = new int[]{2,0,5,1,3,7};
bubbleSort(nums);
for (int i = 0; i < nums.length; i++){
System.out.println(nums[i]);
}
}
//核心代码,相邻的进行比较,大的向上调
public static void bubbleSort(int[] arr){
if(arr == null || arr.length < 2){
return;
}
//每一轮都选出了最大的放到该轮最后面,下一轮范围就除去该轮最后面的数字
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);
}
}
}
}
public static void swap(int[] arr, int i, int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
对于上面的交换swap函数还有一个比较抖机灵的做法:
public static void swap(int[] arr, int i, int j){
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
这涉及到了异或的运算,下面是异或的一些性质:
- 异或相当于无进位相加
- 甲 ^ 0 = 甲; 甲 ^ 甲 = 0
- 甲 ^ 乙 = 乙 ^ 甲
- 甲 ^ 乙 ^ 丙 = 甲 ^ (乙 ^ 丙) 所以代码块中交换的细节如下:
public static void swap(int[] arr, int i, int j){
arr[i] = arr[i] ^ arr[j]; // 甲 = 甲 ^ 乙 乙 = 乙
arr[j] = arr[i] ^ arr[j]; // 乙 = (甲 ^ 乙)^ 乙 = 甲 ^(乙 ^ 乙)= 甲 甲 = 甲 ^ 乙
arr[i] = arr[i] ^ arr[j]; // 甲 = 甲 ^ 乙 ^ 甲 =(甲 ^ 甲)^ 乙 = 乙
// 完成交换
// 当然要交换的两个数不能是同一个内存地址的,因为这样会洗成0
}
补充一个小点:
求按位来讲的数中,最后一个1
number & (~number + 1)
或者
//获得number中最低位的1
int mask = 1;
while((number & mask) == 0) {
mask <<= 1;
}
另外一个:
number & (number − 1)//其预算结果恰为把number的二进制位中的最低位的1变为0之后的结果
如:6 & (6-1) = 4, 6 = (110), 4 = (100)