• 纯手撸——快速排序


    运用递归思想:

    • 随机找主元(一般为第一个、中间、最后一个元素)
    • 对数组进行分割处理,小的元素放在主元前面,大的放在后面
    • 在对小的元素部分再取主元再分割,递归下去(同理大的元素部分)
    • 建议:下拉看图~

    一张图归纳我的上述思想:

    重难点操作:分割 图片参考美文——不要在问我快速排序,写的实在太好了!

    1️⃣单向调整

    选一个主元,如选最后一个为主元。假设数组arr的范围为[left, right],即起始下标为left,末尾下标为right。源数组如下:

    然后可以用一个下标 i 指向 left,即 i = left ;用一个下标 j 也指向left,即j = left

    接下来 j 从左向右遍历,遍历的范围为 [left, right-1] ,遍历的过程中,如果遇到比主元小的元素,则把该元素与 i 指向的元素交换,并且 i = i +1

    如:当j指向1时,1比4小,此时把i和j指向的元素交换,之后 i++

    就这样让j一直向右遍历,直到 j = right

    遍历完成之后,把 i 指向的元素与主元进行交换,交换之后,i 左边的元素一定小于主元,而 i 右边的元素一定大于或等于主元。这样,就 i 完成了一次分割了

    有了上面的引导,一切真的非常简单了,直接开写吧:

    int partition(int a[],int left,int right)
    {
        int tmp,pivot; //tmp作为临时存储,pivot指向主元
        int i,j; 
        pivot=a[right]; //照着图片写的,主元取最后一个元素
        for(j=left;j<right;j++)
        {
        	if(a[j]<pivot)
        	{
        		//swap
        		tmp=a[i];
        		a[i]=a[j];
        		a[j]=tmp;
        		i++; //记得i要移一下哟
        	}
        }
        //i指向的元素与主元元素交换
        a[right]=a[i];
        a[i]=pivot;
        return i;
    }
    void QuickSort(int a[],int left ,int right)
    {
     	int center;
     	//至少存在两个元素
     	if(left<right)
     	{
     		center=partition(a,left,right);
     		QuickSort(a,left,center-1); //左区间递归
     		QuickSort(a,center+1,right); //右区间递归
     	}
    }
    

    2️⃣双向调整

    还是用我的第一个元素充当主元吧。哈哈,源数组如下:

    然后用令变量i = left + 1,j = right。然后让 i 和 j 从数组的两边向中间扫描

    i 向右遍历的过程中,如果遇到大于或等于主元的元素时,则停止移动,j向左遍历的过程中,如果遇到小于或等于主元的元素则停止移动

    当i和j都停止移动时,如果这时i < j,则交换 i, j 所指向的元素。此时 i < j,交换8和3

    然后继续向中间遍历,直到i >= j

    此时i >= j,分割结束。

    最后在把主元与 j 指向的元素交换(当然,与i指向的交换也行)

    这个时候,j 左边的元素一定小于或等于主元,而右边则大于或等于主元。

    到此,分割调整完毕

    有了上面的引导,一切又非常简单了,直接开写吧:

    int partition(int a[],int left,int right)
    {
    	int pivot=a[left]; //这次把主元定在第一个元素
    	int i=left+1; //i指向主元旁第一个元素
    	int j=right;
    	while(i<j) //从两端向中间扫描,直到i=j为止
    	{
    		//从左向右扫描
    		while(i<j&&a[i]<=pivot) i++;
    		//从右向左扫描
    		while(i<j&&a[j]>=pivot) j--;
    		if(i>=j)
    			break;
    		//swap
    		int tmp=a[i];
    		a[i]=a[j];
    		a[j]=tmp;
    	}
    	//a[j]或a[i]与主元交换
    	a[left]=a[j];
    	a[j]=pivot;
    	return j;
    }
    
    void QuickSort(int a[],int left ,int right)
    {
     	int center;
     	//至少存在两个元素
     	if(left<right)
     	{
     		center=partition(a,left,right);
     		QuickSort(a,left,center-1); //左区间递归
     		QuickSort(a,center+1,right); //右区间递归
     	}
    }
    

    一点心得:对于这种算法,其实如果直接读书看代码或记忆真的还挺有难度,不妨记住实现的步骤图,跟着图自行拟出代码即可。

  • 相关阅读:
    cytoscape-d3-force api
    Python基础编程 模块的引入与定义
    更改Ubuntu内核版本
    Jupyter Notebook默认路径修改
    YJZH 前端部署记录 CentOS+Nginx+Vue
    dotnet core webapi centos 服务自启动
    Linux修改时区
    空间数据实战(1)——MySQL
    记录window.sessionStorage的一个小坑
    ElementUI默认表单项el-form-item间距修改
  • 原文地址:https://www.cnblogs.com/wangzheming35/p/13489464.html
Copyright © 2020-2023  润新知