八大排序算法总结

  1. 过程:

选择排序

  1. **平均时间复杂度:**O(n2)

  2. java代码实现:

public static void select_sort(int array[],int lenth){

for(int i=0;i<lenth-1;i++){

int minIndex = i;

for(int j=i+1;j<lenth;j++){

if(array[j]<array[minIndex]){

minIndex = j;

}

}

if(minIndex != i){

int temp = array[i];

array[i] = array[minIndex];

array[minIndex] = temp;

}

}

}

三. 插入排序(Insertion Sort)


  1. 基本思想:

在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

  1. 过程:

插入排序

相同的场景

  1. **平均时间复杂度:**O(n2)

  2. java代码实现:

public static void insert_sort(int array[],int lenth){

int temp;

for(int i=0;i<lenth-1;i++){

for(int j=i+1;j>0;j–){

if(array[j] < array[j-1]){

temp = array[j-1];

array[j-1] = array[j];

array[j] = temp;

}else{ //不需要交换

break;

}

}

}

}

四. 希尔排序(Shell Sort)


  1. 前言:

数据序列1: 13-17-20-42-28 利用插入排序,13-17-20-28-42. Number of swap:1;

数据序列2: 13-17-20-42-14 利用插入排序,13-14-17-20-42. Number of swap:3;

如果数据序列基本有序,使用插入排序会更加高效。

  1. 基本思想:

在要排序的一组数中,根据某一增量分为若干子序列,并对子序列分别进行插入排序。

然后逐渐将增量减小,并重复上述过程。直至增量为1,此时数据序列基本有序,最后进行插入排序。

  1. 过程:

希尔排序

  1. 平均时间复杂度:

  2. java代码实现:

public static void shell_sort(int array[],int lenth){

int temp = 0;

int incre = lenth;

while(true){

incre = incre/2;

for(int k = 0;k<incre;k++){ //根据增量分为若干子序列

for(int i=k+incre;i<lenth;i+=incre){

for(int j=i;j>k;j-=incre){

if(array[j]<array[j-incre]){

temp = array[j-incre];

array[j-incre] = array[j];

array[j] = temp;

}else{

break;

}

}

}

}

if(incre == 1){

break;

}

}

}

五. 快速排序(Quicksort)


  1. 基本思想:(分治)
  • 先从数列中取出一个数作为key值;

  • 将比这个数小的数全部放在它的左边,大于或等于它的数全部放在它的右边;

  • 对左右两个小数列重复第二步,直至各区间只有1个数。

  1. 辅助理解:挖坑填数
  • 初始时 i = 0; j = 9; key=72

由于已经将a[0]中的数保存到key中,可以理解成在数组a[0]上挖了个坑,可以将其它数据填充到这来。

从j开始向前找一个比key小的数。当j=8,符合条件,a[0] = a[8] ; i++ ; 将a[8]挖出再填到上一个坑a[0]中。

这样一个坑a[0]就被搞定了,但又形成了一个新坑a[8],这怎么办了?简单,再找数字来填a[8]这个坑。

这次从i开始向后找一个大于key的数,当i=3,符合条件,a[8] = a[3] ; j-- ; 将a[3]挖出再填到上一个坑中。

数组:72 - 6 - 57 - 88 - 60 - 42 - 83 - 73 - 48 - 85

0 1 2 3 4 5 6 7 8 9

  • 此时 i = 3; j = 7; key=72

再重复上面的步骤,先从后向前找,再从前向后找。

从j开始向前找,当j=5,符合条件,将a[5]挖出填到上一个坑中,a[3] = a[5]; i++;

从i开始向后找,当i=5时,由于i==j退出。

此时,i = j = 5,而a[5]刚好又是上次挖的坑,因此将key填入a[5]。

数组:48 - 6 - 57 - 88 - 60 - 42 - 83 - 73 - 88 - 85

0 1 2 3 4 5 6 7 8 9

  • 可以看出a[5]前面的数字都小于它,a[5]后面的数字都大于它。因此再对a[0…4]和a[6…9]这二个子区间重复上述步骤就可以了。

数组:48 - 6 - 57 - 42 - 60 - 72 - 83 - 73 - 88 - 85

0 1 2 3 4 5 6 7 8 9

  1. **平均时间复杂度:**O(N*logN)

  2. 代码实现:

