没有合适的资源?快使用搜索试试~ 我知道了~
首页八大排序算法总结(含代码)
八大排序算法总结(含代码)
需积分: 50 320 浏览量
更新于2023-05-26
评论 1
收藏 554KB PDF 举报
不稳定的排序算法:快速排序、希尔排序、堆排序、选择排序(简简记记::快快些些选选堆堆) 所需辅助空间最多:归并排序 所需辅助空间最少:堆排序 平均速度最快:快速排序 当n较大,则应采用时间复杂度为O(nlogn)的排序方法:快速排序、堆排序或归并排序。 时间复杂度:冒泡排序=选择排序=插入排序=O(N的平方);其他都是O(NlogN),但是并不是绝对的。 详细内容请见文档。
资源详情
资源评论
资源推荐

八大排序算法八大排序算法
不稳定的排序算法:快速排序、希尔排序、堆排序、选择排序(简记:快些选堆简记:快些选堆 )
所需辅助空间最多:归并排序
所需辅助空间最少:堆排序
平均速度最快:快速排序
当n较大,则应采用时间复杂度为O(nlogn)的排序方法:快速排序、堆排序或归并排序。
时间复杂度:冒泡排序=选择排序=插入排序=O(N的平方);其他都是O(NlogN),但是并不是绝对的。
1.冒泡排序冒泡排序
原理:由大到小排序--相邻两个元素进行比较,大的元素放左边,小的元素放右边,一轮循环后,最小的元素在最右边。
稳定排序算法:能保证排序前后,稳定排序算法:能保证排序前后,2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同
实现
// 冒泡排序--由大到小
public static void bubbleSort(int[] arr) {
for (int i = 0; i < arr.length-1; i++) {

for (int j = 1; j < arr.length - i; j++) {
if (arr[j-1] < arr[j]) {
int temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
}
}
}
}
时间复杂度:O(N的平方),较慢,稳定算法,最坏情况和最好情况都是一样的复杂度
2.选择排序选择排序(直接排序直接排序)
原理:使用索引为0的元素与其他的元素比较,如果有比索引0大的元素,则记录该元素下标,一轮比较完成后,下标值是最大
值,然后进行一次比较,通过一轮循环,最大的元素在索引为0的位置。然后使用索引为1的元素和其余元素进行比较,依次循
环。
比较次数和冒泡一样,但是交换次数变少。每一轮循环只交换一次。
选择排序对冒泡排序进行了改进,将元素的交换次数从O(N的平方)降为O(N),但是比较次数没有变化,依然是O(N的平方)。
它与冒泡排序的比较次数相同,但选择排序的交换次数少于冒泡排序。冒泡排序是在每次比较之后,若比较的两个元素顺序与
待排序顺序相反,则要进行交换,而选择排序在每次遍历过程中只记录下来最小的一个元素的下标,待全部比较结束之后,将
最小的元素与未排序的那部分序列的最前面一个元素交换,这样就降低了交换的次数,提高了排序效率。
实现
#
// 选择排序(直接排序)--从大到小排序
public static void selectSort(int[] arr) {
//每次循环,比较次数和冒泡一样,但是只交换一次,提高效率
for (int i = 0; i < arr.length-1; i++) {
int lowIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[lowIndex] < arr[j]) {
lowIndex = j;
}
}
// 将当前第一个元素与它后面序列中的最大的元素交换,也就是将最大的元素放在最前端
int temp = arr[i];
arr[i] = arr[lowIndex];
arr[lowIndex] = temp;
}
}
时间复杂度:O(N的平方),不稳定算法,最坏情况和最好情况都是一样的复杂度
3.插入排序插入排序
原理:非常类似于平时打牌时候插入牌的过程。开始摸牌时,我们的左手是空的,接着一次从桌上摸起一张牌,并将它插入到
左手的正确位置,为了找到这张牌的正确位置,要将它与手中已有的牌从左到右进行比较,无论什么时候手中的牌都是排序好
的。
分析:对于一个给定要排序的数组,以大牌来分析,当摸第一张牌时候(下标为0的元素),不用排序,直接插入;当摸第二张牌
时候(下标为1的元素),将这张牌和第一张牌进行比较,如果更大,则将第1张牌右移一个位置,也就是第一张牌现在空了一
个位置出来,然后第二张牌插入到右边,这样就完成了目前所有牌的排序了,后面每次来一张牌都要和已排序的牌进行比较,
然后原来的牌要空出一个位置让新来的牌有位置插入。
插入排序法的排序思想就是从数组的第二个元素开始,将数组中的每一个元素按照规则插入到已排好序的数组中以达到排序的目
的.一般情况下将数组的第一个元素作为起始元素,从第二个元素开始依次插入.由于要插入到的数组是已经排好序的,所以只是要
从右向左找到比插入点小(对升序而言)的第一个数组元素就插入到其后面.直到将最后一个数组元素插入到数组中,整个排序过程
就算完成。

