Fork me on GitHub

排序算法

排序算法是最常用的一种算法,在面试中也会经常被问到,今天以升序为例总结一下集中常用的排序算法,以及复杂度和稳定性。

关于稳定性:稳定性指的是一组数据中如果存在相等的数据,Ai=Aj,排序前Ai在Aj的前面,那么排序后Ai仍然在Aj的前面,那么这种排序算法就是稳定的,反正则是不稳定的。

常见的排序算法有:

  • 冒泡排序
  • 选择排序
  • 插入排序
  • 快速排序
  • 堆排序
  • 希尔排序

    冒泡排序

  • 排序思想:冒泡排序的核心思想就是比较相邻两个变量的大小,然后将不符合顺序的两个变量交换位置。如果有n个变量,则需要n-1趟比较,第一趟比较将最大值排序到倒数第一的位置,第二趟排序将次大值排序到倒数第二的位置……直到第n-1趟比较,可以将所有的变量都回归到正确的位置。时间复杂度为O(n^2)。很显然,冒泡排序是一种稳定的排序算法。代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void bubble_sort(int* &a,int n)
    {
    int i,j,temp;
    for(i=n-1;i>0;i--)
    {
    for(j=0;j<i;j++)
    {
    if(a[j]>a[j+1])
    {
    swap(a[j],a[j+1]);// swap函数交换位置
    }
    }
    }
    }

选择排序

  • 排序思想:顾名思义,选择排序就是将n个元素中最小的一个挑选出来放在第0号位置,然后将剩下的n-1个元素中挑选最小的元素放在第
    1号位置……经过n-1次挑选,可以将全部的元素回归到正确的位置。时间复杂度为O(n^2)。选择排序是一种不稳定排序算法,每次交换位置,都有可能会打乱原来元素的相对位置,所以是一种不稳定的算法。代码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    void selection_sort(int* &a,int n)
    {
    int i,j,pos,temp;
    for(i=0;i<n-1;i++)
    {
    pos=i;
    for(j=i+1;j<n;j++)
    {
    if(a[j]<a[pos])
    {
    pos=j;
    }
    }
    swap(a[pos],a[i]);// swap函数交换位置
    }
    }

插入排序

  • 排序思想:有排序完毕的一组数据a1,a2,……av,现在将第v+1个数据,插入到这组有序的数据中,需要找到第一个小于或等于a[v+1]的数,插入到其后。如果有n个元素,则需要进行n-1次插入操作,每次插入操作都不会打乱原来相等元素的相对位置,所以插入排序是稳定算法。时间复杂度为O(n^2)。代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void insert_sort(int* &a,int n)
    {
    int i,j,v;
    for(i=1;i<n;i++)
    {
    v=a[i];
    for(j=i-1;j>=0 && a[j]>v;j--)
    {
    a[j+1]=a[j];// 如果v的值小于a[j]的值,则将a[j]的值向后移动
    }
    a[j+1]=v; //将a[i]的值放入第一个小于或者等于a[i]的后面一个位置
    }
    }

快速排序

  • 排序思想:假设有n个元素的数组a[n],选择一个基准元素,一般选取a[0]。设置左右遍历索引,low=0,high=n-1。先从右往左遍历,直到遇到第一个小于a[0]的元素,然后交换位置;然后从左往右遍历,直到遇到第一个大于a[0]的元素,然后交换位置。如果high的值小于或者等于low,则遍历结束。此时low位置将序列分为两个部分[0,low-1]和[low+1,n-1],对这两个序列分别进行快速排序,即可得到排序结果。排序时间复杂度为O(n*logn)。是一个不稳定排序算法。代码如下:
    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
    void Quick_sort(int* &a,int left,right)
    {
    if(left<right)
    {
    return;
    }
    int low=left;
    int high=right;
    int temp=a[low];
    while(low<high)
    {
    while(high>low && a[high]=>temp)
    {
    high--;
    }
    swap(a[high],a[low]); //当high==low时,交换也没有影响,所以这里不需要判断,直接进行交换
    while(low<high && a[low]<=temp)
    {
    low++;
    }
    swap(a[high],a[low]);

    }
    Quick_sort(a,left,low-1);
    Quick_sort(a,low+1,right);
    }

堆排序

  • 排序思想:利用堆这种数据结构的特殊性,来进行排序。首先数组元素的小标索引应该从1开始,第i个节点左右子节点分别为i2和i2+1。首先自底向上建堆,然后取堆顶元素和最后一个元素进行交换,再对堆顶元素的位置进行调整。再去倒数第二个元素和堆顶元素进行交换,再次调整堆顶元素的位置,直到堆中只有一个数据为止。时间复杂度为O(n*logn)。代码如下:
    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
    void downAdjust(int* &a,int low,int high)
    {
    int i=low,j=i*2;
    while(j<=high)
    {
    if(j+1<=high && a[j+1]>a[j])
    {
    j=j+1;
    }
    if(a[i]<a[j])
    {
    swap(a[i],a[j]);
    }
    else
    {
    break;
    }
    }

    }
    void creatHeap(int* &a,int n)
    {
    for(int i=n/2;i>=1;i--)
    {
    downAdjust(i,n);
    }
    }
    void heapSort(int* &a,n)
    {
    creatHeap(a,n);
    for(int i=n;i>1;i--)
    {
    swap(a[i],a[1]);
    downAdjust(1,i-1);
    }
    }

希尔排序

-------------本文结束感谢您的阅读-------------
Donate comment here