public static void quickSort(int a[],int l,int r){

if(l>=r)

return;

int i = l; int j = r; int key = a[l];//选择第一个数为key

while(i<j){

while(i<j && a[j]>=key)//从右向左找第一个小于key的值

j–;

if(i<j){

a[i] = a[j];

i++;

}

while(i<j && a[i]<key)//从左向右找第一个大于key的值

i++;

if(i<j){

a[j] = a[i];

j–;

}

}

//i == j

a[i] = key;

quickSort(a, l, i-1);//递归调用

quickSort(a, i+1, r);//递归调用

}

key值的选取可以有多种形式,例如中间数或者随机数,分别会对算法的复杂度产生不同的影响。

六. 归并排序(Merge Sort)


  1. 基本思想:参考

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用。

首先考虑下如何将2个有序数列合并。这个非常简单,只要从比较2个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。

//将有序数组a[]和b[]合并到c[]中

void MemeryArray(int a[], int n, int b[], int m, int c[])

{

int i, j, k;

i = j = k = 0;

while (i < n && j < m)

{

if (a[i] < b[j])

c[k++] = a[i++];

else

c[k++] = b[j++];

}

while (i < n)

c[k++] = a[i++];

while (j < m)

c[k++] = b[j++];

}

解决了上面的合并有序数列问题,再来看归并排序,其的基本思路就是将数组分成2组A,B,如果这2组组内的数据都是有序的,那么就可以很方便的将这2组数据进行排序。如何让这2组组内数据有序了?

可以将A,B组各自再分成2组。依次类推,当分出来的小组只有1个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的2个小组就可以了。这样通过先递归的分解数列再合并数列就完成了归并排序。

  1. 过程:

归并排序

  1. **平均时间复杂度:**O(NlogN)

归并排序的效率是比较高的,设数列长为N,将数列分开成小数列一共要logN步,每步都是一个合并有序数列的过程,时间复杂度可以记为O(N),故一共为O(N*logN)。

  1. 代码实现:

public static void merge_sort(int a[],int first,int last,int temp[]){

if(first < last){

int middle = (first + last)/2;

merge_sort(a,first,middle,temp);//左半部分排好序

merge_sort(a,middle+1,last,temp);//右半部分排好序

mergeArray(a,first,middle,last,temp); //合并左右部分

}

}

//合并 :将两个序列a[first-middle],a[middle+1-end]合并

public static void mergeArray(int a[],int first,int middle,int end,int temp[]){

int i = first;

int m = middle;

int j = middle+1;

int n = end;

int k = 0;

while(i<=m && j<=n){

if(a[i] <= a[j]){

temp[k] = a[i];

k++;

i++;

}else{

temp[k] = a[j];

k++;

j++;

}

}

while(i<=m){

temp[k] = a[i];

k++;

i++;

}

while(j<=n){

temp[k] = a[j];

k++;

j++;

}

for(int ii=0;ii<k;ii++){

a[first + ii] = temp[ii];

}

}

七. 堆排序(HeapSort)


  1. 基本思想:

  1. ** 图示:** (88,85,83,73,72,60,57,48,42,6)

Heap Sort

  1. **平均时间复杂度:**O(NlogN)

由于每次重新恢复堆的时间复杂度为O(logN),共N - 1次重新恢复堆操作,再加上前面建立堆时N / 2次向下调整,每次调整时间复杂度也为O(logN)。二次操作时间相加还是O(N * logN)。

  1. java代码实现:

//构建最小堆

public static void MakeMinHeap(int a[], int n){

for(int i=(n-1)/2 ; i>=0 ; i–){

MinHeapFixdown(a,i,n);

}

}

//从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2i+1, 2i+2

public static void MinHeapFixdown(int a[],int i,int n){

int j = 2*i+1; //子节点

int temp = 0;

while(j<n){

//在左右子节点中寻找最小的

if(j+1<n && a[j+1]<a[j]){

j++;

}

if(a[i] <= a[j])

break;

//较大节点下移

temp = a[i];

a[i] = a[j];

a[j] = temp;

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
++;

}

if(a[i] <= a[j])

break;

//较大节点下移

temp = a[i];

a[i] = a[j];

a[j] = temp;

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-eOHTYDml-1715085444695)]

[外链图片转存中…(img-XqLCiO0L-1715085444696)]

[外链图片转存中…(img-yQFHUemX-1715085444696)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值