排序算法(21.12)

Posted 未定_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法(21.12)相关的知识,希望对你有一定的参考价值。

一、基于比较的排序

1.插入排序

无序记录-插入->有序序列

1.1直接插入排序

基本思想:

依次将待排序列中的每一个记录插入到已经排好的序列中,直到全部排好

例:12、30、25、9、18

void insertSort(int r[],int n)

    int j=0;
    for(int i=2;i<=n;i++)
    
        r[0]=r[i];
        j=i-1;
        while(r[j]>r[0])
        
            r[j+1]=r[j];
            j--;
        
        r[j+1]=r[0];
    

性能分析:

·最好的情况:初始序列是正序
比较次数:n-1
移动次数:2(n-1) (从第二项开始每一趟待排记录移到r[0]再移回来)
时间复杂度:O(n)
辅助空间:O(1)

·最坏的情况:初始序列为逆序
比较次数: ∑ i = 2 n i \\sum_i=2^n i i=2ni= ( n + 2 ) ( n − 1 ) 2 \\frac(n+2)(n-1)2 2(n+2)(n1)
移动次数: ∑ i = 2 n i + 1 \\sum_i=2^n i+1 i=2ni+1= ( n + 4 ) ( n − 1 ) 2 \\frac(n+4)(n-1)2 2(n+4)(n1)
时间复杂度:O(n2)
辅助空间:O(1)

·平均情况:
比较次数: ∑ i = 2 n i 2 \\sum_i=2^n \\fraci2 i=2n2i= ( n + 2 ) ( n − 1 ) 4 \\frac(n+2)(n-1)4 4(n+2)(n1)
移动次数: ∑ i = 2 n i + 1 2 \\sum_i=2^n \\fraci+12 i=2n2i+1= ( n + 4 ) ( n − 1 ) 4 \\frac(n+4)(n-1)4 4(n+4)(n1)
时间复杂度:O(n2)
辅助空间:O(1)
适用于待排序记录基本有序待排序记录个数较小的情况,是一种稳定排序算法。

基本有序: 如1,2,8,4,5,6,7,3,9,大部分数开始就在该在的位置上。(接近正序)
局部有序: 如6,7,8,9,1,2,3,4,5,局部有序不能提高直接插入排序算法的时间性能。

1.2希尔排序

是对直接插入排序算法的优化。

基本思想:

将整个待排记录分割成若干个子序列,子序列内分别进行直接插入排序,带整个序列记录基本有序时,对全体进行直接插入排序。(一般需要多趟)
·每趟分割组数d/2(初始d=n)

例:59、20、17、36、98、14、23、83、13、28

void ShellSort(int r[],int n)

    for(int d=n/2;d>=1;d=d/2)
    
        for(int i=d+1;i<=n;i++)
        
            r[0]=r[i];
            int j=i-d;
            while(j>0&&r[j]>r[0])
            
                r[j+d]=r[j];
                j=j-d;
            
            r[j+d]=r[0];
        
    

性能分析:
·希尔排序的趟数:
1:n/2
2:n/4
3:n/8
……
k:n/2k
所以 n 2 k \\fracn2^k 2kn>=1

希尔排序算法的时间性能是所取增量的函数,目前尚未找到最好的增量序列。
平均时间复杂度:O(nlog 2n)~O(n2)
当n在某个特定范围内:最好的时间复杂度:O(n1.3 ) 。最坏的时间复杂度:O(n2)
辅助空间:O(1)

是一种不稳定排序算法。

2.交换排序

ri <—反序则交换—> rj

2.1冒泡排序

基本思想:

两两比较相邻记录的关键码,如果反序则交换,直到没有反序的记录为止。

传统的冒泡排序:

for(j=0; j<n-1; j++)
   for(i=j+1; i<n; i++)
            if(a[j]>a[i])
            
                temp=a[j];
                a[j]=a[i];
                a[i]=temp;
            

传统的冒泡排序需要扫描n-1趟,第 i 趟至少把 i 个大数排到最后(升序排),为了使排序更优化,让已位于最终位置的大数不参与下一趟排序,需要考虑以下几点:
(1) 在一趟起泡排序中,若有多个记录位于最终位置,应如何记载?
(2) 如何确定起泡排序的范围,使得已经位于最终位置的记录不参与下一趟排序?
(3)如何判别起泡排序的结束?
解决:(1) 设变量exchange记载记录交换的位置,一趟排序后,exchange记载的一趟排序中记录的最后一次交换的位置,exchange位置之后的记录都有序。
(2) 设bound表示无序区的最后一个记录,则每趟起泡排序的范围是r[1] ~ r[bound]。在一趟排序后,bound=exchange。
(3) 每趟排序exchange的初值为0,若交换其值大于0。

