冒泡排序
//冒泡排序
public void bubbleSorting(int[] array) {
//遍历比较当前节点和后一节点的值,如果当前节点比较大就交换位置
//那么每次都能把最大的一个节点放到最后,最大的节点已经确认了位置
//那么对于最后一个位置的操作我们就免去了。
int n = array.length;
for(int i = 0; i < n; i++) {
for(int j = 1; j < n - i; j++) {
if(array[j - 1] > array[j]) {
int temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
}
}
}
}
//反向冒泡排序
public void reverseBubbleSorting(int[] array) {
//遍历比较当前节点和后一节点的值,如果当前节点比较小就交换位置
//那么每次都能把 最小 的一个节点放到最前,最大的小已经确认了位置
//那么对于 第一个 一个位置的操作我们就免去了。
int n = array.length;
for(int i = 0; i < n; i++) {
for(int j = n - 1; j > i; j--) {
if(array[j - 1] > array[j]) {
int temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
}
}
}
}
选择排序
//选择排序 跟反向冒泡排序有异曲同工之妙
public void selectSorting(int[] array) {
//每次遍历找到最小的值,把值放在 0 1, 2 ,3 , n - 1 位置
int midIdx;
for(int i = 0; i < array.length; i++) {
midIdx = i;
for(int j = i + 1; j < array.length; j++) {
midIdx = array[midIdx] == Math.min(array[midIdx], array[j]) ? midIdx : j;
}
int temp = array[midIdx];
array[midIdx] = array[i];
array[i] = temp;
}
}
插入排序
//插入排序
//从索引位置1开始,默认该索引 左边已经排序,选择正确的位置插入
public void insertionSorting(int[] array) {
int n = array.length;
for(int i = 1; i < n; i++) {
// 认为 [l, r]区间有序
int l = 0, r = i;
//在[l, r]区间用二分找到需要插入节点的位置
while(l < r) {
int mid = l + ((r - l) >>> 1);
if(array[mid] == array[i]) {
l = mid;
break;
}
// 这里为什么 r = mid; 不是 r = mid - 1呢?
// 因为 当前值正好小于你 大于前面的结果,那么它是要占用的你当前位置,mid后移,如果你mid - 1,那么就无法占用你的位置了
else if(array[i] < array[mid]) r = mid ;
// 这里为什么是 l = mid + 1,而不是 l = mid;
// 如果你能理解上面,理解这里也没有难度
// 因为 当前值大于你,那么一定不会占用你的位置,所以需要 + 1;
else l = mid + 1;
}
//简单的数组添加后,平移的代码
int temp = array[i];
int _r = i;
while(_r > l) {
array[_r] = array[--_r];
}
array[l] = temp;
}
}
希尔排序
//希尔排序
public void donaldShell(int[] array) {
//先分组 后插入排序,直到分组结果小于1;
//一直对半分组
for(int group = array.length / 2; group >= 1; group /= 2) {
//分了多少组,就需要执行多少次
for(int i = 0; i < group; i++) {
//每次添加组距,直到越界
for(int j = i; j < array.length ; j+= group) {
int l = i, r = j;
//插入排序
while(l < r) {
int val = array[l];
if(val < array[r]) l += group;
else break;
}
int temp = array[j];
int _r = j;
while(_r > l) {
array[_r] = array[_r - group];
_r -= group;
}
array[l] = temp;
}
}
}
}
归并排序
//归并排序 归并排序和插入排序也有异曲同工之妙,
//插入排序,先排序 又拆分 .. 排序 拆分
//归并排序,先拆分到不能拆分后,排序,合并,排序,合并
public void mergeSorting(int[] array) {
mergeSorting(0, array.length - 1, array, new int[array.length]);
}
private void mergeSorting(int l,int r, int[] array, int[] temp) {
if(l < r) {
int mid = l + ((r - l) >>> 1);
mergeSorting(l, mid, array, temp);
mergeSorting(mid + 1, r, array, temp);
merge(l,mid, r, array, temp);
}
}
private void merge(int l, int mid, int r, int[] array, int[] temp) {
//左边区间 [l, mid]
//右边区间 [mid + 1, r];
//从左到右比较 两个区间的头结点,把最小的节点放到 temp里面;直到一个区间为null;
int idx = l;
int _l = l;
int _r = mid + 1;
while(_l <= mid && _r <= r) {
if(array[_l] <= array[_r]) {
temp[idx++] = array[_l++];
}else {
temp[idx++] = array[_r++];
}
}
// 肯定有一个区间有剩余,处理一下
while(_l <= mid) {
temp[idx++] = array[_l++];
}
while(_r <= r) {
temp[idx++] = array[_r++];
}
// copy
for(int i = l; i <= r; i++) {
array[i] = temp[i];
}
}