【算法导论】快速排序

快速排序

        快速排序的最坏运行时间为O(n2),虽然这最坏情况的时间复杂度比较大,但快速排序通常是用于排序的最佳实用选择,这是因为其平均性能相当好,平均时间复杂度为O(nlogn),并且O(nlogn)中的隐含常数因子很小。另外,它能够进行就地排序,因此在虚拟内存中也能较好的运行。

        快速排序算法的性能:其运行时间与划分是否对称有关,而是否对称与主元的选取有关。从渐进的意义上讲,如果对称,就和合并的算法一样快,如果不对称,就和插入排序算法一样慢。需要注意的是,但每次递归是都是按照常数比例划分时,从渐进意义上看,与对称划分效果一样,都是nlgn.

        和合并排序一样,快速排序也是基于分治模式的。分治过程分为三个步骤:分解、解决、合并。

        快速合并的基本思想:从要排序的序列中,随意取一个值作为主元,从而将序列以此分为大于和小于主元的两个子序列,然后重复上述过程(递归调用)。

下面以一个分解过程为例:

        假设要排序的序列为:2、8、7、1、3、5、6、4。首先,随便选取主元,在这里我们选择4;其次,通过分解将原序列分为子序列2、1、3和子序列7、5、6、8;最后分别以两个子序列为原序列,不断重复上述过程。分解过程的图解如下:



  具体实现如下:

  • 分解过程:
    /**************************************************\
    函数功能:将原数组分成全大于和全小于x的两个子数组
    输入:原始数组、要对数组进行操作的起始和结束下标
    输出:x在数组中的位置
    \**************************************************/
    
    int Partition(int*Array,int n,int p,int r)
    {
    	int x=Array[r];
    	int i=p-1;
    	int temp=0;
    	for(int j=p;j<=r-1;j++)
    	{
    		if(Array[j]<=x)
    		{
    			i++;
    			temp=Array[i];
    			Array[i]=Array[j];
    			Array[j]=temp;
    		}
    	}
    	temp=Array[i+1];
    	Array[i+1]=Array[r];
    	Array[r]=temp;
    
    	return i+1;
    }

  • 递归过程:

    /**************************************************\
    函数功能:递归调用分解函数,进行快速排序
    输入:原始数组、要对数组进行操作的起始和结束下标
    输出:无
    \**************************************************/
    
    void QuickSort(int* Array,int n,int p,int r)
    {
    	int q=0;
    	if(p<r)
    	{
    		q=Partition(Array,n,p,r);
    		QuickSort(Array,n,p,q-1);
    		QuickSort(Array,n,q+1,r);
    	}
    }


    完整实例:

    #include<stdio.h>
    
    int Partition(int*Array,int n,int p,int r);
    void QuickSort(int* Array,int n,int p,int r);
    
    void main()
    {
    	int Array[8]={2,8,7,1,3,5,6,4};
    	int n=sizeof(Array)/sizeof(int);
    	int p=0;
    	int r=n-1;
    	QuickSort(Array,n,p,r);
    
    	for(int k=0;k<n;k++)
    		printf("%d ",Array[k]);
    	printf("\n");
    }
    
    /**************************************************\
    函数功能:将原数组分成全大于和全小于x的两个子数组
    输入:原始数组、要对数组进行操作的起始和结束下标
    输出:x在数组中的位置
    \**************************************************/
    
    int Partition(int*Array,int n,int p,int r)
    {
    	int x=Array[r];
    	int i=p-1;
    	int temp=0;
    	for(int j=p;j<=r-1;j++)
    	{
    		if(Array[j]<=x)
    		{
    			i++;
    			temp=Array[i];
    			Array[i]=Array[j];
    			Array[j]=temp;
    		}
    	}
    	temp=Array[i+1];
    	Array[i+1]=Array[r];
    	Array[r]=temp;
    
    	return i+1;
    }
    
    /**************************************************\
    函数功能:递归调用分解函数,进行快速排序
    输入:原始数组、要对数组进行操作的起始和结束下标
    输出:无
    \**************************************************/
    
    void QuickSort(int* Array,int n,int p,int r)
    {
    	int q=0;
    	if(p<r)
    	{
    		q=Partition(Array,n,p,r);
    		QuickSort(Array,n,p,q-1);
    		QuickSort(Array,n,q+1,r);
    	}
    }

    注意:我是在vs2008上运行的,与vc 6.0有点区别,主要是循环体中的循环变量的作用域,出错体现在循环变量的重复定义上。例如:在vs2008或vs2010上,程序为:

    #include<stdio.h>
    void main()
    {
    int i=0;
    for(int i=0;i<5;i++)
    printf("%d ",i);
    }

    则在VC 6.0上需改为:

    #include<stdio.h>
    void main()
    {
    int i=0;
    for(i=0;i<5;i++)
    printf("%d ",i);
    } 



    原文:http://blog.csdn.net/tengweitw/article/details/9627659

    作者:nineheadedbird


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
算法导论是计算机科学中非常重要的一门课程,它涵盖了计算机算法的设计、分析与应用。期末复习是为了加深对所学知识的理解和掌握,为考试做好充分准备。 使用Python语言进行算法导论的复习是一种很好的选择。Python是一种强大且易于上手的编程语言,具有简洁的语法和丰富的库支持。下面是几个复习的重点: 1. 熟悉Python的基本语法和数据结构:掌握Python的基本数据类型如列表、字典和集合,并了解它们的操作与性能。 2. 掌握常见排序算法:复习插入排序、归并排序、快速排序等常见的排序算法,并能够灵活应用它们解决实际问题。 3. 熟悉图算法:学习图的表示方法,以及广度优先搜索(BFS)和深度优先搜索(DFS)等基本的图算法。 4. 熟练应用动态规划算法:了解动态规划的基本思想,复习使用动态规划解决背包问题、最长公共子序列等典型问题。 5. 学习贪心算法:了解贪心算法的概念和特点,熟悉使用贪心算法解决活动选择、哈夫曼编码等问题。 6. 熟练掌握分治算法:复习分治算法的基本思想和应用,熟悉使用分治算法解决最大子数组和矩阵乘法等问题。 7. 复习基本的算法分析方法:熟悉时间复杂度和空间复杂度的概念,掌握算法的渐进分析方法。 在复习过程中,可以通过参考教材、课堂笔记和习题集等资料进行练习和巩固所学知识。此外,可以参考一些算法导论的相关网上资源和在线教育平台上的课程进行深入学习。最重要的是,要坚持刷题,多进行实际编码练习,巩固所学算法的理解和应用能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值