1. 冒泡排序
a、冒泡排序,是通过每一次遍历获取最大/最小值
b、将最大值/最小值放在尾部/头部
c、然后除开最大值/最小值,剩下的数据在进行遍历获取最大/最小值
d、代码实现
public static void sort(int arr[]) {
//冒泡
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
2. 选择排序
a、将第一个值看成最小值
b、然后和后续的比较找出最小值和下标
c、交换本次遍历的起始值和最小值
d、说明:每次遍历的时候,将前面找出的最小值,看成一个有序的列表,后面的看成无序的列表,然后每次遍历无序列表找出最小值。
e、代码实现
public static void sort(int arr[]) {
for (int i = 0; i < arr.length; i++) {
int min = arr[i];
int min_index = i;
for (int j = i + 1; j < arr.length; j++) {
if (min > arr[j]) {
min = arr[j];
min_index = j;
}
}
int temp = arr[i];
arr[i] = min;
arr[min_index] = temp;
}
}
3. 插入排序
a、默认从第二个数据开始比较。
b、如果第二个数据比第一个小,则交换。然后在用第三个数据比较,如果比前面小,则插入(狡猾)。否则,退出循环
c、说明:默认将第一数据看成有序列表,后面无序的列表循环每一个数据,如果比前面的数据小则插入(交换)。否则退出。
d、代码实现
public static void sort(int arr[]) {
for (int i = 1; i < arr.length; i++) {
for (int j = i; j >0; j--) {
if (arr[j] < arr[j-1]) {
int temp=arr[j];
arr[j] = arr[j-1];
arr[j-1]=temp;
}
else{
break;
}
}
}
}
4. 希尔排序(插入排序变种版)
a、基本上和插入排序一样的道理
b、不一样的地方在于,每次循环的步长,通过减半的方式来实现
c、说明:基本原理和插入排序类似,不一样的地方在于。通过间隔多个数据来进行插入排序。
d、代码实现
public static void sort(int arr[]) {
for (int s=arr.length/2;s>0;s/=2){
for (int i = s; i < arr.length; i++) {
for (int j = i; j >0 & j-s>=0; j-=s) {
if (arr[j] < arr[j-s]) {
int temp=arr[j];
arr[j] = arr[j-s];
arr[j-s]=temp;
}
else{
break;
}
}
}
}
}
5. 快速排序
a、确认列表第一个数据为中间值,第一个值看成空缺(低指针空缺)。
b、然后在剩下的队列中,看成有左右两个指针(高低)。
c、开始高指针向左移动,如果遇到小于中间值的数据,则将这个数据赋值到低指针空缺,并且将高指针的数据看成空缺值(高指针空缺)。然后先向右移动一下低指针,并且切换低指针移动。
d、当低指针移动到大于中间值的时候,赋值到高指针空缺的地方。然后先高指针向左移动,并且切换高指针移动。重复c、d操作。
e、直到高指针和低指针相等时退出,并且将中间值赋值给对应指针位置。
f、然后将中间值的左右两边看成行的列表,进行快速排序操作。
g、代码实现
public static void sort(int arr[],int low,int high) {
if(high<=low) return;
int index=low;
int value=arr[low];
int left=low,right=high;
while(right>left){
while(right>left && arr[right]>=value){
right--;
}
if(right>left){
arr[index]=arr[right];
index=right;
}
while(right>left && arr[left]<=value){
left++;
}
if(right>left){
arr[index]=arr[left];
index=left;
}
}
arr[left]=value;
sort(arr,low,index-1);
sort(arr,index+1,high);
}
6. 归并排序
public static void sort(int[] arr,int low,int high){
int mid = (low+high)/2;
if(low<high){
sort(arr,low,mid);
sort(arr,mid+1,high);
//左右归并
merge(arr,low,mid,high);
}
}
public static void merge(int[] arr,int low,int mid,int high){
int[] temp=new int[high-low+1];
int t=0;
int p1=low,p2=mid+1;
while(p1<=mid && p2<=high){
if(arr[p1]<=arr[p2]){
temp[t++]=arr[p1++];
}else{
temp[t++]=arr[p2++];
}
}
while(p1<=mid){
temp[t++]=arr[p1++];
}
while(p2<=high){
temp[t++]=arr[p2++];
}
for(int x=0;x<temp.length;x++){
arr[x+low] = temp[x];
}
}
7. 堆排序见另一篇博客,基数排序略
8. 算法对比
排序算法 | 平均时间复杂度 | 最好情况 | 最坏情况 | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O ( n 2 ) O(n^2) O(n2) | O ( n ) O(n) O(n) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 稳定 |
选择排序 | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 不稳定 |
插入排序 | O ( n 2 ) O(n^2) O(n2) | O ( n ) O(n) O(n) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 稳定 |
希尔排序 | O ( n l o g n ) O(n~log~n) O(n log n) | O ( n l o g 2 n ) O(n~log^2n) O(n log2n) | O ( n l o g 2 n ) O(n~log^2n) O(n log2n) | O ( 1 ) O(1) O(1) | 不稳定 |
归并排序 | O ( n l o g n ) O(n~log~n) O(n log n) | O ( n l o g n ) O(n~log~n) O(n log n) | O ( n l o g n ) O(n~log~n) O(n log n) | O ( 1 ) O(1) O(1) | 稳定 |
快速排序 | O ( n l o g n ) O(n~log~n) O(n log n) | O ( n l o g n ) O(n~log~n) O(n log n) | O ( n 2 ) O(n^2) O(n2) | O ( l o g n ) O(log~n) O(log n) | 不稳定 |
堆排序 | O ( n l o g n ) O(n~log~n) O(n log n) | O ( n l o g n ) O(n~log~n) O(n log n) | O ( n l o g n ) O(n~log~n) O(n log n) | O ( 1 ) O(1) O(1) | 不稳定 |