不管何种排序方式,查找比较规则都是从右到左
一般情况下, 该算法比冒泡排序快一倍,比选择排序要快一些
对于有序或者基本有序的数据,插入排序非常快,可以达到O(N)
如果数据是逆序的,那么插入排序比冒泡排序还慢
实现
#
//插入排序--由大到小
public static void insertSort(int[] arr){
int j;
int key;
for (int i = 1; i < arr.length; i++) {
key=arr[i];//key就是我们每次新摸到的牌,现在需要找到插入的位置并空出位置
j=i-1;
while (j>=0 && arr[j]<key) {//将已排好序的所有比key小的元素右移一个位置,空出一个位置,方便key插入
arr[j+1]=arr[j];
j--;
}
arr[j+1]=key;//空出位置后,然后插入
}
}
时间复杂度:O(N的平方),稳定算法
就上面三种算法比较的话,插入排序是最好的,适合小数据量。
以上三种称为简单排序算法
最优复杂度:当输入数组就是排好序的时候,复杂度为O(n),而快速排序在这种情况下会产生O(n^2)的复杂度
最差复杂度:当输入数组为倒序时,复杂度为O(n^2)
插入排序比较适合用于“少量元素的数组”
4.希尔排序希尔排序
原理:是基于插入排序的改进算法,插入排序每次移动都是一个一个移动,当逆序时候,移动次数要很多,希尔排序改进了移
动步长,可以实现大跨度移动,减少移动时间。希尔排序也叫做缩小增量排序法
将整个无序数据分割成若干小的子序列分别进行插入排序
在希尔排序开始时增量较大,分组较多,每组的记录数目少,故各组内直接插入较快,后来增量di逐渐缩小,分组数逐渐减少,
而各组的记录数目逐渐增多,但由于已经按di-1作为距离排序,使文件较接近于有序状态,所以新的一趟排序过程也较快。
在插入算法中,如果有一个最小的数在数组的最后面,用插入算法就会从最后一个位置移动到第一个,这样就会浪费很大,使
用这个改进的希尔排序可以实现数据元素的大跨度的移动。也就是这个算法的优越之处。
先取一个小于n的整数d1作为一个增量,把表的全部记录分成d1个组,所有距离为d1的倍数的记录放在同一个组中,在各组内
进行直接插入排序,然后,取第二个增量d2(<d1),重复上述的分组和排序,直至所取的dt=1,即所有记录放在同一组中进行直接
插入排序为止。
举例:要排序的数组是[3 5 4 12 45 3 -32 7 5 8 34 -4],长度为12,首先确定最大增量,增量的值选取对运行效率影响很大,这里
面有很多间隔划分算法。我们这里选择的增量为长度/2,这里=6,故开始分组 每隔6个元素一组,分组如下:第一组【3 -32】
第二组【5 7】第三组【4 5】第四组【12 8】第五组【45 34】 第六组【3 -4】,然后对每一组进行插入排序,从大到小,经过
第一次排序后,变为【3 7 5 12 45 3 -32 5 4 8 34 -4】,然后再次修改增量,这次增量要缩小,我们再次是上次增量/2=3;然后
开始第二次分组:第一组【3 12 -32 8】第二组【7 45 5 34】第三组【5 3 4 -4】,然后对每组使用插入排序,排序后合成,则
数组变为【12 45 5 8 34 4 3 7 3 -32 5 -4】,从这里可以看出,已经基本有序了。最后增量/2=1;表示不需要再分组了,对上述数
据进行一次插入排序即可。
实现
//希尔排序--由大到小
public static void shellSort(int[] arr) {
int size = arr.length;
//这层for是分组
for(int gap = size/2; gap>=1; gap /= 2) {
//这层for是对每组进行插入排序
for(int i=gap; i<size; i++) {
剩余11页未读,继续阅读
















安全验证
文档复制为VIP权益,开通VIP直接复制

评论0