让算法会说话之快速排序

        转载请注明出处: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("\n快速排序结果: ");
			    disp();             //打印
			}
            else
			{
				//disp();
                break;

			}

        }

        Swap(&a[i], &a[right - 1]); //还原枢纽元素
		printf("\n 还原枢纽元素后结果: ");
        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("\n插入排序结果: ");
    disp();

} 

/*输出函数*/
void disp(void)
{
     int i;

     printf("\n排序结果: \n");
	 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,6

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

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 著

让算法会说话之快速排序,布布扣,bubuko.com

时间: 2024-10-13 01:41:35

让算法会说话之快速排序的相关文章

算法整理(四):浅析快速排序的优化问题

前文介绍了快速排序的单边扫描和双边扫描,但么有做对比,今天来简单分析下. 一.单边扫描的缺点 单边扫描最大的缺点是每次都要交换,如果一个数组是 5 4 3 2 1,用单边扫描的话,则从4开始,4要和4交换一次,3要和3交换一次,依次类推,这种无意义的操作.正因此用双边扫描会更好,第一趟只需交换一次,就能得到1 4 3 2 5这样的数组.但双边扫描也是可以进一步优化的. 二.双边扫描的优化 优化一:对key值得选取应该使用随机选取的原则,而非第一个数字.意义大家都懂得. 优化二:前文的方法是挖坑法

让算法会说话之归并排序

转载请注明出处:http://blog.csdn.net/ruoyunliufeng/article/details/27570953 归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作.归并排序算法依赖归并操作. 一.归并排序算法 /*************************************************************** *版权所有 (C)2014,公司名称. * *文件名称:归并排序法 *内容摘要:无 *其它说明:无 *

浅谈算法和数据结构: 四 快速排序

原文:浅谈算法和数据结构: 四 快速排序 上篇文章介绍了时间复杂度为O(nlgn)的合并排序,本篇文章介绍时间复杂度同样为O(nlgn)但是排序速度比合并排序更快的快速排序(Quick Sort). 快速排序是20世纪科技领域的十大算法之一 ,他由C. A. R. Hoare于1960年提出的一种划分交换排序. 快速排序也是一种采用分治法解决问题的一个典型应用.在很多编程语言中,对数组,列表进行的非稳定排序在内部实现中都使用的是快速排序.而且快速排序在面试中经常会遇到. 本文首先介绍快速排序的思

#排序算法#【4】快速排序

快速排序法是对冒泡排序的一种改进,本来是要和冒泡排序写在一个文章里的,不过前两天刚开始在递归调用的时候没有完全理解,昨天晚上google了一把发现原来自己理解错了,我看的这个教材没有写清楚,今天早上调试了一把终于成功. 快速排序算法的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. 快速排序使用分治策略来把待排序数据序列分为两个子序列

让算法会说话之冒泡排序

转载请注明出处:http://blog.csdn.net/ruoyunliufeng/article/details/25972987 冒泡排序:它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端. 一.冒泡排序算法以及优化 1.常用代码 /**************************************

几种排序算法的C++实现——快速排序、堆排序、基数排序

排序算法是非常常见的面试笔试问题,考查的一个人的基本功,本文将一些排序做了C++的实现,就当是做个学习总结吧. 1.快速排序 快速排序的中心是填坑法,取一个数(这里选取第一个数)作为基准数temp,从队尾开始寻找第一个比基准数小的数a[j],交换a[j]和temp,然后队首开始查找第一个比temp大的数a[i],交换之,遍历的结果是当i>=j时,temp左边的数都小于temp,后边的数都大于temp,这个有点像归并排序.最后利用递归调用完成排序,代码如下: 1 void QuickSort(in

让算法会说话之希尔排序

这是我参照之前在iOS项目中用过的一个不规则形状按钮的第三方Button,这里用Cocos2d-x实现一个相似功能的按钮. 原文地址:http://blog.csdn.net/qqmcy/article/details/26161339 代码下载:http://download.csdn.net/detail/qqmcy/7365843 使用方法: .h // // TestScene.h // maptest // // Created by 杜甲 on 14-5-18. // // #ifn

让算法会说话之插入排序

转载请注明出处:http://blog.csdn.net/ruoyunliufeng/article/details/26059615 插入排序:它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入. 一.插入排序算法 /*************************************************************** *版权所有 (C)2014,公司名称. * *文件名称:插入排序法 *内容摘要:无 *其它说明:无 *当前版

算法导论——lec 07 快速排序

一. 快速排序的描述 1. 快速排序是一种原地排序的算法,最坏情况下的时间复杂度为Θ(n^2),期望的运行时间为Θ(n logn),且其中隐含的常数因子较小. 2. 快速排序分三个步骤: 分解:数组A[p...r]被划分成两个数组A[p...q-1]和A[q+1...r],使得A[p...q-1]中的元素都小于等于A[q],A[q+1...r]中的元素都大于等于A[q].下标q在这个划分过程中计算. 解决:递归调用快速排序,对子数组A[p...q-1]和A[q+1...r]进行排序. 合并:两个