面试必备:排序算法汇总(c++实现)

排序算法主要考点: 7种排序

              冒泡排序、选择排序、插入排序、shell排序、堆排序、快速排序、归并排序

以上排序算法是面试官经常会问到的算法,至于其他排序比如基数排序等等,这里不列举。

以下算法通过c++实现,开发工具Visual Studio 2012:代码下载

 

一、排序 :将杂乱无章的数据元素,通过一定的方法按关键字顺序排列的过程

  排序分为内部排序、外部排序;

  若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序

  反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中完成,则称此类排序问题为外部排序

   假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,

   即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;

     否则称为不稳定的。

  1. 冒泡排序

    时间复杂度:最好的情况:表本身就是有序的,n-1次比较,时间复杂度为O(n);最坏的情况:表是逆序的,此时需要比较 1+2+3+…(n-1) = (n(n-1))/2,时间复杂度为O(n2)

    优点:简单、稳定

    缺点:慢,每次只能移动相邻两个数据,效率低

    c++实现:

 1             //冒泡排序
 2             void Bubble_Sort(int *list,int count)
 3             {
 4                 int flag = true;
 5                 int i = 0,j = 0;
 6                 for(i=0;i<=count&&flag;i++)
 7                 {
 8                     flag = false;
 9                     for(j=count -1;j>=i;j--)
10                     {
11                         if(list[j]<list[j-1])
12                         {
13                             swap(list[j],list[j-1]);
14                             flag = true;
15                         }
16                     }
17                 }
18 
19             }

  2. 选择排序

    时间复杂度:O(n2)  :无论最好、最坏情况,都需要比较 (n(n-1))/2次,最好的情况交换次数为0,最坏的情况交换次数为n-1

    优点:交换移动数据次数相当少,性能上略优于冒泡排序

    缺点:效率低

    c++实现:

 1         //选择排序
 2         void Select_Sort(int *list,int count)
 3         {
 4             int min,i,j;
 5             for(i=0;i<count;i++)
 6             {
 7                 min = i;
 8                 for(j=i+1;j<count;j++)
 9                 {
10                     if(list[i]>list[j])
11                     {
12                         min = j;
13                     }
14                 }
15                 if(min!=i)
16                 {
17                     swap(list[i],list[min]);
18                 }
19 
20             }
21         }

  3. 插入排序

    时间复杂度:最好情况:表本身就是有序的,比较次数是n-1次,没有移动记录,时间复杂度为O(n);最坏情况:表本身是无序的,比较次数是2+3+4+…+n = (n+2)(n-1)/2,移动次数也达到最大

    值为 (n+4)(n-1)/2次,所以时间复杂度为O(n2);如果根据概论相同的原则,平均比较和移动次数约为n2/4;

    优点:比选择,冒泡排序性能要好一些

    缺点:效率较低

    c++实现:

 1         //插入排序
 2         void Insert_Sort(int *list,int count)
 3         {
 4             int temp;/*此处充当哨兵,不在list数组里面单独占一个单位*/
 5             int i,j;
 6             for(i=1;i<count;i++)
 7             {
 8                 if(list[i]<list[i-1])
 9                 {
10                     temp = list[i];
11                     for(j=i-1;list[j]>temp&&j>=0;j--)
12                     {
13                         list[j+1] = list[j];
14                     }
15                     list[j+1] = temp;
16                 }
17             }
18         }    

  4. shell排序

    时间复杂度:O(n3/2)

    优点:跳跃式移动,使得排序效率提高

    缺点:不是一种稳定的排序算法

    c++实现:

 1        //shell排序
 2         void Shell_Sort(int *list,int count)
 3         {
 4             int i,j;
 5             int temp;
 6             int increment = count;
 7             do
 8             {
 9                 increment = increment/3+1;
10                 for(i = increment;i<count;i++)
11                 {
12                     if(list[i]<list[i-increment])
13                     {
14                         temp = list[i];
15                         for(j=i-increment;j>=0&&list[j]>temp;j-=increment)
16                         {
17                             list[j+increment] = list[j];
18                         }
19                         list[j+increment] = temp;
20                         
21                     }
22                     
23                 }
24 
25             }while(increment>1);
26         }

  5. 堆排序

    时间复杂度:O(nlogn)

    优点:性能上远远超过冒泡、选择、插入的时间复杂度O(n2)

    缺点:不是一种稳定的排序算法

    c++实现:

 

