排序算法总结和分析

排序算法总结

插入算法

  • 思想:每次选择一个元素k,将其插入到前面已经有序的部分数组里。A[0...j]已经有序,从n处向前扫描:如果K比A[i]小,说明要继续往前寻找插入的位置,并且将A[i]往后移动;如果K比A[i]大说明应该插入A[i]后面处,然后break,将A[I+1]赋值为K值。

/*
 插入排序伪代码:
  insertSort(A,n)
    for j(1,n)
        do:key <= A[j],i <= j-1
        while(i>=0 and A[i]>key
            do:A[i+1] <=A[i],i=i-1
        A[i+1]=key
        复杂度:最坏0(n^2),平均:o(n^2)。最好o(n),稳定,空间复杂度o(1)
 */
    public static void InsertSort(int A[],int n) {
        for(int j=1;j<n;j++) {
            int key=A[j],i;
            for(i=j-1;i>=0;i-- ) {
                if(A[i]>key)
                    A[i+1]=A[i];
                else
                    break;
            }
            A[i+1]=key;
        }
        
    }


希尔排序

  • 思想:希尔排序也是一种插入排序,采用分组直接插入方式,可以降低复杂度,最坏情况:o(logn),平均复杂度:o(logn);不稳定
  • 步骤:选取第一个增量d1,把表分成d1个组,把数组里下表距离为d1的分为一组,用插入排序算法排好序,使得每个组里有序;然后选择下一个增,一直到d1为1也就是所有数据放到同一个组里直接插入排序排序完成

冒泡排序

    public static void BubSort(int A[]) {
        for(int i=0;i<A.length;i++) {
            for(int j=0;j<A.length-1-i;j++) {
                if(A[j]>A[j+1]) {
                    int tmp=A[j];
                    A[j]=A[j+1];
                    A[j+1]=tmp;
                }
            }
        }
    }


快速排序

  • 思想:快速排序是冒泡排序的一种,多趟排序选择一个记录key,将小于该记录的数据放在key之前,大于key的数放在后面,然后对key前面的和之后的快速排序。平均复杂度:o(nlgn),最坏情况退化为冒泡排序(n^2);不稳定的算法

    public static void QuickSort(int A[],int begin,int end) {
        int i=begin,j=end;
        if(i>=j)
        return;
        int key=A[i];
        while(i<j) {
            while(i<j&&A[j]>key)
                j--;
            if(i<j&&A[j]<=key) {
                A[i]=A[j];
                i++;
            }
            while(i<j&&A[i]<key)
                i++;
            if(i<j&&A[i]>=key) {
                A[j]=A[i];
                j--;
            }
        }
        A[i]=key;
        QuickSort(A,begin,i-1);
        QuickSort(A,i+1,end);
    }

选择排序

  • 思想:从未排序中选择最小元素放到已排序数组部分后
  • 时间复杂度:o(n^2)
    public static void SelectSort(int A[]) {
        for(int i=0;i<A.length;i++) {
            int minindex=i;
            for(int j=i;j<A.length;j++) {
                if(A[j]<A[minindex])
                    minindex=j;
            }
            int tmp=A[minindex];
            A[minindex]=A[i];
            A[i]=tmp;
        }
    }

堆排序

- 思想:利用双亲和孩子节点之间的关系调整完全二叉树,使它最大值(或者最小值)最顶部,每个顶部节点都是最值。平均复杂度,最坏、最好复杂度都是o(nlgn)。但是每次插入元素都要重新调整
package com.hui.sort;
public class HeapSort {
    public void heapSort(int []array) {
        matHeapAdjust(array);
        for(int i=array.length-1;i>0;i--) {
            int tmp=array[0];
            array[0]=array[i];
            array[i]=tmp;
            heapAdjust(array,1,i);      
        }
    }
    private void heapAdjust(int[] array, int s, int m) {
        // TODO Auto-generated method stub
        int tmp,i,largest;
        tmp=array[s-1];
        for(i=2*s;i<=m;i*=2) {
            if(i<m&&array[i-1]<array[i]) {
                largest=i;
                i++;
            }else {
                largest=i-1;
            }
            if(tmp>=array[largest])
                break;
            array[s-1]=array[largest];
            s=largest+1;
        }
        array[s-1]=tmp;
        
    }
    private void matHeapAdjust(int[] array) {
        // TODO Auto-generated method stub
        for(int i=array.length/2;i>0;i--)
            heapAdjust(array,i,array.length);
    }

}

归并排序

  • 思想:将多个有序表归并成新的有序表。
  • 空间复杂度o(n);稳定;时间复杂度o(nlogn)
  • 适用于大数据排序,比如说5000万个数排序而且内存不够。

    public static void MergSort(int a[],int begin,int end,int[] tmp) {
        if(begin<end) {
            int mid=(begin+end)/2;
            MergSort(a,begin,mid,tmp);
            MergSort(a,mid+1,end,tmp);
            MergArray(a,begin,mid,mid+1,end,tmp);
        }
        
    }
private static void MergArray(int[] a, int Lbegin, int Lend, int Rbegin, int Rend, int[] tmp) {
        // TODO Auto-generated method stub
        int i=Lbegin,j=Rbegin,k=0;
        while(i<=Lend&&j<=Rend) {
            if(a[i]<a[j])
                tmp[k++]=a[i++];
            else
                tmp[k++]=a[j++];
        }
        while(i<=Lend)
            tmp[k++]=a[i++];
        while(j<=Rend)
            tmp[k++]=a[j++];
        for(int h=0;h<k;h++)
            a[Lbegin+h]=tmp[h];
        
    }

归并排序变形

  • 题目描述:
    在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

  • 输入描述:
    题目保证输入的数组中没有的相同的数字

  • 数据范围:

    对于%50的数据,size<=10^4

    对于%75的数据,size<=10^5

    对于%100的数据,size<=2*10^5

public class Solution {
    int count=0;
    public int InversePairs(int [] array) {
        if(array==null||array.length==0)
            return 0;
        mergeSort(array,0,array.length-1);
        return count;
    }
    private void mergeSort(int a[],int left,int right){
        if(left>=right)
            return;
        int mid=(left+right)/2;
        mergeSort(a,left,mid);
        mergeSort(a,mid+1,right);
        merge(a,left,mid,right);
    }
    private void merge(int a[],int left,int mid,int right){
        int temp[]=new int[right-left+1];
        int l=mid,r=right,m=mid;
        int t=right-left;
        while(l>=left&&r>mid){
            if(a[l]>a[r]){
                count+=r-mid;
                temp[t--]=a[l--];
                if(count>=1000000007)
                    count=count%1000000007;
            }else{
                temp[t--]=a[r--];
            }
        }
        while(l>=left){
            temp[t--]=a[l--];
        }
        while(r>mid){
            temp[t--]=a[r--];
        }
        for(int i=0;i<right-left+1;i++)
            a[left+i]=temp[i];
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_34130389/article/details/87148659