常用排序算法总结

1.插入排序
1.1 直接插入排序
public static void insertSort(int[] a){
for(int i=1; i<a.length; i++){//从头部第一个开始当做已经排好序了,把后面的数逐个插入到前面;
int j;
int x = a[i]; //x为待插入的元素
        for(j=i; j>0 && x<a[j-1]; j--){
        a[j] = a[j-1]  //通过循环,把较大的数后移
        }
        a[j] = x;//插入
}
}
时间复杂度O(n^2)


1.2 希尔排序
public static void shellSort(int[] a){
int step = a.length / 2;
while(step>=1){
        for(int i=step; i<a.length; i++){
        int j;
        int temp = a[i];
        for(j=i-step; j>=0 && temp<a[j]; j-=step){
        a[j+step] = a[j];
        }
        a[j+step] = temp;
        }
        step = step / 2;
}
}
希尔排序的关键并不是随便分组后各自排序,而是将相隔某个“增量”的记录组成一个子序列,实现跳跃式移动,使得排序的效率提高。需要注意的是,增量序列的最后一个增量值必须等于1才行。另外,由于记录是跳跃式的移动,希尔排序并不是一种稳定的排序算法。 
希尔排序最好时间复杂度和平均时间复杂度都是O(nlogn),最坏时间复杂度为O(n^2)
参考:http://blog.csdn.net/jianyuerensheng/article/details/51258460

