计算机考研之数据结构-排序

数据结构-排序

重要概念

定义

对元素进行重拍使得其关键字满足递增或者递减的过程。

  • 输入:n个记录(R_1,cdots,R_n),对应关键字为(k_1,cdots,k_n)
  • 输出:一个输入序列的重拍(R_1^{'} ,cdots,R_n^{'})使得(k_1^{'}leqcdotsleq k_n^{'}),比较符号可以改变。

稳定性

对于关键字相同的两个元素,如果排序前后顺序不变即满足稳定性。

内部性与外部性

  • 内部排序:排序过程中所有元素都在内存中。
  • 外部排序:排序过程中元素要在内外存中交换。

说明

以下例子都以顺序表为例。

插入类

插排将序列分为两个部分,有序序列和无序的序列。然后从无序序列中拿出一个元素插入到有序序列中即可。

直接插入排序

void Sort(int A[], int len){
    for(int i=1; i<len; i++){
        if(A[i]<A[i-1]){ //判断是否需要向前插入
            int temp = A[i];
            for(int j=i-1; temp<A[j]; j--) //找到插入位置
                A[j+1]=A[j]; // 为插入的元素挪位置
            A[j+1]=temp;
        }
    }
}

性能分析:
空间:O(1)。
时间:最好O(n),最坏O(n2),平均O(n2)。
稳定性:稳定。

折半插入排序

因为插入的序列是有序的,所以可以使用折半查找节约时间。

void sort(int A[], int len){
    for(int i=1; i<len; i++){
        int temp = A[i];
        int low=0;int high=i-1;
        while(low<=high){
            int mid=(low+high)/2;
            if(A[mid]>temp) high=mid-1;
            else low=mid+1;
        }
        for(int j=i-1; j>high; j--) //找到插入位置
            A[j+1]=A[j]; // 为插入的元素挪位置
        A[high]=temp;  
    }
}

性能分析:
空间:O(1)。
时间:平均O(n^2)。
稳定性:稳定。

希尔排序

希尔排序将序列按照一定的长度切分为多个子序列,对子序列进行插入排序,再对整个序列进行插入排序

void Sort(int A[], int len){
    for(int dk/len; dk>=1;dk=dk/2){
        for(int i=dk+1;i<=n;i++){
            if(A[i]<A[i-dk]){
            }
        }
    }
}

性能分析:
空间:O(1)。
时间:一般约为(n1.3),最坏O(n2)。
稳定性:不稳定。

交换类

冒泡排序

冒泡的排序关键在于每一轮都会把第i大的那个关键字排到有序的位置上。

void sort(int A[], int len){
    for(int i=0;i<len-1;i++)
        for(int j=0;j<len-1-i;j++)
            if(A[j]>A[j+1]){
                int temp = A[j];
                A[j]=A[j+1];
                A[j+1]=temp;
            }
}

加入flag来优化最好情况:

void sort(int A[], int len){
    for(int i=0;i<len-1;i++){
        int flag = 0;
        for(int j=0;j<len-1-i;j++){
            if(A[j]>A[j+1]){
                int temp = A[j];
                A[j]=A[j+1];
                A[j+1]=temp;
                flag=1;
            }
        }
        if(flag==0)
            return;
    }
}

性能分析:
空间:O(1)。
时间:最坏 O(n^2),最好 O(n),平均 O(n^2)。
稳定性:不稳定。

快速排序

int partition(int A[], int lo, int hi){
    int p = A[lo];
    while(lo<hi){
        while(lo<hi && A[hi]>=p) hi--;
        A[lo]=A[hi];
        while(lo<hi && A[lo]<=p) lo++;
        A[hi]=A[lo];
    }
    A[lo]=p;
    return lo;
}

void sort(int A[], int lo, int hi){
    int lo=0; int hi=len-1;
    if(lo<hi){
        int pos=partition(A,lo,hi);
        sort(A,lo,pos-1);
        sort(A,pos+1,hi);
    }
}

性能分析:
空间:即递归栈的深度,最好 O(log(n+1)),最坏 O(n),平均 O()
时间:最坏 O(n^2),平均 O(logn)。
稳定性:不稳定。

选择类

选择排序

void sort(int A[], int len){
    for(int i=0;i<len-1;i++){
        int min = i;
        for(int j=i+1;j<n;j++)
            if(A[j]<A[min])
                min = j;
        if(min!=i)
            swap(A[i],A[min]);
    }
}

性能分析:
空间:O(1)
时间:O(n^2)。
稳定性:不稳定。

堆排序

void adjust(int A[], int i, int len){
    int child;
    for(; 2*i+1<len; i=child){
        int child = 2*i+1; //leftchild
        if(child<len-1 && A[child+1]>A[child])
            child++; // rightchild
        if(A[i]<A[child])
            swap(A[i],A[child])
        else
            break;   
    }
}

sort(int A[], int len){
    for(int i=len/2-1; i>=0; i--)
        adjust(A,i,len);
    
    for(int i=length-1;i>0;i--){
        swap(A[0],A[i]);
        adjust(A,0,i);
    }
}

性能分析:
空间:O(1)
时间:O(nlogn)。
稳定性:不稳定。

归并类

归并排序

int *B=(int *)malloc(n)*sizeof(int);

void merge(int A[], int low, int mid, int high){
    for(int k=low;k<=high;k++)
        B[k]=A[k];
    for(int i=low,int j=mid+1,int k=i;i<=mid&&j<=high;k++){
        if(B[i]<=B[j])
            A[k]=B[i++];
        else 
            A[k]=B[j++];
    }
    while(i<=mid) A[k++]=B[i++];
    while(j<=high) A[k++]=B[j++];
}

void sort(int A[], int low, int high){
    if(low<high){
        int mid=(low+high)/2;
        sort(A,low,mid);
        sort(A,mid+1;high);
        merge(A,low,mid,high);
    }
}

性能分析:
空间:O(n)
时间:最坏最好都是O(nlogn)。
稳定性:稳定。

基数类

基数排序

性能分析:
空间:O(r)。
时间:最坏最好都是O(d(n+r))。
稳定性:稳定。

小结

原文地址:https://www.cnblogs.com/nevermoes/p/9872883.html