这里分别用程序来实现这些常见的排序,唉,还是菜,手撕要是写不出来就尴尬了
首先一张图来看看都有哪些排序并分析它们
来自常见的排序算法有哪些?如何实现这些算法?,可以去看看,里面用动态图介绍了几种排序的逻辑,我这主要是程序为主,关于理念概念什么的可以自行百度了
1、冒泡排序
通过相邻的两个数进行比较大小,大的换到后面,小的换到前面,这样一轮下来数组中最大的数就被放在了数组的最后一个,
第二轮确定数组中第二大的放在了数组倒数第二的位置
…
public class Main {
public static void main(String[] args) {
//输入测试用例
int [] num = new int [] {5,4,7,8,9,5,1,3};
//进行冒泡排序
for(int i = 0; i < num.length-1; i++) { //总共需要多少轮
for(int j = 0;j < num.length-1-i; j++) { //每一轮需要比较几次,这个次数应该是递减的
if(num[j] > num[j+1]) { //前面的比后面的大,它俩位置交换
int index = num[j+1];
num[j+1] = num[j];
num[j] = index;
}
}
}
//输出排序后的结果
for(int i =0;i< num.length;i++) {
System.out.print(num[i]+" ");
}
}
}
选择排序
选择排序由两种,一种从最大的开始排,一种是从最小的开始排,这里演示选择最小的开始排序,原理是一样的,
只是一个是先遍历找到最大的放在最后面:最里面的for循环是从length-1-i到0
而另一个是先遍历找到最小的放在最前面:最里面的for循环是从i+1到length-1
public class Main {
public static void main(String[] args) {
//输入测试用例
int [] num = new int [] {5,4,7,8,9,5,1,3};
//选择排序(选最小的)
int minIndex;
for(int i =0; i< num.length-1; i++) { //遍历的轮数是一定的
minIndex = i;
for(int j =i+1;j< num.length;j++) { //每次比较的次数也是递减的
if(num[minIndex] > num[j]) {
minIndex = j;
}
}
int indexNum = num[minIndex];
num[minIndex] = num[i];
num[i] = indexNum;
}
//输出排序后的结果
for(int i =0;i< num.length;i++) {
System.out.print(num[i]+" ");
}
}
}
3、插入排序
遍历数组,到哪个位置就从那个位置开始往前遍历,只要比前面的小就继续往前遍历,直到第一个还比它大就让第一个即往后的挪一个位置,或则前面那个比它小或者等于就可以不用往前遍历,插进此位置的后面一个位置,原来的就往后挪一个位置
public class Main {
public static void main(String[] args) {
//输入测试用例
int [] num = new int [] {5,4,7,8,9,5,1,3};
//插入排序
int index;
for(int i =0; i< num.length; i++) { //遍历的轮数是一定的
//找到前面比当前数值小的位置索引
index = i;
for(int j = i-1; j>=0;j--) {
if(num[i] < num[j]) {
//因为是往前遍历,只要前面的值比当前的值大,就获取它的索引
//最后获取的索引肯定最前面比当前的值的大的索引
index = j;
}
}
//看看索引改变了没有,改变说明需要插入,还要挪动数组
if(i != index) {
//记录当前的值,
int minIndex = num[i];
for(int j = i;j>index;j--) {//索引index到i-1之间的值都要往后挪一步
num[j]=num[j-1];
}
//直接把记录的值赋给数组中索引为index的位置
num[index] = minIndex;
}
}
//输出排序后的结果
for(int i =0;i< num.length;i++) {
System.out.print(num[i]+" ");
}
}
}
4、归并排序
参考[图解] 归并排序
归并排序分为两步,拆分再合并,拆分成很多小的新数组(一个值一个的数组),再通过比较合成一个两个按从小到大排序的数组(如果是两个长度为2的合并就是合并成长度为4的数组)
public class Main3 {
//把需要插入排序的数组传进这里面
public static void mergeSort(int[] arr) {
sort(arr,0,arr.length-1);
}
//开始分解,递归
public static void sort(int []arr,int L,int R) {
if(L==R) {
return;
}
int mid = (L + R)/2;
//左
sort(arr, L, mid);
//右
sort(arr,mid+1,R);
//合并
merge(arr, L, mid, R);
}
//这里进行数组的合并
public static void merge(int[] arr,int L,int mid,int R) {
int [] temp = new int[R-L+1];
//记录新数组的索引
int i =0;
//第一部分数组的索引
int p1=L;
//第二部分数组的索引
int p2=mid+1;
//进行插入,直到一方数组没值了
while(p1 <= mid && p2<=R) {
// 比较左右两部分的元素,哪个小,把那个元素填入temp中,
if(arr[p1]<arr[p2]) {
temp[i++]=arr[p1++];
}else {
temp[i++]=arr[p2++];
}
}
// 上面的循环退出后,肯定还有一个数组还有剩余的元素,之后剩余的元素依次填入到temp中
// 以下两个while只有一个会执行
while(p1<=mid) {
temp[i++] = arr[p1++];
}
while(p2<=R) {
temp[i++] = arr[p2++];
}
//新数组的值替换旧数组中指定位置的值
for(i=0;i<temp.length;i++) {
arr[L+i] = temp[i];
}
}
public static void main(String[] args) {
//输入测试用例
int [] num = new int [] {5,4,7,8,9,5,1,3};
mergeSort(num);
//输出排序后的结果
for(int i =0;i< num.length;i++) {
System.out.print(num[i]+" ");
}
}
}
5、快速排序
快速排序有很多种排序,主要的区别就是你选的基准数是怎么选的,而造成了有很多的快速排序的分支
参考快速排序
如果你看上面的还是没看懂可以去快速排序—(面试碰到过好几次)看一看快速排序的步骤
这里以数组的第一个数为基准数做个例子
public class Main4 {
//递归排序
public static void quick_sort1(int num[] , int l, int r) {
if(l < r) {
int i = l; //数组的左边边界
int j = r; //数组的右边边界
int x = num[l]; //这个就是基准数
while(i < j) { //开始遍历
while(i<j&&num[j]>=x) { //从数组的右边开始向前遍历,找到第一个小于基准数的位置
j--;
}
if(i<j) {
num[i++] = num[j]; //基准数的位置的值换成了从右边遍历第一个小于基准数的值
}
while(i<j &&num[i]<x) { //再开始从左边开始遍历找到第一个大于基准数的位置
i++;
}
if(i<j) {
num[j--] = num[i]; //从左边遍历的第一个大于基准数的值放在上面那个num[j]的位置
}
}
num[i]=x;
quick_sort1(num, l, i-1); //开始递归基准数的左边数组
quick_sort1(num, i+1, r); //开始递归基准数的右边数组
}
}
public static void main(String[] args) {
//输入测试用例
int [] num = new int [] {57,88,60,42,83,73,48,85};
quick_sort1(num, 0, num.length-1);
//输出排序后的结果
for(int i =0;i< num.length;i++) {
System.out.print(num[i]+" ");
}
}
}
6、堆排序
import java.util.Arrays;
/**
* @author 作者
* @data 2019年8月29日
*/
public class Main5 {
public static void main(String[] args) {
int arr[] = {0,8,2,3,9,5,6};
int length = arr.length-1;
//调整为大根堆
for(int i =length/2;i>0;i--) {
adjustHeap(arr, i, length);
}
System.out.println(Arrays.toString(arr));
//和第一个元素交换,然后调整为最大堆,因为最大堆的第一个是最大的,所以肯定排在数组的最后面
//这个相当于选择排序中从后面往前确认数组的值
for(int i =length;i>1;i--) {
int num = arr[i];
arr[i]=arr[1];
arr[1] = num;
adjustHeap(arr, 1, i-1);
}
System.out.println(Arrays.toString(arr));
}
public static void adjustHeap(int arr[],int s,int e) {
int temp = arr[s];
for(int i =s*2;i<=e;i++) {
if(i<e&&arr[i]<arr[i+1]) {
i++;
}
if(arr[i]<=temp) {
break;
}
arr[s] = arr[i];
s=i;
}
arr[s] =temp;
}
}