2.选择排序
public void selectSort(int[] arr){
for(int i=0; i<arr.length-1; i++){
for(int j=i; j<arr.length; j++){
if(a[i]>a[j]){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
}


特点:效率低,容易实现。 
思想:每一趟从待排序序列选择一个最小的元素放到已排好序序列的末尾,剩下的位待排序序列,重复上述步骤直到完成排序。复杂度O(n^2)


3.冒泡排序
特点:效率低,实现简单 
思想(从小到大排):每一趟将待排序序列中最大元素移到最后,剩下的为新的待排序序列,重复上述步骤直到排完所有元素。这只是冒泡排序的一种,当然也可以从后往前排。
复杂度为O(n^2)
public void bubbleSort(int[] arr){
   for(int i = 0; i<arr.length-1; i++){
     for(int j=0; j<arr.length-1-i; j++){
       if(a[j]>a[j+1]){
        int temp = a[j];
        a[j] = a[j+1];
        a[j+1] = temp;
       }
     }
   }
}

4.快速排序


import java.lang.*;
import java.util.Arrays;
public class practice {
    public static void main(String[] args) {
        int[] a = { 54, 35, 48, 36, 27, 12, 44, 44, 8, 14, 26, 17, 28 };
        quickSort(a, 0, a.length-1);
        System.out.println(Arrays.toString(a));
    }


    public static void quickSort(int[] arr, int low, int high){
        int i=low;
        int j=high;
        if(low>high)
            return;
        int key = arr[low];
        while(i<j){
            while(arr[j]>key && j>low){
                j--;
            }
            arr[i]=arr[j];
            while(arr[i]<key && i<high){
                i++;
            }
            arr[j]=arr[i];


        }
        arr[i] = key;
        quickSort(arr,low,i-1);
        quickSort(arr,i+1,high);


    }
    
}

快速排序之所比较快,因为相比冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。
这样在每次交换的时候就不会像冒泡排序一样每次只能在相邻的数之间进行交换,交换的距离就大的多了。因此总的比较和交换次数就少了,速度自然就提高了。当然在最坏的情况下,仍可能是相邻的两个数进行了交换。
因此快速排序的最差时间复杂度和冒泡排序是一样的都是O(N2),它的平均时间复杂度为O(NlogN)。其实快速排序是基于一种叫做“二分”的思想。
http://blog.csdn.net/as02446418/article/details/47395867

5.堆排序
堆排序是一种树形选择排序,是对直接选择排序的有效改进。
初始时把要排序的n个数的序列看作是一棵顺序存储的二叉树(一维数组存储二叉树),调整它们的存储序,
使之成为一个堆,将堆顶元素输出,得到n 个元素中最小(或最大)的元素,这时堆的根节点的数最小(或者最大)。
然后对前面(n-1)个元素重新调整使之成为堆,输出堆顶元素,得到n 个元素中次小(或次大)的元素。
依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。称这个过程为堆排序。
时间复杂度也为:O(nlogn)


public class HeapSort{
    public void createLittleHeap(int[] arr, int last){
        for(int i=last; i>0; i--){
            int parent = (i-1)/2;//找到当前节点的父节点的索引
            if(arr[i]<arr[parent]){
                swap(arr, i, parent);
            }
        }
    }


    public void swap(int[] arr, int i, int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }


    public void print(int[] a){
        for(int i=0; i<a.length; i++){
            System.out.print(a[i] + " ");
        }
    }


    public static void main(String[] args){
        int[] a = {3,4,4,7,9,6,10,12,12,13,20,20,26};
        HeapSort obj = new HeapSort();
        System.out.println("排序开始");
        obj.print(a);
        for(int i=0; i<a.length; i++){
            obj.createLittleHeap(a,a.length-1-i);//创建小顶堆
            obj.swap(a,0, a.length-1-i);//二叉树的顶点是最小值,把顶点与未排好部分的最后一个值交换
            obj.print(a);
            System.out.println();
        }
        System.out.println("排序后");
        obj.print(a);
    }
}


使用堆排序的一道算法题
import java.util.ArrayList;  
public class Solution32 {  
/* 输入n个整数,找出其中最小的K个数。 
 * 例如输入4,5,1,6,2,7,3,8这8个数字, 
 * 则最小的4个数字是1,2,3,4,。 
 * */     
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {  
            ArrayList<Integer> result = new ArrayList<Integer>();  
            if(k > input.length) return result;  
            for(int i = 0; i < k ; i ++){//只排前k次   
                heapSort(input,i,input.length);//进行第i次排序  
                result.add(input[i]);  
            }  
            return result;  
    }  
      
    private void heapSort( int []  input, int root, int end){//小顶堆实现  
            for(int j = end -1; j >= root; j --){  
                int parent = (j + root -1)/2;//这个地方要注意,因为此时最小的元素在数组的首位,因此使用堆排序时父节点的索引发生变化了。
                if(input[parent] > input[j]){//双亲节点大于当前节点,交换位置。  
                    int temp = input[j];  
                    input[j] = input[parent];  
                    input[parent] = temp;  
                }  
            }    
         }  
           
  
    public static void main(String[] args) {  
      int [] str={4,5,1,6,2,7,3,8};  
      Solution32 s=new Solution32();  
      System.out.print(s.GetLeastNumbers_Solution(str,4));  
                  
    }  
}  


6.归并排序
归并排序 (merge sort) 是一类与插入排序、交换排序、选择排序不同的另一种排序方法。
归并的含义是将两个或两个以上的有序表合并成一个新的有序表。归并排序有多路归并排序、两路归并排序 , 可用于内排序,也可以用于外排序。这里仅对内排序的两路归并方法进行讨论。


分而治之(divide - conquer);每个递归过程涉及三个步骤
第一, 分解: 把待排序的 n 个元素的序列分解成两个子序列, 每个子序列包括 n/2 个元素.
第二, 治理: 对每个子序列分别调用归并排序MergeSort, 进行递归操作
第三, 合并: 合并两个排好序的子序列,生成排序结果.


(1)稳定性
      归并排序是一种稳定的排序。
(2)存储结构要求
     可用顺序存储结构。也易于在链表上实现。
(3)时间复杂度
     对长度为n的文件,需进行趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlgn)。
(4)空间复杂度
     需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为O(n),显然它不是就地排序。
  注意:
     若用单链表做存储结构,很容易给出就地的归并排序
    
import java.util.Arrays;
public class MergeSort {
    public static void mergeSort(int[] arr, int low, int high){
        int mid =(low+high)/2;
        if(low<high){
            mergeSort(arr,low,mid);
            mergeSort(arr,mid+1,high);
            merge(arr, low, mid, high);
        }
    }
    public static void merge(int[] arr, int low, int mid, int high){
        int num = high-low+1;
        int[] temp = new int[num];
        int i =low, j=mid+1;
        int k=0;
        while(i<=mid && j<=high){
            if(arr[i]>arr[j])
                temp[k++] = arr[j++];
            else
                temp[k++] = arr[i++];
        }
        while(i<=mid){
            temp[k++] = arr[i++];
        }
        while(j<=high){
            temp[k++] = arr[j++];
        }
        for(int k1=0; k1<num; k1++){
            arr[low+k1] = temp[k1];
        }
    }
    public static void main(String[] args){
        int[] a = {3,2,5,9,12,3,5,9,12,24,18,17,16};
        mergeSort(a,0,a.length-1);
        System.out.println(Arrays.toString(a));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值