冒泡排序
// 冒泡排序
public static void bubbleSort(int[] arr){
// flag作为冒泡排序的优化
// 标识是否交换过数据,如果一次冒泡都没有交换数据,则说明以及有序,直接退出
boolean flag = false;
for(int i = 0; i < arr.length - 1; i++){
for(int j = 0; j < arr.length - 1 - i; j++){
if(arr[j] > arr[j + 1]){
flag = true; // 交换过数据
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
// 没有交换过数据,直接退出
if(!flag){
break;
}else{
// 重置flag进行下一次判断
flag = false;
}
}
}
选择排序
// 选择排序 -- 选择最小的放在前面
public static void selectSort(int[] arr){
for(int i=0; i<arr.length; i++){
// 假设第i位是最小的
int minIndex = i;
int minVal = arr[i];
// 遍历后面的元素, 如果有比第i为更小的,则更新最小位
for(int j=i+1; j<arr.length; j++){
if(minVal > arr[j]){
minIndex = j; // 更新最小值索引
minVal = arr[j]; // 更新最小值
}
}
// 如果最小位的所要更新过,则需要交换数据
if(minIndex != i){
arr[minIndex] = arr[i];
arr[i] = minVal;
}
}
}
插入排序
// 插入排序
// 将待排序的元素分为有序表和无序表,一开始默认有序表只有第一位元素
// 将无序表的元素插入到有序表中 -- 判断大小需要插入的位置,然后插入
public static void insertSort(int[] arr){
for(int i=1; i<arr.length; i++){ // 无序表从第二个原始开始
int insertIndex = i-1; // 插入的位置,初始化为前一位
int insertVal = arr[i]; // 要插入的元素
// 插入的位置要小于0,确认没有越界
// insertVal < arr[insertIndex] 则没有找到合适的位置,需要继续往前走
while(insertIndex >= 0 && insertVal < arr[insertIndex]){
// 数值后移 -- 事先保持了要插入的元素 insertVal
arr[insertIndex+1] = arr[insertIndex];
insertIndex--; // 索引前移
}
// 索引是否发送改变,如果没有改变,则不需要交换数据
if(insertIndex != i-1){
arr[insertIndex+1] = insertVal;
}
}
}
快速排序
//快速排序 -- 一趟排序将元素分成两部分,一部分小于另一部分
public static void quickSort(int[] arr, int left, int right){
if(left > right){
return;
}
int l = left; // 左边界
int r = right; // 有边界
int val = arr[left]; // 自定义的 一趟排序完成后的分界值
while(l < r){
// 以下两个while循环执行顺序不能变,
while(val <= arr[r] && l < r) r--; // 从右边开始找一个比分界值小的数
while(val >= arr[l] && l < r) l++; // 再从左边开始找一个比分界值大的数
// 交换数据
if(l < r){
int temp = arr[r];
arr[r] = arr[l];
arr[l] = temp;
}
}
// 退出循环时,l=r, arr[l] 与 分解值 val 进行交换
// 如果先从右边开始找比分界值大的数,arr[l]的值小于分界值 √
// 如果先从左边开始找比分界值大的数,arr[l]的值大于分界值 ×
// 如果arr[l]大于分界值,交换之后,左边部分不会全部小于右边,不会有序
// 交换数据 -- 将分界值val放到中间
arr[left] = arr[l];
arr[l] = val;
// 先左递归
quickSort(arr, left, l-1);
// 先右递归
quickSort(arr, l+1, right);
}
归并排序
// 归并排序 -- 分治思想 需要额外的数组空间 temp
public static void mergeSort(int[] arr, int left, int right, int[] temp){
if(left < right){
int mid = (left + right) / 2; //中间索引
mergeSort(arr, left, mid, temp); // 左递归分解
mergeSort(arr, mid+1, right, temp); // 右递归分解
merge(arr, left, mid, right, temp); // 排序
}
}
// 归并排序
public static void merge(int[] arr, int left, int mid, int right, int[] temp){
int i=0; // 作为temp的索引
int l1 = left; // 左边序列的起始索引
int l2 = mid+1; // 右边序列的起始索引
while(l1 <= mid && l2 <= right){
if(arr[l1] < arr[l2]){ // 如果左边序列的数小于右边序列
temp[i++] = arr[l1++]; // 将左边序列的数加入到temp辅助数组中
}else{
temp[i++] = arr[l2++];
}
}
// 将剩下的数据全部加入的temp中
while(l1 <= mid){
temp[i++] = arr[l1++];
}
while(l2 <= right){
temp[i++] = arr[l2++];
}
// 将temp中的值重新赋值为arr
for(int t=0; t<i; t++){
arr[left+t] = temp[t];
}
}
基数排序 -- 桶排序
//基数排序 -- 桶排序
// 根据元素的个、十、百、千位的数值进行排序
public static void bucketSort(int[] arr){
// 找出最大的位数,确认需要进行多少次循环
int maxLength = 0;
for(int k : arr){
if((k + "").length() > maxLength){
maxLength = (k + "").length();
}
}
// 定义一个二维数组
// 行 -- 10个桶 0 ~ 9 代表某位的数值
// 列 -- 元素的个数,可能存在极端情况--所有元素的某一位的数值相同
int[][] bucket = new int[10][arr.length];
// 定义一个一维数组,保存每个桶中有多少值,后面需要从中取出
int[] bucketCount = new int[10];
// 加入到桶里面
for(int i=0, n=1; i<maxLength; i++, n*=10){
for(int j=0; j<arr.length; j++){
// 先整除,后取余数,获取每一位的数值
int index = arr[j] / n % 10;
// 加入到对应的桶中
// bucketCount[index] 表示该桶的第二个数据
bucket[index][bucketCount[index]] = arr[j];
// 该桶的数量加一
bucketCount[index]++;
}
int index = 0; // arr 的索引
// 取出数据
for(int k=0; k<bucketCount.length; k++){
// 不是所有的桶都有数据
if(bucketCount[k] != 0){
// 从头循环该桶取出数据
for(int m=0; m<bucketCount[k]; m++){
arr[index++] = bucket[k][m];
}
}
// 清空记录
bucketCount[k] = 0;
}
}
}
希尔排序 -- 交换法、移位法
// 希尔排序 -- 交换法
public static void shellSort(int[] arr){
// 分组
for(int gap = arr.length/2; gap > 0; gap /= 2){
// 遍历每组的元素
for(int i = gap; i<arr.length; i++){
// 每组的元素进行比较交换
for(int j = i-gap; j >= 0; j -= gap){
if(arr[j] > arr[j + gap]){
int temp = arr[j];
arr[j] = arr[j + gap];
arr[j+gap] = temp;
}
}
}
}
}
// 希尔排序 -- 移位法 -- 效率更高
public static void shellSort2(int[] arr){
// 分组
for(int gap = arr.length/2; gap > 0; gap /= 2){
// 遍历每组的元素
for(int i = gap; i<arr.length; i++){
// 从gap元素开始对该组元素直接进行插入排序
int insertIndex = i - gap;
int insertVal = arr[i];
while(insertIndex >= 0 && insertVal <= arr[insertIndex]){
arr[insertIndex + gap] = arr[insertIndex];
insertIndex -= gap;
}
// 判断是否移动过
if(insertIndex != i - gap){
arr[insertIndex + gap] = insertVal;
}
}
}
}