• 常见的排序算法总结


    写在前面:在我们找工作的过程中,经常会被问到是否了解常见的算法,所以,如果想在面试过程中有个良好的表现,对常见的排序算法有一定的了解是必须的。

    七种常见排序算法总结

    第一类:交换排序

    1、冒泡排序

    原理说明:

    (1)比较相邻的元素,如果第一个比第二个大,就交换它们两个;

    (2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;

    (3)针对所有的元素重复以上的步骤,除了最后一个;

    (4)重复步骤1~3,直到排序完成。

    代码实现:

     1 #include <stdio.h>
     2 
     3 int main()
     4 {
     5     int A[]={6,5,3,1,8,7,2,4};
     6     int n=sizeof(A)/sizeof(int);
     7     //从小到大
     8     int tmp=0;
     9     for(int i=0;i<n-1;i++)
    10     {
    11         for(int j=0;j<n-1-i;j++)
    12         {
    13             if(A[j]>A[j+1])
    14             {
    15                 tmp=A[j];
    16                 A[j]=A[j+1];
    17                 A[j+1]=tmp;
    18             }
    19         }
    20     }
    21     for(int i=0;i<n;i++)
    22     {
    23         printf("%d ",A[i]);
    24     }
    25     return 0;
    26 }
    冒泡排序

    2、快速排序

    原理说明:

    (1)从序列中挑出一个元素,作为"基准";

    (2)把所有比基准值小的元素放在基准前面,所有比基准值大的元素放在基准的后面(相同的数可以到任一边),这个称为分区操作;

    (3)对每个分区递归地进行步骤1~2,递归的结束条件是序列的大小是0或1,这时整体已经被排好序了。

    代码实现:

     1 #include <stdio.h>
     2 
     3 int part(int *A,int left,int right)
     4 {
     5     int pivot=left;
     6     int index=left+1;
     7     int tmp=0;
     8     for(int i=index;i<=right;i++)
     9     {
    10         if(A[i]<A[pivot])
    11         {
    12             tmp=A[i];
    13             A[i]=A[index];
    14             A[index]=tmp;
    15             ++index;
    16         }
    17     }
    18     tmp=A[pivot];
    19     A[pivot]=A[index-1];
    20     A[index-1]=tmp;
    21     return index-1;
    22 }
    23 
    24 void quickSort(int *A,int left,int right)
    25 {
    26     int pivotIndex;
    27     if(left<right)
    28     {
    29         pivotIndex=part(A,left,right);
    30         quickSort(A,left,pivotIndex-1);
    31         quickSort(A,pivotIndex+1,right);
    32     }
    33 }
    34 
    35 int main()
    36 {
    37     int A[]={5,2,9,4,7,6,1,3,8};
    38     int n=sizeof(A)/sizeof(int);
    39     quickSort(A,0,n-1);
    40     for(int i=0;i<n;i++)
    41     {
    42         printf("%d ",A[i]);
    43     }
    44     return 0;
    45 }
    快速排序

    第二类:插入排序

    1、简单插入排序

    原理说明:

    (1)从第一个元素开始,该元素可以认为已经被排序;

    (2)取出下一个元素,在已经排序的元素序列中从后向前扫描;

    (3)如果该元素(已排序)大于新元素,将该元素移到下一位置;

    (4)重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;

    (5)将新元素插入到该位置后;

    (6)重复步骤2~5。

    代码实现:

     1 #include <stdio.h>
     2 
     3 int main()
     4 {
     5     int A[]={6,5,3,1,8,7,2,4};
     6     int n=sizeof(A)/sizeof(int);
     7     //从小到大
     8     int i,j,tmp;
     9     for(i=1;i<n;i++)
    10     {
    11         tmp=A[i];
    12         for(j=i-1;j>=0 && tmp<A[j];j--)
    13         {
    14             A[j+1]=A[j];
    15         }
    16         A[j+1]=tmp;
    17     }
    18     for(i=0;i<n;i++)
    19     {
    20         printf("%d ", A[i]);
    21     }
    22     return 0;
    23 }
    简单插入排序

    2、希尔排序

    原理说明:

    (1)插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;

    (2)插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。

    代码实现:

     1 #include <stdio.h>
     2 
     3 void shellSort(int *A,int n)
     4 {
     5     int step=n/2;
     6     int i,j,tmp;
     7     while(step>=1)
     8     {
     9         for(i=step;i<n;i++)
    10         {
    11             tmp=A[i];
    12             for(j=i-step;j>=0 && A[j]>tmp;j-=step)
    13             {
    14                 A[j+step]=A[j];
    15             }
    16             A[j+step]=tmp;
    17         }
    18         step/=2;
    19     }
    20 }
    21 
    22 int main()
    23 {
    24     int A[]={6,5,3,1,8,7,2,4};
    25     int n=sizeof(A)/sizeof(int);
    26     shellSort(A,n);
    27     for(int i=0;i<n;i++)
    28     {
    29         printf("%d ",A[i]);
    30     }
    31     return 0;
    32 }
    希尔排序

    第三类:选择排序

    1、简单选择排序

    原理说明:

    (1)初始时在序列中找到最小(大)元素,放到序列的起始位置作为已排序序列;

    (2)再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾;

    (3)以此类推,直到所有元素均排序完毕。

    代码实现:

     1 #include <stdio.h>
     2 
     3 int main()
     4 {
     5     int A[]={6,5,3,1,8,7,2,4};
     6     int n=sizeof(A)/sizeof(int);
     7     //从小到大
     8     int index,tmp;
     9     for(int i=0;i<n-1;i++)
    10     {
    11         index=i;
    12         for(int j=i+1;j<n;j++)
    13         {
    14             if(A[j]<A[index])
    15             {
    16                 index=j;
    17             }
    18         }
    19         tmp=A[i];
    20         A[i]=A[index];
    21         A[index]=tmp;
    22     }
    23     for(int i=0;i<n;i++)
    24     {
    25         printf("%d ",A[i]);
    26     }
    27     return 0;
    28 }
    简单选择排序

    2、堆排序

    原理说明:

    堆排序是指利用堆这种数据结构所设计的一种选择排序算法,堆是一种近似完全二叉树的结构。

    (1)由输入的无序数组构造一个最大堆,作为初始的无序区;

    (2)把堆顶元素(最大值)和堆尾元素互换;

    (3)把堆(无序区)的尺寸缩小1,并从新的堆顶元素开始进行堆调整;

    (4)重复步骤2,直到堆的尺寸为1。

    代码实现:

     1 #include <stdio.h>
     2 
     3 //堆调整
     4 void heapAdjust(int *A,int i,int size)
     5 {
     6     int leftChild=2*i+1;
     7     int rightChild=2*i+2;
     8     int root=i;
     9     if(leftChild<size && A[leftChild]>A[root])
    10     {
    11         root=leftChild;
    12     }
    13     if(rightChild<size && A[rightChild]>A[root])
    14     {
    15         root=rightChild;
    16     }
    17     int tmp;
    18     if(root!=i)
    19     {
    20         tmp=A[i];
    21         A[i]=A[root];
    22         A[root]=tmp;
    23         heapAdjust(A,root,size);
    24     }
    25 }
    26 
    27 void heapSort(int *A,int size)
    28 {
    29     //建立堆
    30     for(int i=size/2-1;i>=0;i--)
    31     {
    32         heapAdjust(A,i,size);
    33     }
    34     int tmp;
    35     for(int i=size-1;i>0;i--)
    36     {
    37         tmp=A[0];
    38         A[0]=A[i];
    39         A[i]=tmp;
    40         heapAdjust(A,0,i);
    41     }
    42 }
    43 
    44 int main()
    45 {
    46     int A[]={6,5,3,1,8,7,2,4};
    47     int n=sizeof(A)/sizeof(int);
    48     heapSort(A,n);
    49     for(int i=0;i<n;i++)
    50     {
    51         printf("%d ",A[i]);
    52     }
    53     return 0;
    54 }
    堆排序

    第四类:归并排序

    1、二路归并排序

    原理说明:

    递归实现的归并排序是算法设计中分治策略的典型应用,我们将一个大问题分割成小问题分别解决,然后用所有小问题的答案来解决整个大问题。

    (1)申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;

    (2)设定两个指针,最初位置分别为两个已经排序序列的起始位置;

    (3)比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;

    (4)重复步骤3直到某一指针到达序列尾;

    (5)将另一序列剩下的所有元素直接复制到合并序列尾。

    代码实现:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 //合并两个已排好序的数组
     5 void merge(int *A,int left,int mid,int right)
     6 {
     7     int len=right-left+1;
     8     int *tmp=(int*)malloc(sizeof(int)*len);
     9     int i=left;
    10     int j=mid+1;
    11     int index=0;
    12     while(i<=mid && j<=right)
    13     {
    14         tmp[index++]=A[i]<=A[j]?A[i++]:A[j++];
    15     }
    16     while(i<=mid)
    17     {
    18         tmp[index++]=A[i++];
    19     }
    20     while(j<=right)
    21     {
    22         tmp[index++]=A[j++];
    23     }
    24     for(int k=0;k<len;k++)
    25     {
    26         A[left++]=tmp[k];
    27     }
    28     free(tmp);
    29 }
    30 
    31 void mergeSort(int *A,int left,int right)
    32 {
    33     int mid;
    34     if(left<right)
    35     {
    36         mid=(left+right)/2;
    37         mergeSort(A,left,mid);
    38         mergeSort(A,mid+1,right);
    39         merge(A,left,mid,right);
    40     }
    41 }
    42 
    43 int main()
    44 {
    45     int A[]={6,5,3,1,8,7,2,4};
    46     int n=sizeof(A)/sizeof(int);
    47     mergeSort(A,0,n-1);
    48     for(int i=0;i<n;i++)
    49     {
    50         printf("%d ",A[i]);
    51     }
    52     return 0;
    53 }
    二路归并排序

    附:在我们做笔试的过程中,经常会用到全排与组排的算法思想,所以在这里也一并的整理出来。

    1、全排算法

    代码实现:

     1 #include<stdio.h>
     2 #include <stdlib.h>
     3 
     4 void swap(int *p1,int *p2)
     5 {
     6     int t=*p1;
     7     *p1=*p2;
     8     *p2=t;
     9 }
    10 
    11 void permutation(int a[],int index,int size)
    12 {
    13     if(index==size)
    14     {
    15         for(int i=0;i<size;i++)
    16             printf("%d ",a[i]);
    17         printf("
    ");
    18     }
    19     else
    20     {
    21         for(int j=index;j<size;j++)
    22         {
    23             swap(&a[j],&a[index]);
    24             permutation(a,index+1,size);//此处用到递归思想
    25             swap(&a[j],&a[index]);
    26         }
    27     }
    28 }
    29 
    30 int main()
    31 {
    32     int n;
    33     scanf("%d",&n);
    34     int *a=(int*)malloc(sizeof(int)*n);
    35     for(int i=0;i<n;i++)
    36         a[i]=i+1;
    37     permutation(a,0,n);
    38     free(a);
    39     return 0;
    40 }
    全排算法

    输入:

    4

    输出:

    1 2 3 4
    1 2 4 3
    1 3 2 4
    1 3 4 2
    1 4 3 2
    1 4 2 3
    2 1 3 4
    2 1 4 3
    2 3 1 4
    2 3 4 1
    2 4 3 1
    2 4 1 3
    3 2 1 4
    3 2 4 1
    3 1 2 4
    3 1 4 2
    3 4 1 2
    3 4 2 1
    4 2 3 1
    4 2 1 3
    4 3 2 1
    4 3 1 2
    4 1 3 2
    4 1 2 3
    全排输出

    2、组排算法

    代码实现:

     1 #include<stdio.h>
     2 #include <stdlib.h>
     3 
     4 void combine(int n,int m,int a[],int b[],const int M)
     5 {
     6     for(int j=n;j>=m;j--)
     7     {
     8         b[m-1]=j-1;
     9         if(m>1)combine(j-1,m-1,a,b,M);//用到了递归思想
    10         else
    11         {
    12             for(int i=M-1;i>=0;i--)
    13             {
    14                 printf("%d ",a[b[i]]);
    15             }
    16             printf("
    ");
    17         }
    18     }
    19 }
    20 
    21 int main()
    22 {
    23     int n,m;
    24     scanf("%d%d",&n,&m);
    25     int *a=(int*)malloc(sizeof(int)*n);
    26     int *b=(int*)malloc(sizeof(int)*m);
    27     for(int i=0;i<n;i++)
    28         a[i]=i+1;
    29     const int M=m;
    30     combine(n,m,a,b,M);
    31     free(a);
    32     free(b);
    33     return 0;
    34 }
    组排算法

    输入:

    4 3

    输出:

    4 3 2
    4 3 1
    4 2 1
    3 2 1
    组排输出

    后记:欢迎各路大神批评与指正!

  • 相关阅读:
    Error: unable to load xmlsec-openssl library
    count(1)、count(*)与count(列名)的执行区别
    Linux下的压缩zip,解压缩unzip命令详解及实例
    linux centos 如何查看操作系统版本信息
    These dependencies were not found: *!!vue-style-loader!css-loader?
    Git如何永久删除某个重要文件文件或文件夹 (包括历史记录) 强制
    LDAP的filter查询详解
    详谈mysqldump数据导出的问题
    GO -- 遍历删除 数组 slice
    mjml强大&&灵活的邮件模版引擎
  • 原文地址:https://www.cnblogs.com/gcl0909031172/p/9744901.html
Copyright © 2020-2023  润新知