1.冒泡排序
public static void bubbleSort(int nums[]) {
for (int i = 0; i < nums.length - 1; i++) {
for (int j = 0; j < nums.length - i - 1; j++) {
if(nums[j] > nums[j + 1]) {
int temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
System.out.println(Arrays.toString(nums));
}
}
就是相邻元素进行比较,把大的元素往后移,小的元素往左移,最后达到升序。我们可以看到程序在第五次排序的 时候其实是已经有序了,这里可以优化了一下,加个判断提前终止排序。
2.选择排序
public static void selectSort(int arr[]) {
int n = arr.length;
// 循环遍历数组
for (int i = 0; i < n - 1; i++) {
// 找到最小元素的索引
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// 交换找到的最小元素和当前位置元素
int temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp;
System.out.println(Arrays.toString(arr));
}
}
选择排序就是在每一次循环中,将该元素与后面的元素进行比较,找到最小值然后进行交换。
假设原数组是:64, 25, 12, 22, 11
i = 0 的时候 arr[i] = 64 ,就会与后面的所有元素比较,记录最小元素的下标值,然后进行交换。
[11, 25, 12, 22, 64]。以此类推。。。。
[11, 12, 25, 22, 64]
[11, 12, 22, 25, 64]
[11, 12, 22, 25, 64],经过四轮排序。
3.插入排序
public static void main(String[] args) {
int[] array = {64, 25, 12, 22, 11};
insertSort(array);
}
public static void insertSort(int arr[]){
for (int i = 1; i < arr.length; i++) {
int tmp = arr[i];
int j = i;
while (j > 0 && tmp < arr[j - 1]) {
arr[j] = arr[j - 1];
j--;
}
if (j != i) {
arr[j] = tmp;
}
System.out.println(Arrays.toString(arr));
}
}
主要原理就是,先记录当前的值为tmp,然后与左边排好序的值进行比较,如果是小于它,就将左边的值覆盖右边的值 就是 arr[j] = arr[j-1],直到j == 0。
当i = 1 的时候,tmp = 25 j = 1
25 < 65 然后覆盖左边的值 变成 64,64,12,22,11
j = 0 i = 1 符合条件 arr[0] = 25 变成 [25, 64, 12, 22, 11]
当 i = 2 , tmp = 12 j = 2
12 < 64 25,64,64,22,11 j = 1
12 < 25 25,25,64,22,11 j = 0
此时j == 0 arr[0] = tmp = 12 转换成 [12, 25, 64, 22, 11]
以此类推。。。。。
经过四轮排序。
[25, 64, 12, 22, 11]
[12, 25, 64, 22, 11]
[12, 22, 25, 64, 11]
[11, 12, 22, 25, 64]
4.希尔排序
public static void shellSort(int[] arr) {
int length = arr.length;
int temp;
for (int step = length / 2; step >= 1; step /= 2) {
for (int i = step; i < length; i++) {
temp = arr[i];
int j = i;
while (j >= step && arr[j - step] > temp) {
arr[j] = arr[j - step];
j -= step;
}
arr[j] = temp;
System.out.println(Arrays.toString(arr));
}
System.out.println("----------------------");
}
}
希尔排序主要是对插入排序进行了优化,引入了步长这个概念。分割成了若干个子序列进行插入排序,当setp =1 的时候然后再总体进行一次插入排序。
第一轮
[12, 25, 64, 22, 11]
[12, 22, 64, 25, 11]
[11, 22, 12, 25, 64]
----------------------
第二轮
[11, 22, 12, 25, 64]
[11, 12, 22, 25, 64]
[11, 12, 22, 25, 64]
[11, 12, 22, 25, 64]
----------------------
我们来列举一下第一轮的过程。
当step = 2
i = 2 temp = 12 j = 2
进行一次插入排序 判断条件 (j >= 2 && arr[j - step] > 12) 满足条件
进行覆盖 64,25,64,22,11 。然后 j == 0 退出条件。
arr[0] = 12 ----->>>> [12, 25, 64, 22, 11]
i = 3 temp = 22 j =3
arr[j - step] = 25
第一次判断(j >= 2 && arr[j - step] > 22 ) 满足条件
进行覆盖 12,25,64,25,11 此时j = 1 小于step 退出条件
arr[1] = 22 -------------> [12, 22, 64, 25, 11]
i = 4 temp = 11 j = 4
arr[j - step] = 64
第一次判断(j >= 2 && arr[j - step] > 11) 满足条件
进行覆盖 12,22,64,25,64 j = 2 满足条件
j = 2
arr[j - step] = 12
第二次判断 (j >= 2 && arr[j - step] > 11)满足条件
进行覆盖 12,2212,25,64 j = 0 退出
arr[0] = 11 ------------->>>>>>>>>>> [11, 22, 12, 25, 64]
5.归并排序
public static void main(String[] args) {
int[] array = {64, 25, 12, 22, 11};
mergeSort(array,0, array.length - 1);
}
public static void mergeSort(int arr[],int left, int right) {
if(left < right) {
int mid = (right - left) / 2 + left;
mergeSort(arr, left, mid);
mergeSort(arr,mid + 1, right);
merge(arr,left,mid,right);
System.out.println(Arrays.toString(arr));
}
}
public static void merge(int arr[], int left, int mid, int right) {
//临时数组记录此处的数值
int temp[] = new int[right - left + 1];
//左指针
int l = left;
//右指针
int r = mid + 1;
//记录数组下标
int k = 0;
while (l <= mid && r <= right) {
if(arr[l] < arr[r]) {
temp[k++] = arr[l++];
} else {
temp[k++] = arr[r++];
}
}
//将多于的元素重新填充
while(l <= mid) {
temp[k++] = arr[l++];
}
while (r <= right) {
temp[k++] = arr[r++];
}
//重新赋值到原数组
for(int i = 0; i < temp.length; i++) {
arr[i + left] = temp[i];
}
}
我们来看看流程图,就很直观了。就是将数组不断的切分,化成左右两份,然后去比较大小,最后再去合并数组。合并的逻辑主要是用一个临时数组去存储记录。
6.快速排序
public static void main(String[] args) {
int[] ints = {30, 34, 22, 11, 90};
quickSort(ints,0, ints.length - 1);
}
public static void quickSort(int arr[], int left, int right) {
if(left < right) {
int mid = partition(arr, left, right);
quickSort(arr, left, mid - 1);
quickSort(arr,mid + 1, right);
}
}
public static int partition(int arr[], int left, int right ) {
//选择左边第一个数作为基准数
int pivot = left;
int index= pivot + 1;
for (int i = index; i <= right; i++) {
if(arr[i] < arr[pivot]) {
swap(arr,i,index);
index++;
}
}
swap(arr,index - 1,pivot);
System.out.println(Arrays.toString(arr));
return index - 1;
}
private static void swap(int arr[], int left, int right) {
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
核心主要是分区,这里以左边第一个作为基准数,排序过程是要将小于基准数放到左边,大于基准数放到右边。
这里举一个例子就能明白了。
当第一次进入partition函数中的时候。
left = 0 right = 4 arr[pivot] = 30
i = 1 index = 1 34 > 30 30, 34, 22, 11, 90
i = 2 index = 1 22 < 30 交换 ---------->>>>>>>>30,22,34,11,90 index = 2
i = 3 index = 2 11 < 30 交换 ------------>>>>>>>>30,22,11,34,90 index = 3
i = 4 index = 3 90 > 30 结束了for循环
此时的数组是 30,22,11,34,90 index = 3
如果我们要实现小于基准数放到左边,大于基准数放到右边。
那么就需要index - 1 = 2 然后去交换,变成 11,22,30,34,90
往后的递归就是分成左右两边不断地去重复这个过程,直到全部排序完。