Post

排序

排序算法:

  • 稳定性
    • 关键字相同的元素在排序之后相对位置是否会发生改变
  • 分类:
    • 内部排序
      • 数据都在内存中
      • 关注算法时、空间复杂度更低
    • 外部排序
      • 数据太多,无法全部放入内存
      • 关注如何使读、写磁盘次数更少 可视化网站: https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html

插入排序:

Img Img

希尔排序

  • 算法流程:
    • 先将待排序表,分割成若干 形如L[i,i+d,i+2d,…,i+kd]的“特殊“子表,对各个子表分别进行直接插入排序。
    • 缩小增量d,重复上述过程,直到d=1
  • 性能:
    • 空间复杂度:O(1)
    • 时间复杂度:未知,但是优于直接插入排序
    • 稳定性:不稳定
    • 适用性:仅可用于顺序表
  • 高频题型:
    • 给出增量序列,分析每一趟排序后的状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//希尔排序
void ShellSort(int A[],int n){
int d, i, j;
//A[0]只是暂存单元,不是哨兵,当j<=0时,插入位置已到
for(d= n/2; d>=1; d=d/2)
    for(i=d+1; i<=n;++i)
        if(A[i]<A[i-d]){
            A[O]=A[i];
            for(j= i-d; j>0 && A[0]<A[j]; j-=d)
                A[j+d]=A[j];

            A[j+d]=A[0];
        }
}

Img

简单选择排序:

Img

Img

实例:利用指针数组实现字符串排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>s
#include <string.h>
#define N 13

int main(int argc, char const *argv[])
{
    void sort(char *name[],int n);
    void print(char *name[],int n);

    char *name[] ={"4PGC938", "2IYE230", "3CIO720", "1ICK750", "1OHV845", "4JZY524", "1ICK750", "3CIO720","1OHV845", "1OHV845","2RLA629", "2RLA629", "3ATW723"};

    sort(name,N);
    print(name,N);

    return 0;
}


void sort(char *name[],int n) //使用选择排序
{
    char *temp;
    int i,j,k;
    for(i=0;i<N-1;i++)
    {
        for(j=i+1;j<N;j++)
        {
            if(strcmp(name[i],name[j])>0) 
/*如果返回值小于 0,则表示 str1 小于 str2。
如果返回值大于 0,则表示 str1 大于 str2。
如果返回值等于 0,则表示 str1 等于 str2。*/
                {
                    temp = name[i];
                    name[i] = name[j];
                    name[j] = temp;
                }
        }
    }
}


void print(char *name[],int n)
{
    int i;
    for(i=0;i<N;i++) printf("%s\n",name[i]);
}
//输出
1ICK750
1ICK750
1OHV845
1OHV845
1OHV845
2IYE230
2RLA629
2RLA629
3ATW723
3CIO720
3CIO720
4JZY524
4PGC938

关于教材上利用k来判断交换的写法,与上面没有区别

  • 他们进行交换的次数都是33次

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    
    #include <stdio.h>
    #include <string.h>
    #define N 13
      
    int main(int argc, char const *argv[])
    {
        void sort(char *name[],int n);
        void sort_2(char *name[],int n);
        void print(char *name[],int n);
      
        char *name[] ={"4PGC938", "2IYE230", "3CIO720", "1ICK750", "1OHV845", "4JZY524", "1ICK750", "3CIO720","1OHV845", "1OHV845","2RLA629", "2RLA629", "3ATW723"};
      
        sort(name,N);
        print(name,N);
      
        return 0;
    }
      
    //没有k的情况
    void sort(char *name[],int n) //使用选择排序
    {
        int count = 0;
        char *temp;
        int i,j,k;
        for(i=0;i<N-1;i++)
        {
            for(j=i+1;j<N;j++)
            {
                if(strcmp(name[i],name[j])>0) 
    /*如果返回值小于 0,则表示 str1 小于 str2。
    如果返回值大于 0,则表示 str1 大于 str2。
    如果返回值等于 0,则表示 str1 等于 str2。*/
                    {
                        temp = name[i];
                        name[i] = name[j];
                        name[j] = temp;
                        count++;
                    }
            }
        }
        printf("sort without k swap count: %d\n",count);
    }
      
    //有k的情况
    void sort_2(char *name[],int n) //使用选择排序
    {
        int count = 0;
        char *temp;
        int i,j,k;
        for(i=0;i<N-1;i++)
        {
            for(j=i+1;j<N;j++)
            {
                k=i;
                if(strcmp(name[i],name[j])>0) 
    /*如果返回值小于 0,则表示 str1 小于 str2。
    如果返回值大于 0,则表示 str1 大于 str2。
    如果返回值等于 0,则表示 str1 等于 str2。*/
                    {
                        k=j;
                    }
                if(k!=i)
                {
                        temp = name[i];
                        name[i] = name[j];
                        name[j] = temp;
                        count++;
                }
            }
        }
        printf("sort with k swap count: %d\n",count);
    }
      
      
    void print(char *name[],int n)
    {
        int i;
        for(i=0;i<N;i++) printf("%s\n",name[i]);
    }
    
    sort without k swap count: 33
    1ICK750   
    1ICK750   
    1OHV845   
    1OHV845   
    1OHV845   
    2IYE230   
    2RLA629   
    2RLA629   
    3ATW723   
    3CIO720
    3CIO720
    4JZY524
    4PGC938
    

    注意点:

    • 不能写成以下形式: if ( * name[ k]> * name[j] ) k= j ; 这样只比较name [ k ] 和name [ j] 所指向的宇符串中的笫1 个宇符。
      • 字符串比较应当用strcmp 函数。
      • 想想一下如果字符串的第一个字符都相同,那么会发生什么。
    • tips:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    //print 函数也可改写为以下形式:
    void print_2( char * name[], int n)
    {
        int i=0;
    	char * p;
    	p= name[0] ;
    	while(i < n )
    	{p= * (name+ i++) ;
        // p为 指向数组的指针变量
    	printf("%s\n" , p) ;
        }
    }
    
This post is licensed under CC BY 4.0 by the author.