• 让算法会说话之高速排序


            转载请注明出处:http://blog.csdn.net/ruoyunliufeng/article/details/30729523


           高速排序是由东尼.霍尔所发展的一种排序算法。在平均状况下,排序n 个项目要O(n log n)次比較。在最坏状况下则须要Ο(n2)次比較,但这样的状况并不常见。

    其实,高速排序通常明显比其它Ο(n log n) 算法更快,由于它的内部循环(inner loop)能够在大部分的架构上非常有效率地被实现出来。


    一.排序步骤总结:

    高速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。

    1.用三数中值切割法找出枢纽元(基准)。

    2.又一次排序数列,全部元素比基准值小的摆放在基准前面,全部元素比基准值大的摆在基准的后面(同样的数能够到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。

    3.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。


    二.高速排序算法

    /***************************************************************
    *版权全部 (C)2014,公司名称。
    *
    *文件名:高速排序法
    *内容摘要:无
    *其他说明:无
    *当前版本号:V1.0
    *作   者:若云流风
    *完毕日期:2014.6.14
    ***************************************************************/
    #include <stdio.h>
    
    #define N       (14)
    #define cutoff  (3)    //截止范围小于等于3
    
    void disp(void);
    
    int a[N]={8,14,3,12,10,7,5,1,9,4,11,13,2,6};
    
    /*交换函数*/
    void Swap(int *a, int *b)
    {
            int t;
            t = *a;
            *a = *b;
            *b = t;
    }  
    
    /*三种值切割*/
    int Median3(int a[], int left, int right)
    {
        //取数据的头、尾和中间三个数。并对他们进行排序
        //排序结果直接保存在数组中
        int centre = (left + right)/2;
        if(a[left] > a[centre])
            Swap(&a[left], &a[centre]);
        if(a[left] > a[right])
            Swap(&a[left], &a[right]);
        if(a[centre] > a[right])
            Swap(&a[centre], &a[right]);
        //把中值,即枢纽与数组倒数第二个元素交换
        Swap(&a[centre], &a[right - 1]);
        return a[right - 1];//返回枢纽
    }
    
    /*高速排序程序*/
    void QSort(int a[], int left, int right)
    {
        //假设须要排序的数据大于3个则使用高速排序
        if(right - left >= cutoff)
        {
            //取得枢纽的值
            int centre = Median3(a, left, right);
            int i = left;
            int j = right - 1;
            while(1)
            {
                /*向后扫描数组,找出大于枢纽元素的元素
                * 因为在选择枢纽时。已经把比枢纽值大的数据放在right位置
                * 所以不会越界
    			*/
                while(a[++i] < centre);                               //当i大于等于中枢元素时候跳出循环
    
                /*向前扫描数组,找出小于枢纽元素的元素
                * 因为在选择枢纽时,已经把比枢纽值小的数据放在left位置
                * 所以不会越界
    			*/
                while(a[--j] > centre);
                //把比枢纽小的数据放在前部,大的放到后部
                if(i < j)
    			{
                    Swap(&a[i], &a[j]);
                    printf("
    高速排序结果: ");
    			    disp();             //打印
    			}
                else
    			{
    				//disp();
                    break;
    				
    			}
                
            }
    
            Swap(&a[i], &a[right - 1]); //还原枢纽元素
    		printf("
     还原枢纽元素后结果: ");
            disp();
    
            QSort(a, left, i - 1);
            QSort(a, i + 1, right);
        }
        else                   //假设要排序的数据非常少。少于等于3个,则直接使用冒泡排序
        {
            InsertionSort(a+left, right - left + 1);
        }
    }
    
    /*插入排序*/
    int InsertionSort(int a[],int M)  
    {
    	int j,p,temp;
    
    	for(p=1;p<M;p++)
    	{
    		temp=a[p]; //a[p]和左面的有序数列去比較
    
    /*j>0保证不溢出,因为当j=0时啊a[j-1]非法。用a[p]分别与左面的值相比較
    **假设a[p]小的话则互换位置,
    */
    
    		for(j=p; j>0 && a[j-1]>temp;j--)     
    		{
    			a[j]=a[j-1];
            } 
    		a[j]=temp;
    	}
    	printf("
    插入排序结果: ");
        disp();
    
    } 
    
    /*输出函数*/
    void disp(void)
    {
         int i;
    
         printf("
    排序结果: 
    ");
    	 for(i=0;i<N;i++)
    	 {
    		printf("%d", a[i]);
    		printf("  ");
    	 }
    	
    }
    
    int main(void)
    {
    	QSort(a , 0, N-1);
       // disp();
    	return 0;
    
    }



    三.算法会说话

    1.输出结果


    2.整体过程分析

          a.三数中值切割法

                                                           8,14,3,12,10,7,5,1,9,4,11,13,2,         

            红色的三个数字依照大小顺序排好。中间的那个元素叫做中枢元,将中枢元和倒数第二个元素互换位置后返回。

                                                           5,14,3,12,10,7,2,1,9,4,11,13,6,8

        b.高速排序

                                                           5,14,3,12,10,7,2,1,9,4,11,13,6,8

                        (找出比中枢元大的)     i  -->                                  <--j(找出比中枢元小的)

                                                           5,14,3,12,10,7,2,1,9,4,11,13,6,8

                                                                 i    <--交换-->        j

                                                         

                                                                    i   <--交换-->  j         

                                                   

                                                                          i <--> j 

                                                    

                                                                          j    i                                                                      i>j退出

                             还原枢纽元素 

                       注意此时产生的结果就是以枢纽元素为分界线,左面的所有小于枢纽元素,右面的所有大于枢纽元素

                    先对6前面的排序:

                                                                 5,   4,   3,   1,   2         

                                                                2,   4,   1,    3,    5

                                                                       i      j


                                                                           

                                                               

                                                              2,1(插入排序)        3             4  ,5(插入排序)                                                      

                                                            

                   6后面的排序和前面类似。故不再详细分析。


    參考:1.维基百科

               2.数据结构与算法分析---C语言描写叙述     Mark Allen Weiss 著
  • 相关阅读:
    CSS快速入门
    Kafka (一) 核心概念
    软件工程模型
    函数式编程
    spark计算操作整理
    HBase 文件合并
    HBase 数据存储结构
    目的论浅谈
    PHP8的注解
    JS的移入移除
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/6694738.html
Copyright © 2020-2023  润新知