import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
int[] arr = {-1, 0, 10, 9, 20};
int tmp = 0;
for(int i = 0; i < arr.length - 1; i++){ // 外层循环是用来表示需要进行多少趟排序
boolean flag = false; // 标识位,用来判断是否有进行过数据交换
for(int j = 0; j < arr.length - 1 - i; j++){ // 内层的 for 循环,用来遍历数组,交换数据
if(arr[j] > arr[j + 1]){ // 这里发现逆序(即下标小的 > 小标大的,需要将下标大的往后移动,而发生交换的代码)
flag = true; // 若有发生交换,则将标识位置为 正
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
System.out.println("第" + (i + 1) + "趟排序后的数组");
System.out.println(Arrays.toString(arr));
if(!flag){
break;
}
}
}
}
冒泡排序一定要看这个,我老是忘记,这个视频真的可有意思了
import java.util.Arrays;
public class SelectSort {
public static void main(String[] args) {
int[] arr = {8, 3, 2, 1, 7, 4, 6, 5};
System.out.println("排序前~");
System.out.println(Arrays.toString(arr));
select(arr);
}
public static void select(int[] arr){
for(int i = 0; i < arr.length - 1; i++){
int min = arr[i];
int minIndex = i;
for(int j = i + 1; j < arr.length; j++){
if(min > arr[j]){
minIndex = j;
min = arr[j];
}
}
if(minIndex != i){
arr[minIndex] = arr[i];
arr[i] = min;
}
System.out.println("第 " + (i + 1) +" 次排序后~");
System.out.println(Arrays.toString(arr));
}
}
}
import java.util.Arrays;
public class InsertSort {
public static void main(String[] args) {
int[] arr = {17,3,25,14,20,9};
insert(arr);
}
public static void insert(int[] arr){
// 原始数组为 [17,3,25,14,20,9]
for(int i = 1; i < arr.length; i++){
int insertVal = arr[i]; // 用来表示准备插入的值
int insertIndex = i - 1; // 用来表示开始比较的下标值
// insertIndex >= 0 保证了下标的合法性
// insertVal < arr[insertIndex] 我们要按照从小到大的顺序排列,
// 所以必须当要插入的值 > 当前数组的值时,才算找到合适的位置;当 要插入的值 < 当前数组的值时,必须接着往前比较,直到找到有序序列的开头或者合适的位置
while(insertIndex >= 0 && insertVal < arr[insertIndex]){
arr[insertIndex + 1] = arr[insertIndex]; // 把当前下标的值往后移动
insertIndex--; // 下标值往前移动
// 示例:第一趟的[17,3,25,14,20,9]经过第一次while循环判断后
// [17,17,25,14,20,9] 原本的 1 下标的值,用 insertVal 保存了,所以不用担心
}
// 退出 while 循环则说明已经找到合适的下标,或者到了有序序列的开始位置
// if 判断是优化代码
// 就是有的数据可能在此次插入中,比有序序列的数据都大,insertIndex 的值没有变化 —— 没有进入 while 循环
// 但是经过 80000 个数据的测试,其实优化后和优化前的时间所差不大
if(insertIndex != i){
// 一定要注意:这里赋值的时候下标值一定 得是 insertIndex + 1!!!!!!!!
// 1)当数据遍历完毕后,要往有序序列第一个添加时,此时insertIndex = -1
// 2) 当while循环是遇到合适的值退出时,当前 insertVal > arr[insertIndex],就算插入也要插入到它的下个位置
arr[insertIndex + 1] = insertVal;
}
System.out.println("第 " + i +" 趟插入排序后");
System.out.println(Arrays.toString(arr));
}
}
}
插入排序的代码要注意的小细节特别多,在写的时候一定要小心,多多注意当前下标在哪,要往哪插
import java.util.Arrays;
public class ShellSort {
public static void main(String[] args) {
int[] arr = {8,9,1,7,2,3,5,4,6,0};
shell(arr);
}
public static void shell(int[] arr){
int count = 0;
for(int gap = arr.length / 2; gap > 0; gap /= 2){
for(int i = gap; i < arr.length; i++){
int j = i - gap; // 插入排序中的第一个待比较的下标
int tmp = arr[i]; // 准备插入的数
while(j >= 0 && tmp < arr[j]){
arr[j + gap] = arr[j];
j -= gap;
}
arr[j + gap] = tmp;
}
System.out.println("第 "+(++count)+ " 次排序后的数组为 = " + Arrays.toString(arr));
}
}
}
package sort;
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int[] arr = {-9, 78, 0, 23, -567, 70};
quick(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
public static void quick(int[] arr, int left, int right){ // 用的是 几数取中法 + hoare
if(left == right){
return;
}
if(left > right){
return;
}
int pivotIndex = partition(arr, left, right);
quick(arr, left, pivotIndex - 1);
quick(arr, pivotIndex + 1, right);
}
private static int partition(int[] arr, int left, int right) {
int i = left;
int j = right;
int pivot = arr[left];
while(i < j){
while(i < j && arr[j] >= pivot){
j--;
}
while(i < j && arr[i] <= pivot){
i++;
}
swap(arr, i, j);
}
// 一旦退出while循环,则说明 i 和 j 相遇了
// 交换 i 或者 j 和 left 为下标的值,因为 基准值 pivot 在left 的位置,需要把基准值换到数组中间去
swap(arr, i, left);
return i;
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
import java.util.Arrays;
public class MergeSort {
public static void main(String[] args) {
int[] arr = {8,4,5,7,1,3,6,2};
int[] tmp = new int[arr.length];
mergeSort(arr, 0, arr.length - 1, tmp);
System.out.println(Arrays.toString(arr));
}
public static void mergeSort(int[] arr, int left, int right, int[] tmp){
if(left < right){
int mid = (left + right) / 2;
// 开始分解数组
// 先分解 mid 的左边
mergeSort(arr, left, mid, tmp);
// 再分解有右边的
mergeSort(arr, mid + 1, right,tmp);
// 分解好之后再合并
merge(arr, left, mid, right, tmp);
}
}
private static void merge(int[] arr, int left, int mid, int right, int[] tmp) {
int i = left; // 遍历左边部分时的下标
int j = mid + 1; // 遍历右边部分时的下标
int index = 0; // 临时数组的下标变化
while(i <= mid && j <= right){ // 当左边的下标和右边的下边都符合条件时,才可能进行下边的
if(arr[i] <= arr[j]){
tmp[index++] = arr[i++];
}else{
tmp[index++] = arr[j++];
}
}
// 左半边没有剩余的数
while(i <= mid){
tmp[index++] = arr[i++];
}
// 右边还有剩余的数
while(j <= right){
tmp[index++] = arr[j++];
}
// 将 tmp 数组的值拷贝到 arr 中
index = 0;
int tmpIndex = left;
while(tmpIndex <= right){
arr[tmpIndex++] = tmp[index++];
}
}
}
import java.util.Arrays;
public class RadixSort {
public static void main(String[] args) {
int[] arr = {53,3,542,748,14,214};
radixSort(arr);
System.out.println("排序后的数组 arr=" + Arrays.toString(arr));
}
private static void radixSort(int[] arr){
// 定义一个二维数组,表示 10 个桶(0 ~9)
// 1. 二维数组包含 10 个一维数组
// 2. 每个一维数组用来保存该位数下 值 为 一维数组下标的数
// 3. 因为不了解每个一维数组中应该放入多少个数,为了防止溢出,所以每个一维数组的长度设为 arr.length
int[][] bucket = new int[10][arr.length];
// 在从桶中取数据的时候不知道要从该桶中取出多少个数据,即不知道每个桶中有多少个数据
// 所以,设置 bucketElementCounts 这个数组用来记录 每个桶中有多少个数据
int[] bucketElementCounts = new int[10];
// 想知道应该遍历多少次,就应该先知道原始数组中最大数据的位数是多少
int max = arr[0];
for(int i = 1; i < arr.length; i++){ // 1)找出原始数组中的最大值
if(max < arr[i]){
max = arr[i];
}
}
// 2)确定最大数据的位数
int maxLength = (max + "").length();
// 循环开始
for(int i = 0, n = 1; i < maxLength; i++, n *= 10){ // 确定循环次数
for(int j = 0; j < arr.length; j++){ // 给原始数组中的每一个值找到合适的桶
int digitOfElement = arr[j] / n % 10;
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
bucketElementCounts[digitOfElement]++;
}
// for 循环结束,意味着把数据给桶中放的过程完成
// 从桶中取数据
int index = 0; // 用来定位数组的下标
for(int k = 0; k < bucketElementCounts.length; k++){
if(bucketElementCounts[k] != 0) {
for (int l = 0; l < bucketElementCounts[k]; l++) {
arr[index++] = bucket[k][l];
}
}
// 假设:这一轮在比较 个位数的值,则下一轮开始十位数的值的比较
// 在开始之前,必须将桶中数据的个数置为 0,即将 bucketElementCounts 数组的每一个置为 0
bucketElementCounts[k] = 0;
}
// for 循环结束,意味着将桶中的数据也全部取出了,则开始下一轮
}
}
}
堆排序单独写了一个博客