前端时间考研,复习了不少基础算法,决定趁这个机会总结一下,近期我会把常用的八大排序算法都总结到,算是对自己前段时间的总结:排序算法按排序方式可分为交换排序,选择排序,插入排序和归并排序,基数排序,现在先来介绍交换排序:
交换排序是指通过交换元素位置来实现算法的排序:最典型的就是冒泡排序和快速排序,下面分别讲解这两种算法:
冒泡排序:
算法思想:通过从前往后或者从后往前两两比较相邻元素的值,逐级把最大的元素或者最小的元素给甄选出来,结果将最小(大)的元素交换至待排序列的第一个位置,下一趟冒泡时,已经确定的元素不在参与比较。
稳定性:稳定
时空复杂度与初始状态是否有关:是
时间复杂度:
最好情况O(n)——元素已经有序,排序时只需比较n-1次,无须移动元素
最坏情况O(n^2) ——元素逆序 ,排序时比较次数为n(n-1)/2, 移动次数为:3n(n-1)/2
平均情况O(n^2)
下面是java实现的代码:
public class Main {
public static void main(String[] args) {
int []a={4,9,2,7,1,8,9,5,3};
BubbleSort(a);//传入的是引用
print(a);
}
public static void BubbleSort(int [] target){
int length=target.length;
for(int i=0;itarget[j+1]){//一趟排序确定一个最大元素,当然也可以是确定最小的元素,不过要改for循环从后往前遍历
int temp=target[j];
target[j]=target[j+1];
target[j+1]=temp;
changeFlag=true;
}
}
if(changeFlag==false)return ;//若没交换,则说明元素已经有序
}
return ;
}
public static void print(int []target){
for(int i=0;i
算法思想:这个基本思想是基于分治法的:在待排序表中任取一元素pivot作为基准,然后通过一趟排序将排序表划分为大于等于privot元素和小于privot元素的两个部分,将privot放在两部分中间的位置上,这个位置就是其在这个表上的最终位置,这个过程称为一趟快速排序,也就是说每一次快速排序,都会确定一个元素的最终位置。而后分别递归的对这两部分重复上述过程,直到每部分都只有一个元素或为空为止,这样元素都放在了其最终的位置上。这样说每个人应该都能看懂,可是实际操作起来,就发现没那么简单,因为我们并不能把元素都取出分为一个一个的,然后把小的放在privot左边,大的放在privot'右边,因为数组中的地址是固定不变的,我们能做的只是寻找出privot在数组中的位置,然后将privot放入其中就好,因此这个算法的重点是找到privot的位置。
稳定性:不稳定
时空复杂度与初始状态是否有关:是
时间复杂度:与划分是否对称有关,即取到的privot值是否能将表划分为两部分等长的元素
最好情况O(nlog2^n) ——每次划分均等分
最坏情况O(n^2)——初始排序已基本有序或逆序
空间复杂度:就是额外需要用到的空间,本算法就是递归用到的栈的深度
最好情况:O(log2^n)
最坏情况:O(n)
java实现的代码:
public class Main {
public static void main(String[] args) {
int []a={4,9,2,7,1,8,9,5,3};
quickSort(a,0,a.length-1);
print(a);
}
public static void quickSort(int []a,int low,int high){
if(lowhigh
int middle=getMiddle(a,low,high);
quickSort(a,low,middle-1);
quickSort(a,middle+1,high);
}
}
public static int getMiddle(int []a,int low,int high){//划分函数
int privot=a[low];//一般取数组中第一个元素作为基准,用privot保存基准值,数组中空出一个空位
while(low=privot)high--;//先从后往前遍历寻找到比privot小的值
a[low]=a[high];//将比privot小的值放入基准的位置,这时又空出一个空位
while(low