各算法复杂度及稳定性
冒泡排序(Bubble Sort)
冒泡排序可以说是非常经典的一种排序算法也是最为基础的一种排序算法,其算法如其名,将元素像泡泡一样的往上浮动到水面。废话不多说,直接上图。
此图能够清晰的表现出冒泡算法的核心之处,就是在于两两元素间的比较,小的则放前面,遍历一遍后可以清楚的发现最大的元素已经排到了末尾,由此我们可以得出仅需要遍历n-1遍即可以得出最终结果。但是这里有一个细节之处在于并不是每一次遍历都需要从头元素到尾元素,因为每遍历一次,后面都会确定一个,所以每轮遍历应该是从0到n-i,接下来上代码:
int[] arr=new int[]{3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};//定义一个用来测试的数组
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 temp=arr[j];//设置一个中间变量来存储数据
arr[j]=arr[j+1];//将小的移动到前面去
arr[j+1]=temp;
}
}
}
选择排序(Selection Sort)
选择排序的过程相对比较简单,也是大部分人第一时间能够想到的,就是每次遍历确定一个最小的元素,然后将其放在最前面,跟冒泡排序的意思有点相反的意思(冒泡每次确定一个最大的数),所以每次遍历也不用遍历所有的元素,从i到n即可。
int[] arr=new int[]{3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};//定义一个用来测试的数组
int min_index,temp;
for (int i = 0; i < arr.length - 1; i++) {
min_index=i;//存取每次遍历的最小值的下标
for (int j = i+1; j < arr.length; j++) {//每次遍历仅需要从开始元素后面一位进行比较,且每次遍历都能确定一个开头元素,所以从i+1开始
if (arr[j]<arr[min_index]){
min_index=j;
}
}
temp=arr[i];
arr[i]=arr[min_index];//将最小元素与开始元素进行互换
arr[min_index]=temp;
}
插入排序(Insertion Sort)
插入排序的实现和选择排序相似,但是分阶段性的,在每次的遍历中取当前元素,然后依次向前比较,如果比自己大则将元素向后移,直到找到小于当前自己的元素,然后放其后面
int[] arr=new int[]{3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};//定义一个用来测试的数组
int preIndex,current;
for (int i=1;i< arr.length;i++){
preIndex=i-1;//记录前一个元素的下标
current=arr[i];//记录当前元素
while (preIndex>=0&¤t<arr[preIndex]){//如果到达头元素或者前一个元素比当前元素小则跳出循环
arr[preIndex+1]=arr[preIndex];//元素依次后移
preIndex--;
}
arr[preIndex+1]=current;//将当前元素插入到合适位置
}
希尔排序(Shell Sort)
希尔排序可以说是插入排序的优化版本,也可称之为分组的插入排序。我们将一列元素分为间隔为gap的若干组每一组都进行插入排序,然后再缩小组的间隔,继续进行插入排序,直到间隔为零,即能排列出这组元素
注意:这里虽然是插入排序的原理,但是只对组进行插入排序,其他元素不动
int[] arr=new int[]{3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};//定义一个用来测试的数组
for (int gap = (int) Math.floor(arr.length / 2); gap>0; gap= (int) Math.floor(gap/2)){//确定初始间隔,每次遍历缩小间隔,直到间隔为0
for (int i=gap;i<arr.length;i++){
int index=i;
int current=arr[i];
while (index-gap>=0&¤t<arr[index-gap])
arr[index]=arr[index-gap];
index-=gap;
}
arr[index]=current;
}
}
归并排序(Merge Sort)
归并排序体现了分治的思想,将一列元素进行切分,每次切分为一半,直到切分为两个为一组的元素,然后两两进行比较,小的放在前面,然后再由层往上进行比较,直到最后合为一组即排序完毕。
实现:使用递归的方法,依次细化,每层使用一个数组进行存储排好序的元素,最后用排好序的元素进行替换原数组的元素
public void mergeSort(int[] arr,int left,int right){//进行切分
if (left>=right) return;//临界条件
int mid=(left+right)>>>1;//取中间元素下标
mergeSort(arr,left,mid);//递归进行细化
mergeSort(arr,mid+1,right);
merge(arr,left,mid,right);
}
public void merge(int[] arr,int left,int mid,int right){//逐层进行排序
int s1=left,s2=mid+1;//根据中间数进行切分为左右两段,此处记录两段的起点
int[] ret=new int[right-left+1];//开辟一个数组存取每次排序的元素
int i=0;//记录新开辟的数组的下标
while (s1<=mid&&s2<=right){//当两段元素元素都不为空时
if (arr[s1]>arr[s2]){//比较两段元素的起点,将小的存入新开辟的数组,然后将起点后移一位
ret[i++]=arr[s2++];
}else {
ret[i++]=arr[s1++];
}
}
while (s1<=mid){//当第一段元素不为空第二段元素为空的时候
ret[i++]=arr[s1++];
}
while (s2<=right){//当第二段元素不为空第一段元素为空的时候
ret[i++]=arr[s2++];
}
for (int j=0;j< ret.length;j++){//将中间数组中排好序的元素存入原数组中
arr[left++]=ret[j];
}
}
下次有时间就更新剩下的几种排序
参照以下博客及视频,如有侵权,请联系删除!
[1]: https://www.cnblogs.com/onepixel/articles/7674659.html
[2]: https://www.bilibili.com/video/BV1Sv411B7F7?p=1