1.算法思想是什么
2.时间复杂度
3.稳定性
4.什么情况下适用?
基于比较的排序,已证明,基于比较的排序算法时间复杂度不会低于O(nlgn)最好的情况能达到这个下限,包括:插入排序/希尔排序/选择排序/堆排序/冒泡排序/归并排序/快速排序
不是基于比较的排序算法有望将时间复杂度降到O(nlgn)以下,适当的作为补偿,待排序的序列也必须有一定的规律,包括:计数排序/基数排序/桶排序
插入排序
算法思想:从数组的第二个元素开始遍历整个数组。针对每个元素,依次将其前面的所有元素从后向前和进行比较,大于它的元素均向后移动,最后将该元素插入。
时间复杂度:O(n^2)。最好情况下,已经有序O(n),最坏情况下逆序O(n^2)
稳定性:稳定,原址排序
适用场景:当数组已经基本有序时,使用插入排序能有效减少移动的次数,时间消耗最少。
希尔排序
算法思想:也属于插入排序,直接插入排序在当序列恰好为顺序时,时间消耗为O(n),因此若某个序列已基本有序,直接插入排序的效率就会提高,基于这个思想,通过比较相距一定间隔的元素来工作,各趟比较所用距离随着算法的进行而减小,直至只比较相邻元素的最后一趟排序,因此也称递减增量排序算法。
时间复杂度:对插入算法的改进,低于O(n^2),具体与选择的增量序列有关
稳定性:不稳定,原址排序
使用场景:时间复杂度和增量序列的联系紧密,好的增量序列才能保证有好的时间复杂度,使用较少。
选择排序
算法思想:从所有序列中先找到最小的,然后放到第一个位置,之后再看剩余元素中最小的,放到第二个位置……以此类推
时间复杂度:O(n^2)
稳定性:不稳定,原址排序
适用场景:理解简单,比较元素较少时都可以使用,因为要遍历整个数组,任何情况下性能都很差。
算法思想:也属于一种选择排序。由于一般的选择排序在寻找最大值时需要遍历数组,遍历数组的复杂度为O(n),因此造成了时间的浪费,如若将待排序的数组进行一系列整理,例如将其整理成有特点的堆这种数据结构,由于其删除最大值的复杂度仅仅为O(lgn),那么我们有理由相信,能将选择排序的时间复杂度降低到O(nlgn)
时间复杂度:O(nlgn)
稳定性:不稳定,原址排序
适用场景:没有特定的场景,只是没有快速排序用的多。
算法思想:从第一个元素开始相邻的两个元素两两比较,按照小数在上大数在下的规则交换,一趟下去大数沉底。再从第一个元素开始两两比较相邻两个元素,直到倒数第二个元素....
时间复杂度:O(n^2),改进后再最好情况下达到O(n)
稳定性:不稳定,原址排序
适用场景:容易理解,比较元素较少时都可以使用。
归并排序
算法思想:分治思想,将数组分成两部分,如果这两部分均有序,那么便可在O(n)的时间内合并成一个完整的有序数组。由此,将区间划分下去,直到每个区间只有一个元素,即可认为已经有序,然后两两合并,而合并两个有序数组只需要O(n)的复杂度。
时间复杂度:O(nlgn)
稳定性:稳定,需要额外辅助空间
适用场景:同复杂度的的情况下可选,更多的用在外排序中。
算法思想:分治思想,和归并排序相比,归并排序主要工作在于合并操作,而快速排序在于划分。划分数组为两部分,左边部分小于中间的值,右边部分大于中间的值,然后递归的对左右两边进行快速排序,这里,对数组的划分只需要O(n)的复杂度.
时间复杂度:O(nlgn),最差情况划分为1,n-1,此时复杂度为O(n^2)其他情况均为O(nlgn),期望为O(nlgn)
稳定性:不稳定,原址排序
适用场景:顾名思义,使用当然是最多的,整体情况下是最快的。
public class paixu {
/*
* 插入排序 第二个与前一个比较 第三个与前两个比较 第四个与前三个比较
* 正序时时间复杂度为O(n),这时最好的情况。反序时,故时间复杂度为O(n2)*/
public static void charusort(int [] arr){
for(int i=0;i<arr.length-1;i++)
for(int j=0;j<=i;j++){
if(arr[i+1]<arr[j])
{ int s=arr[j];
arr[j]=arr[i+1];
arr[i+1]=s;
}
}
}
/*
* 希尔排序 分组和插入排序相结合
* 基本思想:取一个小于n的整数d1=N/2作为第一个增量,把文件的全部记录分成d1个组。
* 所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;
* 然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),
* 即所有记录放在同一组中进行直接插入排序为止。该方法实质上是一种分组插入方法。
*
*
* 所以希尔排序是不稳定的。
希尔排序的时间性能优于直接插入排序, 希尔排序的平均时间复杂度为O(nlogn)*/
public static void shellsort(int []arr){
int d=arr.length;
while(true){
d=d/2;
for(int x=0;x<d;x++){
for(int i=0;i<arr.length-d;i=i+d)
for(int j=0;j<=i;j=j+d){
if(arr[i+d]<arr[j])
{ int s=arr[j];
arr[j]=arr[i+d];
arr[i+d]=s;
}
}
}if(d == 1){
break;
}
}
}
/*
* 选择排序 选出最小的和第一个交换 和第二个交换 第三个交换
* 简单选择排序是不稳定的排序。
时间复杂度:T(n)=O(n2)。*/
public static void selectsort(int []arr){
for(int i=0;i<arr.length;i++){
int min=arr[i];
int n=i;
for(int j=i+1;j<arr.length;j++){
if(arr[j]<min){ //找出最小的数
min = arr[j];
n = j;
}
}
arr[n] = arr[i];
arr[i] = min;
}
}
public static void bubblesort(int []arr){
for(int i=0;i<arr.length;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;
}
}
}
/*快速排序
* */
public static void quick(int []arr){
quickSort(arr,0,arr.length-1);
}
private static void quickSort(int[] a, int low, int high) {
if(low<high){ //如果不加这个判断递归会无法退出导致堆栈溢出异常
int middle = getMiddle(a,low,high);
quickSort(a, 0, middle-1);
quickSort(a, middle+1, high);
}
}
private static int getMiddle(int[] a, int low, int high) {
int temp = a[low];//基准元素
while(low<high){
//找到比基准元素小的元素位置
while(low<high && a[high]>=temp){
high--;
}
a[low] = a[high];
while(low<high && a[low]<=temp){
low++;
}
a[high] = a[low];
}
a[low] = temp;
return low;
}
//归并排序
public static void gunbin(int []arr){
mergesort(arr,0,arr.length-1);
}
private static void mergesort(int[] arr, int i, int j) {
if(i<j){ int middle = (i+j)/2;
mergesort(arr,0,middle);
mergesort(arr,middle+1,j);
hebinsort(arr,i,middle,j);
}
}
private static void hebinsort(int[] arr, int i, int middle, int j) {
int [] brr=new int [arr.length];
int mid=middle+1;
int tmp = i;
int third = i;
while(i<=middle&&mid<=j){
if(arr[i]<arr[mid]){
brr[third++]=arr[i++];}
else {
brr[third++]=arr[mid++];
}
}
while(i<=middle){
brr[third++]=arr[i++];
}
while(mid<=j){
brr[third++]=arr[mid++];
}
while(tmp<=j){
arr[tmp] = brr[tmp++];
}
}
/**
* @param args
*/
public static void main(String[] args) {
int[] a={49,38,65,97,76,13,27,49,78,34,12,64,1};
gunbin(a);
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
}
}