目录:
一.冒泡排序:
冒泡排序就是我们平时对数组进行排序就常规的一种方式.相对来说,运行速度比较慢.
代码如下:
package lession.sort;
import java.util.Arrays;
//优化过的(避免了在每轮的重复计算比较)
public class BubbleSort {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6};
boolean flag = false;
int tmp = 0;
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;
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
System.out.println("第" + (i + 1) + "趟" + Arrays.toString(arr));
if (!flag) {
break;
} else {
flag = false;
}
}
}
}
二.选择排序:
每一次都找一个最小的,然后从剩下的再找最小的,速度较快
代码如下:
package lession.sort;
import java.util.Arrays;
//选择排序
public class SelectSort {
public static void main(String[] args) {
int[] arr = {101, 34, 119, 1,-1,-123,1000};
selectSort(arr);
}
public static void selectSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
int minIndex = i;
int min = arr[minIndex];
for (int j = i + 1; j < arr.length; j++) {
if (min > arr[j]) {
min = arr[j];
minIndex = j;
}
}
//进行交换
arr[minIndex] = arr[i];
arr[i] = min;
}
System.out.println(Arrays.toString(arr));
}
}
三.插入排序:
定义:一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表.
代码如下:
package lession.sort;
import java.util.Arrays;
public class InsertSort {
public static void main(String[] args) {
int[] arr = {101, 34, 119, 1};
insertSort(arr);
}
//插入排序
public static void insertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
//定义待插入数
int insertVal = arr[i];
int insertIndex = i - 1;
while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
arr[insertIndex + 1] = arr[insertIndex];
insertIndex--;
}
if (insertIndex + 1 != i) {
arr[insertIndex + 1] = insertVal;
}
}
System.out.println(Arrays.toString(arr));
}
}
四.希尔排序:
希尔排序法基本思想:希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序.随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止.
package lession.sort;
import java.util.Arrays;
public class ShellSort {
public static void main(String[] args) {
int[] arr = {8, 9, 10, 7, 2, 3, 5, 4, 6, 0};
shellSort2(arr);
}
//1.希尔排序--交换法 17s左右--慢
public static void shellSort1(int[] arr) {
int tmp = 0;
for (int gap = arr.length / 2; gap > 0; gap = 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]) {
tmp = arr[j];
arr[j] = arr[j + gap];
arr[j + gap] = tmp;
}
}
}
}
System.out.println(Arrays.toString(arr));
}
//2.希尔排序--移位法 1s 分组后在每个组里直接用插入法
public static void shellSort2(int[] arr) {
for (int gap = arr.length / 2; gap > 0; gap = gap / 2) {
for (int i = gap; i < arr.length; i++) {
int j = i;
int tmp = arr[j];
if (arr[j] < arr[j - gap]) {
while (j - gap >= 0 && tmp < arr[j - gap]) {
//移动
arr[j] = arr[j - gap];
j -= gap;
}
arr[j] = tmp;
}
}
}
System.out.println(Arrays.toString(arr));
}
}
五.快速排序:
快速排序法:快速排序是对冒泡排序的一种改进。基本思想是:通过一趟排序将要排序的数据割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
运行速度挺快
代码如下:
package lession.sort;
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int[] arr = {-9, 78, 0, 23, -567, 70, 30, -55, 122};
int[] crr = {4, 2, 1, 5, 3, 4};
quickSort(arr, 0, arr.length - 1);
System.out.println("arr:" + Arrays.toString(arr));
}
//快速排序
public static void quickSort(int[] arr, int left, int right) {
int l = left;//左小标
int r = right;//右下标
//pivot 中轴值
int pivot = arr[(left + right) / 2];
//为了是比pivot小的放到左边,比pivot大的放到右边
while (l < r) {
//在pivot左边一直找比它大的,才退出
while (arr[l] < pivot) {
l++;
}
//在pivot右边一直找比它小的,才退出
while (arr[r] > pivot) {
r--;
}
//如果l>=r,说明pivot左边的值全部小于它,而右边的值全部大于它
if (l >= r) {
break;
}
//交换值
int tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
//如果交换完后,发现这个arr[l]==pivot,让r--,前移
if (arr[l] == pivot) {
r -= 1;
}
//如果交换完后,发现这个arr[r]==pivot,让l++,后移
if (arr[r] == pivot) {
l += 1;
}
}
//如果l==r,必须l++,r--,否则栈溢出
if (l == r) {
l += 1;
r -= 1;
}
//向左递归
if (left < r) {
quickSort(arr, left, r);
}
//向右递归
if (right > l) {
quickSort(arr, l, right);
}
}
}
六.归并排序:
归并排序:归并排序是利用归并的思想实现的排序方法,该算法采用经典的分治 策略 (分治法将问题分成一些小的问题然后递归求解,而治的阶段则将分的阶段得到的各答案”修补"在-起,即分而治之)。
运行速度挺快
代码如下:
package lession.sort;
import java.util.Arrays;
public class MergetSort {
public static void main(String[] args) {
int[] arr = {8, 4, 5, 6,7, 1, 3, 2};
int[] tmp = new int[arr.length];
mergetSort(arr, 0, arr.length - 1, tmp);
System.out.println("arr:" + Arrays.toString(arr));
}
//分解
public static void mergetSort(int[] arr, int left, int right, int[] tmp) {
if (left < right) {
int mid = (left + right) / 2;//中间索引
//左递归分解
mergetSort(arr, left, mid, tmp);
//右递归分解
mergetSort(arr, mid + 1, right, tmp);
//合并一次
merge(arr, left, right, mid, tmp);
}
}
//合并
/**
* @param arr 排序的原始数组
* @param left 左边序列的初始索引
* @param right 右边序列的初始索引
* @param mid 中间索引
* @param tmp 临时存储数据的数组
*/
public static void merge(int[] arr, int left, int right, int mid, int[] tmp) {
int i = left;//初始化i,左边序列的初始索引
int j = mid + 1;//初始化j,右边序列的初始索引
int t = 0;//tmp的索引
//1.
//先把左右两边(有序)的数据,按照规则填充到tmp数组
//直到左右两边的有序序列有一方处理完毕
while (i <= mid && j <= right) {
//如果左边的有序序列的当前元素小于等于右边的有序序列的当前元素
//把左边的有序序列的当前元素拷贝到tmp数组里
//t后移,i后移
if (arr[i] <= arr[j]) {
tmp[t] = arr[i];
i++;
} else {//反之也是如此
tmp[t] = arr[j];
j++;
}
t++;
}
//2.
//将有剩余数据的一边依次填充到tmp里
while (i <= mid) {//左边的有序序列还右剩余元素,就全部填充到tmp数组
tmp[t] = arr[i];
t++;
i++;
}
while (j <= right) {//左边的有序序列还右剩余元素,就全部填充到tmp数组
tmp[t] = arr[j];
t++;
j++;
}
//3.将tmp数据拷贝到arr里
t = 0;
int tmpLeft = left;
while (tmpLeft <= right) {
arr[tmpLeft] = tmp[t];
t++;
tmpLeft++;
}
}
}
七.基数排序(桶排序):
基数排序:将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。这样说明,比较难理解,下面我们看一个图文解释,理解基数排序的步骤
运行速度最快
代码如下:
package lession.sort;
import java.util.Arrays;
public class RadixSort {
public static void main(String[] args) {
int[] arr = {53, 3, 542, 748, 14, 214};
radixSort(arr);
}
public static void radixSort(int[] arr) {
//得到数组中最大数的位数
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
int maxLength = (max + "").length();
//第一轮排序(针对每个数的个位)
//定义一个二维数组,表示10桶,每一个桶都代表一个二维数组
int[][] buck = new int[10][arr.length];
//为了记录每个桶的有效数字,我们定义一个一维数组来记录各个桶的实际情况
int[] bulkCount = new int[10];
for (int i = 0; i < maxLength; i++) {
for (int j = 0; j < arr.length; j++) {
///取出每个元素的个位
int digit = arr[j] / (int) Math.pow(10, i) % 10;
//放到对应桶
buck[digit][bulkCount[digit]] = arr[j];
bulkCount[digit]++;
}
//按照桶的顺序,依次取出数据并放到原来的数组里
int index = 0;
//遍历每一个桶,并将桶中的数据放入到原数组
for (int k = 0; k < buck.length; k++) {
//如果桶中有数据,才让放入到原数组
if (bulkCount[k] != 0) {
//说明对应的桶有数据,循环拿出数据
for (int l = 0; l < bulkCount[k]; l++) {
//取出元素放入arr
arr[index] = buck[k][l];
index++;
}
}
//第i+1轮结束后需要将bulkCount[k]=0
bulkCount[k] = 0;
}
}
System.out.println(Arrays.toString(arr));
}
}
八.堆排序:
堆排序利用的是二叉树,所以首先要对二叉树有一定的了解!!!
代码如下:
package lession.sort;
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args) {
//根据要求升序排序,大顶堆
int[] arr = {4, 6, 8, 5, 9, 7, -5, 100, -20};
heapSort(arr);
}
public static void heapSort(int[] arr) {
System.out.println("堆排序:");
for (int i = arr.length / 2 - 1; i >= 0; i--) {
adjustHeap(arr, i, arr.length);
}
//将第一个元素依次和最后一个元素交换位置
int tmp = 0;
for (int i = arr.length - 1; i > 0; i--) {
tmp = arr[i];
arr[i] = arr[0];
arr[0] = tmp;
adjustHeap(arr, 0, i);
}
System.out.println(Arrays.toString(arr));
}
//将数组(二叉树)转为大顶堆
/**
* 功能:完成 将以i对应的节点的数调整为大顶堆
*
* @param arr 待调整的数组
* @param i 非叶子节点在数组的位置
* @param length 多少个元素进行调整,length逐渐减少
*/
public static void adjustHeap(int[] arr, int i, int length) {
//先取出当前元素的值
int tmp = arr[i];
//开始调整
for (int k = (2 * i + 1); k < length; k = 2 * k + 1) {
if (arr[k] < arr[k + 1] && k + 1 < length) {//右子节点的值当于左子节点的值
k++;//k指向右节点
}
if (arr[k] > tmp) { //如果子节点大于父节点
arr[i] = arr[k];//把较大的值赋给当前节点
i = k;//然后让i指向k,继续循环比较
} else {
//因为这里是从下往上进行的
break;
}
}
//当for循环结束,我们将i为父节点数的最大值放到了顶端
arr[i] = tmp;//把tmp的值放到调整后的位置
}
}
九.排序速度快慢比较:
1.基数排序(桶排序)
2.堆排序
3.希尔排序--移位法(本人建议,因为以上两种我感觉不太好理解!)
4.快速排序,选择排序,归并排序
5.插入排序
6.,冒泡排序,希尔排序--交换法