常见排序算法

排序算法:

    • 快速排序   O(nlogn)

    • 堆排序   O(nlogn)

    • 归并排序   O(nlogn)

    • 冒泡排序   O(n^2)

    • 选择排序   O(n^2)

    • 插入排序   O(n^2)

    • 希尔排序

1.快速排序:

快速排序原理就是先找一个基准值,将小于基准值的值放在左端,将大于基准值的值放在右端,然后按基准值划分成两部分,分别进行递归快速排序。

java代码:

public class QuickSort {
    public static void quick_sort(int[] a ,int left ,int right){
        if (left < right) {
            int i = left;
            int j = right;
//以最左端的值作为基准值
            int x = a[left];
            while (ix){
                    j--;
                }
                //找到后再进行赋值
                if (i=j时,将基准值赋值给左端计数变量位置的元素a[i]
            a[i]=x;
  //
            quick_sort(a,left,i-1);//左端进行递归快速排序
            quick_sort(a,i+1,right);//右端进行递归快速排序
        }
    }
    public static void main(String[] args){
    int[] a = {3,4,6,1,2,5};
    quick_sort(a,0,a.length-1);
        for (int i :
                a) {
            System.out.print(i+" ");
        }
    }
}

快速排序平均比较次数为:O(nlogn);所以时间复杂度为O(nlogn);没有用到辅助数组,所以空间复杂度为O(1)

 

2.堆排序:

原理:将要排序的数据构建成堆结构,然后从最后一个非叶子节点处转换成大顶堆或者小顶堆,最后将堆顶值和最后一个节点值进行交换。循环上述操作,将除了最后一个节点的剩余节点进行再排序。以此类推。

代码:

public class HeapSort {
    /**
     * 排序主函数
     * @param a
     */
    public static void sort(int []a){
        //首先从最后一个非叶子节点处构建堆结构
        for(int i = a.length/2-1;i>=0;i--){
            changeHeap(a,i,a.length);
        }
        //交换数据,前提是堆已经转换为大顶堆
        for (int t = a.length-1;t>0;t--){
            //进行交换
            swap(a,0,t);
            //对交换后的剩余数据从0开始进行再调整,使其成为大顶堆
            changeHeap(a,0,t);
        }
    }

    /**
     * 构建堆结构和转换大顶堆或小顶堆
     * @param a
     * @param i
     * @param length
     */
    public static void changeHeap(int []a ,int i,int length){
        //获取当前元素值
        int temp = a[i];
        //与左右两子节点进行比较
        for (int j=2*i+1;j temp){
                //此时a[j]并未改变
                a[i]=a[j];
                i=j;
            }else
                break;
        }
        //在此处会对原来的a[j]进行赋值
        a[i]=temp;
    }

    /**
     * 进行元素交换函数
     * @param a
     * @param i
     * @param j
     */
    public static void swap(int []a ,int i,int j){
        int temp = a[i];
        a[i]=a[j];
        a[j]=temp;
    }

    public static void main(String[] args){
        int []a={2,6,3,0,1};
        sort(a);
        for (int i :
                a) {
            System.out.print(i+" ");
        }
    }
}

      堆排序是一种选择排序,堆结构是完全二叉树结构,所以每次循环将进行log2(n-i)次比较所以堆排序的时间复杂度为O(nlogn)

       堆排序适合进行百万级别的数据排序,而快速排序和归并排序需要进行递归操作,所以在数据量很大时会出现堆栈溢出风险。

3.归并排序:

原理:通过递归方法将所有数据分成单独的元素,然后再进行两两合并排序,最后得到有序数列。

 

代码:

 

public class MergeSort {   
/**
     * 排序主方法
     * @param a
     * @param left
     * @param right
     * @param temp
     */
    public static void sort(int []a ,int left,int right,int []temp){
        if (left

 

归并排序是稳定排序,java自带的排序算法就是归并排序的优化版本,其最好最坏平均的时间复杂度均为O(nlogn)。因为用到了一个辅助数组所以空间复杂度为O(n)。

在递归过程中先对短的那段进行递归,可以使递归深度最小。

 

4.简单选择排序:

原理:在所有数列中选出最小值,并且与第一个元素交换,然后从剩余的元素中再选择一个最小值并与第二个元素交换,依次循环直至结尾。

 

代码:

 public class ChooseSort {
/**
     * 选择排序主方法
     * @param a
     */
    public static void sort(int []a){
        int min=0;
        for (int i =0 ;i < a.length;i++){
            min=i;
            for (int k = i+1;k

选择排序在排序过程中每次循环均需要比较n-i次,所以其时间复杂度为:O(n^2),空间复杂度为O(1)

 

5.冒泡排序:

原理:从数列头进行两两比较,然后经过多轮比较,将最大值交换到最后端,然后再进行多伦比较将次大数交换到最大值后,以此循环。

 

代码:

public class BubbleSort {
    public static void sort(int []a){
        int temp =0;
        //需要冒的泡泡数
        for (int i = 0;i < a.length-1;i++){
            //每个泡泡需要比较的次数
            for (int k = 0;k < a.length-1-i;k++){
                if (a[k]>a[k+1]){
                  temp =a[k];
                  a[k]=a[k+1];
                  a[k+1]=temp;
                }
            }
        }
    }
    public static void main(String[] args){
        int []a={2,1,5,4,3,6};
        sort(a);
        for (int i :
                a) {
            System.out.print(i+" ");
        }
    }
}

冒泡排序在排序过程中每次循环都需要进行n-i次比较,所以时间复杂度和选择排序一样都是O(n^2)。

 

6.插入排序(步长为1):

       原理:因为步长为1,所以从第二个元素开始与前一个元素进行比较两两比较,若小于前面的元素则与其交换,然后在与前一个元素比较交换,直至没有前一个元素,然后再从第三个元素开始进行循环比较。

       希尔排序也是插入排序的一种,只不过其步长不为1,它的步长在排完一次后减小1,最后减小为1,然后进行步长为1的插入排序。

 

代码:

public class InsertSort {
/**
     *
     * @param a
     */
    public static void sort(int []a){
        for (int i =1 ; i < a.length ; i++){
//这里可以使用fori()循环替代
            int j =i;
            while (j > 0 && a[j]

插入排序,选择排序和冒泡排序的时间复杂度均为O(n^2).

你可能感兴趣的:(数据结构与算法)