数据结构 排序

排序(Sort),就是重新排序表中的元素,使表中的元素满足按关键字允许的过程
image.png
排序算法的评价指标
时间复杂度、空间复杂度
算法的稳定性:
image.png
image.png

插入排序

算法思想:每次将一个待排序的记录按其关键字大小插入到前面已排好序的子序列中,直到全部记录插入完成
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

算法实现

//直接插入排序
void InserSort(int A[],int n){
	int i,j,temp;
    for(i=1;i<n;i++)		//将各元素插入已排好序的序列中
        if(A[i]<A[i-1]){	//若A[i]关键字小于前驱
            temp=A[i];		//用temp暂存A[i] 
            for(j=i-1;j>=0 && A[j]>temp;--j) //检查所有前面已排好序的元素
                A[j+1]=A[j];	//所有大于temp的元素都向后挪位
            A[j+1]=temp;		//复制到插入位置
        }
}

算法实现(带哨兵)
image.png
算法效率分析
空间复杂度:O(1)
时间复杂度:主要来自对比关键字、移动元素若有n个元素,则需要n-1趟处理
最好情况:
共n-1趟处理,每一趟只需要对比关键字1次,不用移动元素
最好时间复杂度--O(n)
最坏情况:
image.png
最坏时间复杂度--O(n^2)
image.png

优化--折半插入排序

思路:先用折半查找找到应该插入的位置,再移动元素
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

//折半插入排序
void InserSort(int  A[],int n){
	int i,j,low,high,mid;
    for(i=2;i<=n;i++){
        A[0]=A[i];
        low=1;high=i-1;
        while(low<=high){
            mid=(low+high)/2;
            if(A[mid]>A[0]) high=mid-1;
            else low=mid+1;
        }
        for(j=i-1;j>=high+1;--j)
            A[j+1]=A[j];
        A[high+1]=A[0];
    }
}

image.png
image.png

希尔排序(Shell Sort)

先追求表中元素部分有序,再逐渐逼近全局有序
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
算法实现

//希尔排序
void Shell Sort(int A[],int n){
	int d,i,j;
    for(d=n/2;d>=1;d=d/2)
        for(i=d+1;i<=n;++i)
            if(A[i]<A[i-d]){
                A[0]=A[i];
                for(j=i-d;j>0&&A[0]<A[j];j-=d)
                    A[j+d]=A[j];
                A[j+d]=A[0];
            }
}

image.png
image.png
image.png

冒泡排序

基于“交换”的排序:根据序列中两个元素关键字的比较结果来对换这两个记录在序列中的位置
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
算法实现

//交换
void swap(int &a,int &b){
	int temp=a;
    a=b;
    b=temp;
}
//冒泡排序
void BubbleSort(int A[],int n){
	for(int i=0;i<n-1;i++){
        bool flag=false;
        for(int j=n-1;j>i;j--)
            if(A[j-1]>A[j]){
                swap(A[j-1],A[j]);
                flag=true;
            }
        if(flag==false)
            return;
    }
}

image.png
算法性能分析
image.png
image.png

快速排序

基于“交换”的排序:根据序列中两个元素关键字的比较结果来对换这两个记录在序列中的位置
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

int Partition(int A[],int low,int high){
	int pivot=A[low];
    while(low<high){
        while(low<high&&A[high]>=pivot)--high;
        A[low]=A[high];
        while(low<high&&A[low]<=pivot)++low;
        A[high]=A[low];
    }
    A[low]=pivot;
    return low;
}
void QuickSort(int A[],int low,int high){
	if(low<high){
        int pivotpos=Partition(A,low,high);
        QuickSort(A,low,pivotpos-1);
        QUickSort(A,pivotpos+1,high);
    }
}

image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
算法效率分析
image.png
image.png
image.png
image.png
最坏情况
image.png
比较好的情况
若每一次选中的“枢轴”将待排序序列划分为均匀的两个部分,则递归速度最小,算法效率最高
image.png
image.png
image.png

简单选择排序

选择排序:简单选择排序、堆排序
选择排序:每一趟在待排序元素中选取关键字最小(或最大)的元素加入有序子序列

每一趟在待排序元素中选取关键字最小的元素加入有序子序列
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
算法实现

void SelectSort(int A[],int n){
	for(int i=0;i<n-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]);
    }
}
void swap(int &a.int &b){
	int temp=a;
    a=b;
    b=temp;
}

image.png
算法性能分析
image.png
image.png
image.png

堆排序

什么是堆
image.png
image.png
image.png
建立大根堆
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

void BuildMaxHeap(int A[],int len){
	for(int i=len/2;i>0;i--)
        HeadAdjust(A,i,len);
}
void HeadAdjust(int A[],int k,int len){
	A[0]=A[k];
    for(int i=2*k;i<=len;i*=2){
        if(i<len&&A[i]<A[i+1])
            i++;
        if(A[0]>=A[i])break;
        else{
            A[k]=A[i];
            k=i;
        }
    }
    A[k]=A[0];
}

image.png
基于大根堆进行排序
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

void BuildMaxHeap(int A[],int len)

void HeadAdjust(int A[],int k,int len)

void HeapSort(int A[],int len){
	BuildMaxHeap(A,len);
    for(int i=len;i>1;i--){
        swap(A[i],A[1]);
        HeadAdjust(A,1,i-1)
    }
}

image.png
image.png
算法效率分析
image.png
image.png
image.png

在堆中插入新元素

image.png
image.png
image.png
image.png
image.png

在堆中删除元素

image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

归并排序

归并:把两个或多个已经有序的序列合并成一个
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
代码实现

int *B=(int *)malloc(n*sizeof(int));
void Merge(int A[],int low,int mid,int high){
	int i,j,k;
    for(k=low;k<=high;k++)
        B[k]=A[k];
    for(i=low,j=mid+1,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++];
}

image.png

image.png
image.png
image.png
image.png

image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

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

image.png
image.png
image.png

基数排序(Radix Sort)

image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
算法效率分析
image.png
image.png
image.png
稳定性
image.png
image.png
image.png
image.png
基数排序的应用
image.png
image.png
image.png
image.png

外部排序

外存、内存之间的数据交换

image.png
image.png
image.png
image.png
image.png

外部排序原理

image.png
构造初始“归并段”
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
第一趟归并
把8个有序子序列(初始归并段)两两归并
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
第二趟归并
把4个有序子序列(归并段)两两归并
image.png
image.png
image.png
image.png
第三趟归并
把2个有序子序列(归并段)归并
image.png
image.png
时间开销分析
image.png
外部排序时间开销=读写外存的时间+内部排序所需时间+内部归并所需时间
优化:多路归并
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

败者树

多路平衡归并带来的问题
image.png
什么是败者树
image.png
image.png
image.png
基于已经构建好的败者树,选出新的胜者只需进行3场比赛

败者树在多路平衡归并中的应用

image.png
image.png
image.png
image.png
image.png
image.png

置换-选择排序

image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

最佳归并树

归并树的神秘性质
image.png
image.png
构造2路归并的最佳归并树
image.png
多路归并的情况
image.png
多路归并的最佳归并树
image.png
image.png
image.png
image.png
image.png
如果减少一个归并段
image.png
image.png
image.png
正确的做法
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

posted @ 2023-09-23 19:14  小旺不正经  阅读(56)  评论(0)    收藏  举报