8种排序算法
- 1.冒泡排序
- 原理:
- 代码
- 2.选择排序
- 原理:
- 代码
- 3.直接插入排序
- 原理
- 代码
- 4.希尔排序
- 原理
- 代码
- 5.快速排序
- 原理
- 代码
- 6.归并排序
- 原理
- 代码
- 7.基数排序
- 原理
- 8.堆排序
- 原理
- 代码
- 建议参看视频学习
1.冒泡排序
原理:
数组元素两两比较,交换位置,大元素往后放,那么经过一轮比较后,最大的元素,就会出现在最大索引处
代码
import java.util.Arrays;
public class BubbleSort {
//冒泡排序
public static void main(String[] args) {
//原理:数组元素两两比较,交换位置,大元素往后放,那么经过一轮比较后,最大的元素,就会出现在最大索引处
int[] arr = {24, 69, 80, 57, 13};
//分析
/*
//第一轮比较
for (int i = 0; i < arr.length-1; i++) {
if (arr[i]>arr[i+1]){
//互换位置
int t = arr[i];
arr[i] = arr[i+1];
arr[i+1]=t;
}
}
//第二轮比较
for (int i = 0; i < arr.length-1-1; i++) {
if (arr[i]>arr[i+1]){
//互换位置
int t = arr[i];
arr[i] = arr[i+1];
arr[i+1]=t;
}
}
//第三轮比较
for (int i = 0; i < arr.length-1-2; i++) {
if (arr[i]>arr[i+1]){
//互换位置
int t = arr[i];
arr[i] = arr[i+1];
arr[i+1]=t;
}
}
//第四轮比较
for (int i = 0; i < arr.length-1-3; i++) {
if (arr[i]>arr[i+1]){
//互换位置
int t = arr[i];
arr[i] = arr[i+1];
arr[i+1]=t;
}
}
*/
int[] result = bubbleSort(arr);
System.out.println(Arrays.toString(result));
}
public static int[] bubbleSort(int[]arr){
//比较的轮数
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]){
//互换位置
int t = arr[j];
arr[j] = arr[j+1];
arr[j+1]=t;
}
}
}
return arr;
}
}
2.选择排序
原理:
选择排序原理:从0索引处开始,依次和后面的元素进行比较,小的元素往前放,经过一轮比较后, 最小的元素就出现在了最小索引处
代码
import java.util.Arrays;
public class SelectSort {
//选择排序
public static void main(String[] args) {
//原理:选择排序原理:从0索引处开始,依次和后面的元素进行比较,小的元素往前放,经过一轮比较后, 最小的元素就出现在了最小索引处
int[] arr = {24, 69, 80, 57, 13, 50};
//第一轮比较,从0索引开始
int index = 0;
//分析
/*第一轮
for (int i = 1; i < arr.length; i++) {
if (arr[index]>arr[i]){
int t = arr[index];
arr[index] = arr[i];
arr[i] = t;
}
}
//第二轮
index = 1;
for (int i = 1+index; i < arr.length; i++) {
if (arr[index]>arr[i]){
int t = arr[index];
arr[index] = arr[i];
arr[i] = t;
}
}
//第三轮
index = 2;
for (int i = 1+index; i < arr.length; i++) {
if (arr[index]>arr[i]){
int t = arr[index];
arr[index] = arr[i];
arr[i] = t;
}
}
//第四轮
index = 3;
for (int i = 1+index; i < arr.length; i++) {
if (arr[index]>arr[i]){
int t = arr[index];
arr[index] = arr[i];
arr[i] = t;
}
}
System.out.println(Arrays.toString(arr));
*/
int[] result = selectSort(arr);
System.out.println(Arrays.toString(result));
}
public static int[] selectSort(int[] arr){
for (int index = 0; index < arr.length-1; index++) {
for (int i = 1+index; i < arr.length; i++) {
if (arr[index]>arr[i]){
int t = arr[index];
arr[index] = arr[i];
arr[i] = t;
}
}
}
return arr;
}
}
3.直接插入排序
原理
直接插入排序:从1索引处开始,将后面的元素,插入之前的有序列表中使之仍保持有序
代码
import java.util.Arrays;
//直接插入排序
public class DirectInsertionSort {
public static void main(String[] args) {
//直接插入排序:从1索引处开始,将后面的元素,插入之前的有序列表中使之仍保持有序
int[] arr = {24, 69, 80, 57, 13, 50};
int[] result = directInsertionSort(arr);
System.out.println(Arrays.toString(result));
}
public static int[] directInsertionSort(int[] arr){
//外层循环定义伦次
// for (int i = 1; i < arr.length; i++) {
// //这里循环进行比较插入
// int j = i;
// while (j>0 && arr[j]<arr[j-1]){
// int t = arr[j];
// arr[j] = arr[j-1];
// arr[j-1]=t;
// j--;
// }
// }
for (int i = 1; i < arr.length; i++){
for (int j =i ; j > 0; j--) {
if(arr[j]<arr[j-1]){
int t = arr[j];
arr[j] = arr[j-1];
arr[j-1]=t;
}
}
}
return arr;
}
}
4.希尔排序
原理
- 希尔排序:他是对插入排序的一个优化,核心的思想就是合理的选取增量,经过一轮排序后, 就会让序列大致有序
- 然后再不断的缩小增量,进行插入排序,直到增量为1 那整个排序结束
代码
import java.util.Arrays;
//希尔排序(直接插入排序的的优化)
public class ShillSort {
public static void main(String[] args) {
//希尔排序:他是对插入排序的一个优化,核心的思想就是合理的选取增量,经过一轮排序后, 就会让序列大致有序
//然后再不断的缩小增量,进行插入排序,直到增量为1 那整个排序结束
int[] arr = {46, 55, 13, 42, 17, 94, 05, 70};
int[] result = shillSort(arr);
System.out.println(Arrays.toString(result));
}
public static int[] shillSort(int[] arr) {
/*
//定义一个增量
//第一轮增量为4
int h = 4;
for (int i = h; i < arr.length; i++){
for (int j =i ; j > h-1; j-=h) {
if(arr[j]<arr[j-h]){
int t = arr[j];
arr[j] = arr[j-h];
arr[j-h]=t;
}
}
}
//第二轮增量为2
h = 2;
for (int i = h; i < arr.length; i++){
for (int j =i ; j > h-1; j-=h) {
if(arr[j]<arr[j-h]){
int t = arr[j];
arr[j] = arr[j-h];
arr[j-h]=t;
}
}
}
//第三轮增量为1
h = 1;
for (int i = h; i < arr.length; i++){
for (int j =i ; j > h-1; j-=h) {
if(arr[j]<arr[j-h]){
int t = arr[j];
arr[j] = arr[j-h];
arr[j-h]=t;
}
}
}*/
// for (int h = 4; h > 0; h/=2) {
// for (int i = h; i < arr.length; i++){
// for (int j =i ; j > h-1; j-=h) {
// if(arr[j]<arr[j-h]){
// int t = arr[j];
// arr[j] = arr[j-h];
// arr[j-h]=t;
// }
// }
// }
// }
//希尔排序的思想,合理的选取这个增量
//第一次这个增量选取数组长度的一半,然后不断的减半
// for (int h = arr.length/2; h > 0; h/=2) {
// for (int i = h; i < arr.length; i++){
// for (int j =i ; j > h-1; j-=h) {
// if(arr[j]<arr[j-h]){
// int t = arr[j];
// arr[j] = arr[j-h];
// arr[j-h]=t;
// }
// }
// }
// }
//我们第一 次的增量选择数组长度的一半,还不是很好,我们可以使用一种序列叫做克努特序列
//克努特序列公式
//int h=1;
//h=h*3+1; //1,4,13, 40,121,364
//根据克努特序列选取我们第一次的增量
int jiange=1;
while (jiange<=arr.length/3){
jiange=jiange*3+1;
}
for (int h = jiange; h > 0; h=(h-1)/3) {
for (int i = h; i < arr.length; i++){
for (int j =i ; j > h-1; j-=h) {
if(arr[j]<arr[j-h]){
int t = arr[j];
arr[j] = arr[j-h];
arr[j-h]=t;
}
}
}
}
return arr;
}
}
5.快速排序
原理
- 将基准数挖出形成第一个坑。
- 由后向前找比他小的数,找到后挖出此数填到前一个坑中。
- 由前向后找比他大或等于的数,找到后也挖出此數填到前一个坑中。
- 再重复执行2,3两步骤,
代码
import java.util.Arrays;
//快速排序
public class QuickSort {
public static void main(String[] args) {
//定义了一个数组
int[] arr = {10, 3, 5, 6, 1, 0, 100, 40, 50, 8};
//调用工具类,进行快速排序传入数组,传入起始位置,传入结束位置
QuickSortUtils.quickSort(arr,0,arr.length-1);
//输出排序后的结果
System.out.println(Arrays.toString(arr));
}
}
class QuickSortUtils {
//快速排序
public static void quickSort(int[] arr,int start, int end){
//找出分左右两区的的索引位置,然后对左右两区进行递归调用
if (start<end){
int index = getIndex(arr,start,end);
quickSort(arr,start,index-1);
quickSort(arr,index+1,end);
}
}
//将基准数挖出形成第一个坑。
//由后向前找比他小的数,找到后挖出此数填到前一个坑中。
//由前向后找比他大或等于的数,找到后也挖出此數填到前一个坑中。
//再重复执行2,3两步骤,
private static int getIndex(int[] arr, int start, int end) {
int i = start;
int j = end;
int x = arr[i];
while (i<j){
//由后向前找比他小的数,找到后挖出此数填到前一个坑中。
while (i<j &&arr[j]>=x){//需要找比arr[i]小的数,如果比他大,则角标-1接着找
j--;
}
if (i<j){
arr[i] = arr[j];
i++;
}
//由前向后找比他大或等于的数,找到后也挖出此數填到前一个坑中。
while (i<j &&arr[i]<x){//需要找比arr[i]小的数,如果比他大,则角标-1接着找
i++;
}
if (i<j){
arr[j] = arr[i];
j--;
}
}
//把基准位填入到最后的坑位
arr[i] = x;
return i;
}
}
6.归并排序
原理
拆分-归并
代码
import java.util.Arrays;
//归并排序
public class MergeSort {
public static void main(String[] args) {
//我们先给一个左右两边是有序的一个数组,先来进行归并操作.
int[ ] arr={4,5,7,8, 1,2,3,6};
//拆分
chaifen(arr,0,arr.length-1);
//归并
mergeSort(arr,0,(arr.length-1)/2,arr.length-1);
//输出原数组
System.out.println(Arrays.toString(arr));
}
private static void chaifen(int[] arr, int startIndex, int endIndex) {
//计算中间索引
int centerIndex = (startIndex+endIndex)/2;
if (startIndex<endIndex){
//拆成单个的
chaifen(arr,startIndex,centerIndex);
chaifen(arr,centerIndex+1,endIndex);
// 开始归并排序
mergeSort(arr,startIndex,centerIndex,endIndex);
}
}
private static void mergeSort(int[] arr, int startIndex, int centerIndex, int endIndex) {
//定义一个临时数组
int[] tempArr = new int[endIndex-startIndex+1];
//定义左边数组起始索引
int i= startIndex;
//定义右边数组起始索引
int j = centerIndex+1;
//定义临时数组起始索引
int index = 0;
//比较左右两个数组的元素大小,往临时数组中放
while (i<=centerIndex && j<=endIndex){
if (arr[i]<=arr[j]){
tempArr[index] = arr[i];
i++;
}else {
tempArr[index] = arr[j];
j++;
}
index++;
}
//假如不能对半分完,应该处理剩余元素
//处理剩余元素
while (i<=centerIndex){
tempArr[index] = arr[i];
i++;
index++;
}
//处理剩余元素
while (j<=endIndex){
tempArr[index] = arr[j];
j++;
index++;
}
//System.out.println(Arrays.toString(tempArr));
//将临时数组中的元素取到原数组中
for (int k = 0; k < tempArr.length; k++) {
arr[k+startIndex] = tempArr[k];
}
}
}
7.基数排序
原理
基数排序:通过分配再收集的方式进行排序
import java.util.Arrays;
//基数排序
public class BaseOrder {
public static void main(String[] args) {
// 基数排序:通过分配再收集的方式进行排序
int[] arr = {2,1,5,21, 31, 444, 23, 33, 47, 10, 903, 124, 987,100};
//得确定排序轮次,
//获取数组中的最大值
//int max=getMax(arr) ;
//基数排序
baseOrder(arr);
//输出基数排序的结果
System.out.println(Arrays.toString(arr));
}
private static void baseOrder(int[] arr) {
//定义二维数组,放10个桶,每个桶最大容量为数组的最大值
int[][] tempArr = new int[10][arr.length];
//定义统计数组
int[] counts = new int[10];
int max = getMax(arr);
int len = String.valueOf(max).length();//排序几轮
//循环轮次
for (int i = 0,n=1; i < len; i++,n*=10) {
for (int j = 0; j < arr.length; j++) {
//获取每个位上的数字
int ys = arr[j]/n%10;
tempArr[ys][counts[ys]++] = arr[j];
}
//取出桶中的元素
int index = 0;
for (int k = 0; k < counts.length; k++) {
if (counts[k]!=0){
for (int h = 0; h < counts[k]; h++) {
//从桶中取出元素放回原数组
arr[index] = tempArr[k][h];
index++;
}
counts[k]=0;//清除上一次统计的个数
}
}
}
}
private static int getMax(int[] arr) {
int max = arr[0];
for (int i = 1;i<arr.length;i++){
if (arr[i]>max){
max=arr[i];
}
}
return max;
}
}
8.堆排序
原理
先把数组变成一个大顶堆,然后把根元素和最后一个元素进行调换,再进行顶堆操作
代码
import java.util.Arrays;
//堆排序
public class HeapSort {
public static void main(String[] args) {
//定义一个数组
int[] arr={1,0,6,7,2,3,4};
//调整成大顶堆的方法
//定义开始调整的位置
int startIndex = (arr.length-1)/2;
//循环开始调
for (int i = startIndex; i >= 0; i--) {
toMaxHeap(arr,arr.length,i);
}
//System.out.println(Arrays.toString(arr));
//经过上面的操作后,已经把数组变成一个大顶堆,把根元素和最后一个元素进行调换
for (int i = arr.length-1; i >0; i--) {
//进行调换
int t = arr[0];
arr[0] = arr[i];
arr[i] = t;
//换完之后,1我们再把剩余元素调成大顶堆
toMaxHeap(arr,i,0);
}
System.out.println(Arrays.toString(arr));
}
/**
*
* @param arr 要排序的数组
* @param size 调整的元素个数
* @param index 从哪里开始调整
*/
private static void toMaxHeap(int[] arr, int size, int index) {
//获取左右子节点的索引
int leftNodeIndex = index*2+1;
int rightNodeIndex = index*2+2;
//查找最大节点所对应的索引
int maxIndex = index;
if (leftNodeIndex<size && arr[leftNodeIndex]>arr[maxIndex]){
maxIndex = leftNodeIndex;
}
if (rightNodeIndex<size && arr[rightNodeIndex]>arr[maxIndex]){
maxIndex = rightNodeIndex;
}
//我们来调换位置
if (maxIndex!=index){
int t=arr[maxIndex];
arr[ maxIndex]=arr[index];
arr[index]=t;
//调换完之后可能会影响到下面的子树不是大顶堆,我们还需要再次调换
toMaxHeap(arr,size,maxIndex);
}
}
}