排序

39 阅读3分钟

image.png

1、堆排序(升序采用大顶堆)--时间复杂度:O(NlogN);不稳定;空间复杂度:O(1)

image.png image.png

调整堆:从不满足堆的性质的节点开始(O(logN))

//调整堆;arr:待维护的数组,n:数组长度;i:待维护节点的下标
void heapify(int arr[],int n,int i){
    int longest=i;
    int lson=i*2+1;
    int rson=i*2+2;
    //找到节点值最大的下标
    if(lson<n && arr[lson]>arr[longest])longest=lson;
    if(rson<n && arr[rson]>arr[longest])longest=rson;
    if(longest!=i){
        int temp=arr[i];
        arr[i]=arr[longest];
        arr[longest]=temp;
        heapify(arr,n,longest);//继续调整该节点对应的堆
    }
}

建堆:(O(N))从有子节点的第一个节点开始

void heap_sort(int arr[],int n){
    //建堆
    for(int i=(n-1)/2;i>=0;i--){
        heapify(arr,n,i);
    }
    //排序
    for(i = n-1; i>0; i--){
        //将堆顶元素和最后一个元素交换
        int temp=arr[i];
        arr[i]=arr[0];
        arr[0]=temp;
        //调整堆为大顶推 ,i表示排前i个元素 
        heapify(arr,i,0);
    }
}

2 快速排序

对于基本有序表,为最坏情况,时间复杂度是O(n2),空间复杂度O(1)

分治,选择一个基准元素(base),通常选择第一个或最后一个元素;

通过第一轮扫描,比base小的元素都在base左边,比base大的元素都在base右边,再有同样的方法递归排序这两部分,直到序列中所有数据均有序为止。

需要有base,left指针,right指针

时间复杂度:平均O(nlogn),最好O(nlogn),最坏O(n2); 空间复杂度:O(logn);

/*
    left:数组左边界
    right:数组右边界
    采用分治的思想,先找到 每次分割的点 pos ,再排序。
    */
    public void quickSort(int[] arr, int left, int right){
        if(left < right){
            int pos = partition(arr, left, right);
            quickSort(arr, left, pos - 1);
            quickSort(arr, pos + 1, right);
        }
    }
    public int partition(int[] arr, int left, int right){
        int base = arr[left];
        while(left < right){
            while(left < right && arr[right] >= base){
                right--;
            }
            arr[left] = arr[right];
            while(left < right && arr[left] <= base){
                left++;
            }
            arr[right] = arr[left];       
        }
        arr[left] = base;
        return left;
    }
}

3 归并排序

时间复杂度:最好O(nlogn),最坏O(nlogn),平均O(nlogn)

空间复杂度:O(n)

image.png

void mergesort(int arr[],int p,int q){
    if(p < q){
        int r=(q-p)/2;
        mergesort(arr,p,r);
        mergesort(arr,r+1,q);
        merge(arr,p,q,r);
    }
}

void merge(int arr[],int p,int q,int r){//r是中间的下标
    int L1,L2;
    L1=r-p+1;
    L2=q-r;
    int L[50],R[50];
    for(int i=0;i<L1;i++){
        L[i]=arr[p+i];
    }
    for(int i=0;i<L2;i++){
        R[i]=arr[r+1+i];
    }
    L[L1]=INT_MAX;
    R[L2]=INT_MAX;
    int i=0,j=0;
    for(int k=p;k<=q;k++){
        if(L[i]<R[j]){
            arr[k]=L[i];
            i++;}
        else{
            arr[k]=R[j];
            j++;}
    }
    
}

4 冒泡排序

时间复杂度:最好情况O(n),最坏O(n2),平均O(n2)

空间复杂度:O(1)

稳定

5 选择排序

时间复杂度:最好,最坏,平均:O(n2)

空间复杂度:O(1)

不稳定

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕

6 直接插入排序

对于基本有序的表,时间复杂度是O(n),空间复杂度是O(1)

时间复杂度:最好O(n),最坏O(n2),平均O(n2)

空间复杂度:O(1)

稳定

7希尔排序

递减增量排序算法

时间复杂度:平均O(nlogn),最好O(nlogn2),最坏O(nlogn2)

空间复杂度:O(1)

不稳定