基础排序算法总结

一、冒泡排序

思想:n个数循环比较找出最大(或最小)的值,再重复比较在剩下的数中找到最大值

代码:

    public static void BubbleSort(int[] numbers){

     int temp;

     int k=numbers.length;

     boolean didSwap;

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

     didSwap=false;     //当一轮都没交换说明已排好序

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

     if(numbers[j]>numbers[j+1]){

     temp=numbers[j];

     numbers[j]=numbers[j+1];

     numbers[j+1]=temp;

     didSwap=true;

     }

     }

     if(didSwap==false)

     return;

     }

}

    时间复杂度    最优 | O(n)  最坏| n(n-1)/2——>O(n2)

空间复杂度    O(1)

二、选择排序

思想:n个数循环比较找出最大(或最小)的值,再重复比较在剩下的数中找到最大值,比较的次数与冒泡一样,减少了交换的次数。

代码:

    public static void SelectSort(int[] numbers){

     for(int i=0,len=numbers.length-1;i<len;i++){         

     int min=numbers[0],min_id=0;

     for(int j=i;j<numbers.length;j++){

     if(min>numbers[j]){

     min=numbers[j];

     min_id=j;

     }

     }

     numbers[min_id]=numbers[i];

     numbers[i]=min;

     }

}

时间复杂度    n(n-1)/2——>O(n2)

空间复杂度    O(1)

三、插入排序

    思想:每次循环比较将一个数插入一个有序的序列中(一个即有序),从第二个数开始比较。

    代码:

    public static void InsertSort(int[] numbers){        

     for(int i=0;i<numbers.length;i++){         

     int currentNumber=numbers[i];            

     int j=i-1;                            

     while(j>=0&&numbers[j]>currentNumber){ //中断条件时期优于冒泡,中断期望为length/2,所以比冒泡块1倍 

     numbers[j+1]=numbers[j];           

     j--;                               

     }                                      

     numbers[j+1]=currentNumber;             

     }

}

时间复杂度   最优 | O(n)  最糟|n*(n-1)/2——>O(n2)

空间复杂度    O(1)

四、希尔排序

思想:根据插入算法每次自能移动一位的缺点,添加了个间隔值dk(=length/2),每轮比较将相隔dk的数据放在一组进行直接插入排序,在缩小dk重复循环,直至dk为1。

代码:

    public static void ShellSort(int[] numbers){

     int dk=numbers.length/2;

     while(dk>=1){

     ShellInsertSort(numbers,dk);       //log2n

     dk=dk/2;

     }

    }

    

    public static void ShellInsertSort(int[] numbers,int dk){

     for(int i=dk;i<numbers.length;i++){    //所有相隔dk的组合

     if(numbers[i]<numbers[i-dk]){     //对每一种组合进行直接插入排序

     int x=numbers[i];

     int j=i-dk;

     do{

     numbers[j+dk]=numbers[j];

     j=j-dk;

     }

     while(j>0&&numbers[j]>x);

     numbers[j+dk]=x;

     }

    

     }

}

时间复杂度    O(nlog2n)

空间复杂度    O(n)

五、归并排序

    思想:分治思想+将两个有序的序列合并。先将数组循环二分,直至一组数据只有一个,在开始向上合并。

    代码:

    public static void sort(int[] numbers){

     sort(numbers,0,numbers.length);

    }

    public static void sort(int[] numbers,int pos,int end){

     if(end-pos>1){                                     

     int mid=(end+pos)/2;

     sort(numbers,pos,mid);

     sort(numbers,mid,end);

     MergeSort(numbers,pos,mid,end);              //log2n次

     }

    }

    public static void MergeSort(int[] numbers,int pos,int mid,int end){     int len1=mid-pos,len2=end-mid;

     int[] array1=new int[len1];     ß

     int[] array2=new int[len2];     ß

     System.arraycopy(numbers, pos, array1, 0, len1);

     System.arraycopy(numbers, mid, array2, 0, len2);

     for(int i=pos,j=0,k=0;i<end;i++){

     if(j==len1){

     System.arraycopy(array2, k, numbers, i, len2-k);break;

     }

     if(k==len2){

     System.arraycopy(array1, j, numbers, i, len1-j);break;

     }

     if(array1[j]<=array2[k]){

     numbers[i]=array1[j++];

     }

     else{

     numbers[i]=array2[k++];

     }

     }

    }

时间复杂度   O(n*log2n)

    空间复杂度   O(n)---->上面代码的空间复杂度为nlog2n,可以在递归之前申请n的数组

    替代上面红色箭头所指的代码即可降低空间复杂度为O(n)

六、快速排序

    思想:分治—>设置哨兵,将比哨兵大的数据分一边,小的分到一边,再递归重复。

    代码:

    public static  void quickSort(int[] a,int left,int right){

     if(left<right){

     int key=a[left];      //哨兵

     int low=left;

     int high=right;

     while(low<high){

     while(low<high&&a[high]>key){

     high--;

     }

     if(low<high)

         a[low++]=a[high];

     while(low<high&&a[low]<key){

     low++;

     }

     if(low<high)

         a[high--]=a[low];

     }

     a[low]=key;

     quickSort(a,left,low-1);

     quickSort(a,low+1,right);

     }

    }

    时间复杂度    最优|O(nlog2n)   最糟|O(n2)

    空间复杂度    最优|O(log2n)    最糟|O(n)

七、堆排序

    思想:先将数据初始化为大堆顶(或小堆顶)的二叉树,然后每轮取出堆顶,再将最后一个支点赋给堆顶。大堆顶被破坏,在循环调整得到大堆顶,如此循环直至得到有序的序列。

代码:

    public static void HeapSort(int[] numbers,int length){

     BuildingHeap(numbers,length);

     int len=numbers.length;

     for(int i=len-1;i>=0;i--){

     int temp=numbers[i];numbers[i]=numbers[0];numbers[0]=temp;

      HeapAdjust(numbers,0,i);

     }

    }

    public static void BuildingHeap(int[] numbers,int length){

     for(int i=length/2;i>0;i--){

     HeapAdjust(numbers,i-1,length);

     }

    }

    public static void HeapAdjust(int[] numbers,int s,int length){

     int tmp=numbers[s];

     int child=2*s+1;

     while(child<length){

     if(child+1<length&&numbers[child]<numbers[child+1]){

     ++child;

     }

     if(numbers[s]<numbers[child]){

     numbers[s]=numbers[child];

     s=child;

     child=2*s+1;

     }else{

     break;

     }

     numbers[s]=tmp;

     }

    }

    时间复杂度   nlog2n

    空间复杂度   o(1)

八、桶排序

    思想:对于均匀分布的序列排序很好,将n个数据格局其值域分到m个组里,再讲各个组用其它排序对其排序。

posted @ 2017-12-11 23:13  共祝愿  阅读(140)  评论(0编辑  收藏  举报