//调整为一个堆
void Heap_Adjust(int *list,int s,int m)
{
    int temp = list[s];
    for(int j=2*s+1;j<=m;j = 2*j+1)
    {
        if(list[j]<list[j+1]&&j<m)
        {
            j++;
        }
        if(temp>list[j])
            break;
        list[s] = list[j];
        s = j;
    }
    list[s] = temp;
}

//堆排序
void Heap_Sort(int *list,int len)
{
    //创建一个大顶堆
    for(int s = len/2-1;s>=0;s--)
    {
        Heap_Adjust(list,s,len-1);
    }

    //排序
    for(int i = len-1;i >= 1;i--)
    {
        swap(list[0],list[i]);
        Heap_Adjust(list,0,i-1);
    }

}

 

 

 

    6. 归并排序

    时间复杂度:O(nlogn)

    优点:效率高、稳定

    缺点:占用内存较多

    c++实现:

 

//将有个有序数组排序
void Merge(int *list,int start,int mid,int end)
{
    const int len1 = mid -start +1;
    const int len2 = end -mid;
    const int len = end - start +1;
    int i,j,k;


    int * front = (int *)malloc(sizeof(int)*len1);
    int * back = (int *)malloc(sizeof(int)*len2);

    for(i=0;i<len1;i++)
        front[i] = list[start+i];
    for(j=0;j<len2;j++)
        back[j] = list[mid+j+1];

    for(i=0,j=0,k=start;i<len1&&j<len2&&k<end;k++)
    {
        if(front[i]<back[j])
        {
            list[k] = front[i];
            i++;
        }else
        {
            list[k] = back[j];
            j++;
        }
    }
    while(i<len1)
    {
        list[k++] = front[i++];
    }
    while(j<len2)
    {
        list[k++] = back[j++];
    }

}

 

      //归并排序
        void Merge_Sort(int *list,int count)
        {
            MSort(list,0,count-1);
        }
        //归并排序
        void MSort(int *list,int start,int end)
        {
            
            if(start<end)
            {
                int mid = (start+end)/2;
                MSort(list,0,mid);
                MSort(list,mid+1,end);
                Merge(list,start,mid,end);
            }

        }        

  7. 快速排序

    时间复杂度:O(nlogn)(平均情况)

    优点:目前来说最快的排序算法,现在的快排算法大多是快速排序算法的改进算法

    缺点:跳跃式,不稳定

    c++实现:

        //快速排序
        void Quick_Sort(int *list,int count)
        {
            Qsort(list,0,count-1);
        }
       //快速排序
        void Qsort(int *list,int low,int high)
        {
            int pivot;
            if(low<high)
            {
                pivot =Partition(list,low,high);
                Qsort(list,low,pivot-1);
                Qsort(list,pivot+1,high);
            }

        }
     int Partition(int *list,int low,int high)
        {
            int pivotKey;
            pivotKey = list[low];
            while(low<high)
            {
                while(low<high&&list[high]>=pivotKey)
                {
                    high--;
                }
                swap(list[low],list[high]);
                while(low<high&&list[low]<=pivotKey)
                {
                    low++;
                }
                swap(list[low],list[high]);
            }
            return low;
        }

附:

     void swap(int& a,int& b)
        {
            int temp = a;
            a = b;
            b = temp;
        }

 

总结:排序:  插入排序类: 插入排序,希尔排序

        选择排序类: 选择排序,堆排序

        交换排序类: 冒泡排序,快速排序

        归并排序类: 归并排序

 

 

              

    原文作者:野原新之助
    原文地址: https://www.cnblogs.com/daimingming/p/3219744.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