例:5、69、 81、12、38、53、98

void BubbleSort(int r[],int n)

    int exchange=n,bound;
    while(exchange)
    
        bound=exchange;
        exchange=0;
        for(int j=1;j<bound;j++)
        
            if(r[j]>r[j+1])
            
                int t=r[j];
                r[j]=r[j+1];
                r[j+1]=t;
                exchange=j;
            
        
    

性能分析:
·最好的情况:初始序列是正序
比较次数:n-1
移动次数:0
时间复杂度:O(n)
辅助空间:O(1)

·最坏的情况:初始序列为逆序
比较次数: ∑ i = 1 n − 1 ( n − i ) \\sum_i=1^n-1 (n-i) i=1n1(ni)= n ( n − 1 ) 2 \\fracn(n-1)2 2n(n1)
移动次数: ∑ i = 1 n − 1 3 ( n − i ) \\sum_i=1^n-13(n-i) i=1n13(ni)= 3 n ( n − 1 ) 2 \\frac3n(n-1)2 23n(n1)(比较1次移动3次)
例如:
5-4-3-2-1
4-3-2-1 5
3-2-1 4 5
2-1 3 4 5
1 2 3 4 5
时间复杂度:O(n2)
辅助空间:O(1)
·平均情况:
时间复杂度:O(n2)
辅助空间:O(1)
每趟至少把一个最大或最小排到序列的末端,是一种稳定排序算法。

2.2快速排序

基本思想:

选轴值,一趟排序将待排序记录分割成两部分,轴值前一部分记录的关键码均小于或等于轴值,轴值后一部分记录的关键码均大于或等于轴值,重复上述方法,直到整个序列有序。

一般选第一个数作为轴值,轴值最好在序列的位置是居中的,如果待排序列是正序或逆序(最坏的情况),比较序列中第一个记录、最后一个记录和中间记录的关键码,取关键码居中的作为轴值并调换到第一个位置。
选取不同轴值的后果:
决定两个子序列的长度,子序列的长度最好相等。

例:38、27、55、50、13、49、65

int Partition(int r[],int first,int end)//一次划分

    int i=first,j=end;
    r[0]=r[i];
    while(i<j)
    
        while(i<j&&r[0]<=r[j])
            j--;
        if(i<j)
        
            r[i]=r[j];
            i++;
        
        while(i<j&&r[i]<=r[0])
            i++;
        if(i<j)
        
            r[j]=r[i];
            j--;
        
    
    r[i]=r[0];
    return i;

void QuickSort(int r[],int first,int end)

    if(first>=end)//一定要大于等于
        return;
    int f=Partition(r,first,end);
    QuickSort(r,first,f-1);
    QuickSort(r,f+1,end);

性能分析:

执行时间取决于递归的深度
·最好的情况:每次划分左右侧子序列的长度都相等。
扫描时间:O(n)
排序时间:O(nlog2n)

·最坏的情况:初始序列为正序或逆序
比较次数: ∑ i = 1 n − 1 ( n − i ) \\sum_i=1^n-1 (n-i) i=1n1(ni)= n ( n − 1 ) 2 \\fracn(n-1)2 2n(n1)=O(n2)
移动次数:小于比较次数
时间复杂度:O(n2)

·平均情况:
时间复杂度:O(nlog2n)
辅助空间:O(log2n)~O(n)
是内排序算法中最好的,适用于待排数据量教大的情况,是一种不稳定排序算法。

3.选择排序

有序序列<-加入-选择最小记录
选择排序的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

3.1简单选择排序

基本思想:

int selectSort(int r[],int n)

    for(int i=1; i<n; i++)
    
        int index=i;
        for(int j=i+1; j<=n; j++)
            if(r[j]<r[index])
                index=j;
        if(index以上是关于排序算法(21.12)的主要内容,如果未能解决你的问题,请参考以下文章

查找技术(21.12)

查找技术(21.12)

查找技术(21.12)

21.9-21.12 Redis介绍,安装,持久化介绍

21.9 redis介绍;21.10 redis安装;21.11 redis持久化;21.12

21.9 redis介绍 21.10 redis安装 21.11 redis持久化 21.12 re