自己总结的一些java实现的排序算法,如果有不合适的地方,欢迎指出,希望大家不吝赐教~~感谢感谢各位同学
java中常用的排序算法分为以下四类:
①插入排序:直接插入排序,希尔排序为代表
②交换排序:冒泡排序,快速排序为代表
③选择排序:简单选择排序,堆排序为代表
④归并排序:归并排序为代表
第一类:插入排序
排序思想:
给定一个长度为6的无序数组,arr = [3,5,2,3,5,1]。我们对这个数组进行排序,我们假设arr[0]是排好序的,我们从arr[1]开始看元素,arr[1]=5,5比3大,那么我们看下一位,arr[2]=2,2比5小,那么我们此时将5往后放置,放在arr[2]的位置,然后我们用2和arr[0]比,发现2比3小,那么我们继续把3也往后放置一位,此时发现前面没有元素可以和2进行比较,那么就把2放在当前位置,这一轮排序下来,现在的arr=[2,3,5,3,5,1]。我们这样进行比较,直到把arr[length-1]也放在了正确的位置上。排序到此结束。
我的实现代码(可能有弊端,若有错误请不吝赐教)
-------直接插入排序:
/**
* @param arr 给定数组
* @param step 元素比较的间隔,直接插入排序step默认为1
* @return
*/
//方法:直接插入排序
public int[] insertSort(int[] arr,int step){
int start = step; //赋值:选定开始遍历的位置,将开始的位置设置为step的值
//判断:如果数组长度小于2,直接返回原数组
if(arr.length<2)
return arr;
/*
*循环:
* ①从start开始遍历,与距离为step的前一个数组进行比较大小
* ②如果小于前值,那么将前元素后移step个长度。否则,跳出当前这次循环,进行下次遍历
* ③当start遍历到start=arr.length停止循环
*/
for(int j = start;j<arr.length;j++){
int value = arr[j]; //赋值:保留当前循环的元素value
int i = j-step; //赋值:计算出距离为step的前一个数,并且i应该大于等于0,否则无意义
//循环:直接插入逻辑,指针每次递减step
for(;i>=0&&arr[i]>value;i-=step){
arr[i+step] = arr[i];
}
arr[i+step] = value; //赋值:将当前循环的元素value赋值给当前指针的位置
}
return arr; //返回:返回结果数组
}
思考:
我们实现之后需要思考,完成的这个代码虽然可以实现我们的排序要求,但是当前代码花费的时间以及空间又是如何呢。在工作中也是如此,当任务完成后,我们需要回过头看看我们的想法所使用的资源情况,这样才可以在下一次做的更好。当然了我觉得done is better than perfect。只有实现之后才有去优化的价值。下面我们看下这段代码的时间以及空间复杂度,还有我们不经常谈起的稳定性。
时间复杂度分析:
-----可以看到代码里面我们使用了两个for循环,每次循环n次,那么我们分析,①若数组有序,我们依旧需要循环nn次。②若数组无序,我们还是要循环nn次。所以这段代码最好和最坏的时间复杂度都是O(n^2)。
空间复杂度分析:
-----有上述代码我们可以看到,自始至终我们基本上都是在原数组中进行操作,唯一创建的变量是value ,用来存储当前循环的元素value。所以我们的空间复杂度是O(1)。
排序是否稳定:
-----我们可以看到,元素每次和之前一位进行比较,如果我们数组中元素为[1,1,2,3,4,5]。当从arr[1]开始遍历,和前一位arr[0]进行比较,因为1和1是相等的(为了避免分不清哪个1,我们这里将arr[0]叫做1+,arr[1]叫做1-),所以1+和1-并不会交换顺序。等到排序完成后,其实1+也是在1-前面的。那么可以证明,我们的代码是稳定排序。