1冒泡排序
1.冒泡排序是稳定的排序之一
2.平均时间复杂度是 n²
3.空间复杂度是O(1)
4.实现
从左到右依次两两交换 找出最大或最小
5.代码
import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
int[]a=new int[] {5,15,17,10,1,4};
for(int i=0;i<a.length;i++) {
//J<a.length-1 是因为两两交换 最后一个没有可交换的伙伴
//减i是因为优化算法 每一次循环都会确定最后一个数字是(最大或最小)
for(int j=0;j<a.length-i-1;j++) {
if(a[j]>a[j+1]) {
//找到后两两交换
int t=a[j+1];
a[j+1]=a[j];
a[j]=t;
}
}
}
System.out.println(Arrays.toString(a));
}
}
2选择排序
1.选择排序是不稳定的
2.平均时间复杂度是n²
3.空间复杂度是O(1)
4.实现
每次循环都找到最大(或最小)的数放到前面
5.代码
import java.util.Arrays;
public class SelectSort {
public static void main(String[] args) {
int[]a=new int[] {5,15,17,10,1,4};
for(int i=0;i<a.length;i++) {
int min=a[i];
int index=i;
//这个循环用来找到最值和下标
//j=i+1 每一次循环找到该放到第i个位置的数字
//所以i之前的已经确定
for(int j=i+1;j<a.length;j++) {
if(a[j]<min) {
min=a[j];
index=j;
}
}
//交换
if(index!=i) {
int t=a[i];
a[i]=min;
a[index]=t;
}
}
System.out.println(Arrays.toString(a));
}
}
3插入排序
1.这个算法我认为比前两个理解多了一些困难 要自己推一遍过程
2.插入排序是稳定的
3.平均时间复杂度是n²
4.空间复杂度是O(1)
5.实现
相当于把数组分为两段 前面为有序 后面无序
当数组就一个数字时 无论怎样都是有序的
当大于1时 就开始从第二个开始
找第二个插入的合适位置
以此类推…
6.代码
import java.util.Arrays;
public class InsertSort {
public static void main(String[] args) {
int[]a=new int[] {5,15,17,10,-1,4};
//类似选择也是把数组分为两部分
//一部分是排好的 一部分是没有的
int insertIndex;
int insertValue;
//默认第一个是有序的 所以每次从第二个开始
for(int i=1;i<a.length;i++) {
//i-1的意思是
//当要判断第i个插在哪里时要从第i-1开始往前判断
insertIndex=i-1;
insertValue=a[i];
//下标不能越界所以>=0
//a[insertIndex]这个就是要判断的前一个值
while(insertIndex>=0&&a[insertIndex]>insertValue) {
a[insertIndex+1]=a[insertIndex];
insertIndex--;
}
//加1是因为判断不是前一个吗
//所以当找到的时候 insertIndex是这个插入数的前一个下标
if(insertIndex + 1 != i) {
a[insertIndex + 1] = insertValue;
}
}
System.out.println(Arrays.toString(a));
}
}
4希尔排序
1.希尔排序是不稳定的
2.平均时间复杂度 nlog2n
3.空间复杂度O(1)
4.实现
希尔排序是把记录按下表的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
0.1 交换法实现
相当于冒泡排序(速度慢)
public class ShellSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[]a=new int[] {5,15,0,10,1,4,3,8,18,17};//10个数据
int temp;
//希尔排序每次分组都是除2
//i=a.length/2 也是步长
for(int i=a.length/2;i>0;i/=2) {//代表总循环次数
//下面两个for相当于冒泡排序
for(int j=i;j<a.length;j++) {
//k=j-i保证每次循环从0开始
//由于j在增加所以k也再变大一直到倒数第2个
//为什么是倒数第二个 因为比较的时候是与他后一个比
//这也是下面>a[k+i]的原因
//k-i的意思 是用来找分过组之后的所有组员
for(int k=j-i;k>=0;k=k-i) {
if(a[k]>a[k+i]) {
temp=a[k];
a[k]=a[k+i];
a[k+i]=temp;
}
}
}
}
System.out.println(Arrays.toString(a));
}
}
0.2位移法
相当于插入排序
import java.util.Arrays;
public class ShellSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[]a=new int[] {5,15,0,10,1,77,3,8,18,17,14};//11个数据
//希尔排序每次分组都是除2 最后一组是长度是a.lenrth
//i=a.length/2 也是步长
for(int i=a.length/2;i>0;i/=2) {//代表总循环次数
for(int j=i;j<a.length;j++) {
int index=j;
int value=a[index];
//a[index-i]是他这组的前一个数字
if(value<a[index-i]) {
//插入排序思想
while(index-i>=0&&value< a[index - i]) {
a[index]=a[index-i];
index-=i;
}
a[index]=value;
}
}
}
System.out.println(Arrays.toString(a));
}
}
5快速排序
1.快速排序是不稳定的
2.平均时间复杂度 nlog2n
3. 空间复杂度O(logn)
4. 最佳情况:T(n) = O(nlogn) 最差情况:T(n) = O(n2) 平均情况:T(n) = O(nlogn)
5. 实现
6.大佬的描述更好 点击访问
7.具体原理看一下上面的链接
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[]a=new int[] {6,1,2,7,9 ,3,4,5,10,8};
sort(a,0,a.length-1);
System.out.println(Arrays.toString(a));
}
public static void sort(int[]a,int left,int right) {
int l=left;
int r=right;
/一定要先判断 这是递归终止的条件
if(r<l) {
return;
}
int v=a[left];
//此处设置基准为最左边的数
//所以要最右边先开始扫描
while(l<r) {
//必须从右边先开始
//必须加上l<r
//***解释: 例如 1 2 3 4 数组
//当先从左开始时 l会在0处挺 r会在3处 所以一交换就错了
//而先从右边开始 r会在0处 l也在0 所以不一影响***
while(a[r]>=v&&l<r) {
r--;
}
while(a[l]<=v&&l<r) {
l++;
}
//交换
if(l<r) {
int temp=a[r];
a[r]=a[l];
a[l]=temp;
}
}
//最后把基准和中间交换
//上面while退出条件为l=r
a[left]=a[l];
a[l]=v;
//分别向左向右递归
sort(a, left, r-1);
sort(a,l+1,right);
}
}
6归并排序
1.快速排序是稳定的
2.平均时间复杂度 nlog2n
3.空间复杂度O(logn)
4.归并排序 实现
把长度为n的输入序列分成两个长度为n/2的子序列;
对这两个子序列分别采用归并排序;
将两个排序好的子序列合并成一个最终的排序序列
5.代码
import java.util.Arrays;
public class MergetSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int a[] = { 8, 4, 5, 7, 1, 3, 6, 2 };
int[] temp=new int[a.length];
sort(a, 0, a.length-1, temp);
System.out.println(Arrays.toString(a));
}
//第二步写分+和
public static void sort(int[]a,int start,int end,int[]temp) {
if(start<end) {
int mid=(start+end)/2;
sort(a, start, mid, temp);
sort(a, mid+1, end, temp);
fen(a, start, mid, end, temp);
}
}
//先写归并排序的和
public static void fen(int[]a,int start,int mid,int end,int[]temp) {
int i=start;
int j=mid+1;
//t是temp数组的下标
int t=0;
while(i<=mid&&j<=end) {
if(a[i]<=a[j]) {
temp[t]=a[i];
i++;
t++;
}else {
temp[t]=a[j];
t++;
j++;
}
}
//当while循环退出时可能有一边有剩余
while(i<=mid) {
temp[t]=a[i];
t++;
i++;
}
while(j<=end) {
temp[t]=a[j];
j++;
t++;
}
//讲temp中拷贝到原数组中
//注意此时temp的长度不是整个 而是分的长度
//这个长度是 start到end
t=0;
int tempt=start;
while(tempt<=end) {
a[tempt]=temp[t];
t++;
tempt++;
}
}
}
7基数排序
1.基数排序是稳定的
2.平均时间复杂度是nk
3.空间复杂度是nk
4.实现
取得数组中的最大数,并取得位数;
arr为原始数组,从最低位开始取每个位组成radix数组;
对radix进行计数排序(利用计数排序适用于小范围数的特点)
5.代码
6.此排序虽然比较好理解 但是有很多的不足之处
import java.util.Arrays;
public class RadixSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int a[] = { 53, 3, 542, 748, 14, 214};
radixSort(a);
System.out.println(Arrays.toString(a));
}
public static void radixSort(int[]a) {
//先求出最大数的位数
int max=a[0];
for(int i=1;i<a.length;i++) {
max=Math.max(max,a[i]);
}
int wei=(max+"").length();
//a.length也是基数排序消耗额外空间的原因
int[][]bucket=new int[10][a.length];
//每个桶的下标
int[]bucketwei=new int[10];
//最大位数也是大循环的次数
int t=1;
//aa是原数组的下标;
for(int i=0;i<wei;i++) {
int aa=0;
for(int j=0;j<a.length;j++) {
int zy=(a[j]/t)%10;
bucket[zy][bucketwei[zy]]=a[j];
bucketwei[zy]++;
}
//把桶中数据放回
for(int j=0;j<10;j++) {
if(bucketwei[j]!=0) {
for(int k=0;k<bucketwei[j];k++) {
a[aa]=bucket[j][k];
aa++;
}
}
bucketwei[j]=0;
}
//此处不要忘了t*10
t=t*10;
}
}
}