快速排序和分治排序

快速排序让我看了很久,也折磨了我很长时间,因为大体上的思路我是有了,但是写代码时总是出现各种问题,要想把它调试出来对我个人来说还是有一定难度的,而且因为工作和偷懒的原因,导致之前调试不出来的错误放了很久,今天终于出来啦,还是有些小激动的哦,下面来分享一下我的代码并做一点点说明。

  要学会快速排序,就必须先要学会分治法,分治的思想是给一串乱序的数字(数字是假设,也可以是其他的对象,当然方法的参数可以自己定义哦,我在这里假设有一个整型的数组吧)然后给他一个中间数,分治法会把这些数字以给他的那个是中间数为分界分为两部分,一部分在中间数的左边,另一部分在右边,以这个数为分界点,两边的数现在还是乱序的,我给他定义的方法如下:

//left是数组的想分治部分的左端点,right是数组分治部分的总端点,如长度为10的数组,我想对前5个整数进行分治,则传0,4即可
    public int signalFenZhi(int left,int right){
        if(left<0||left>n-1||right<0||right>n-1){
            return -1;
        }
        int temp = test[left];
        int j=right;
        int i=left;

        while(i<j){
            while(test[j]>=test[left]&&i<j){
                j--;
            }
            while(test[i]<=test[left]&&i<j){
                i++;
            }

            if(i<j){
                temp = test[i];
                test[i]=test[j];
                test[j]=temp;
            }
        }

        if(i==j){
            temp = test[i];
            test[i]=test[left];
            test[left]=temp;
        }

        for(int m=0;m<n;m++){
            System.out.print(test[m]+"     ");
        }

        return i;

    }

当然,也可以把那个中间数当参数传进来,现在我只是单纯的以数组的传进来的第left数做为分界数,这只是为了说明。

  明白了分治,那么快速排序也就简单了,那就是对已经分为两部分的数再进行分治,依次类推,直到全部的数字都有序为止,代码如下:

public void quickSort(int left,int right){
        if(right-left<1){
            return ;
        }else{
            int point = this.signalFenZhi(left, right);
            System.out.println(point);
            //if(point!=left&&point!=right){
                quickSort(left,point-1);
                quickSort(point+1,right);
            //}
        }
    }

  快速排序的效率在众多的排序算法中是很优秀的,时间复杂度为O(N*log2n),但是如果分治的分界点选的不好的话,时间复杂度将会降到(n的平方),因为如果正好这个数组是有序的,然后我们每次都取传过来的最左端的数,那么效率就会很低,所以要避免发生这种情况,如果检测所有的选项,那么将会很花时间,所以一个折中的办法 ,就是把最左端的数和最右端的数加上一个中间的数,找到他们三个中间的数,以这个为分界值就会变的好一点,在上面方法的基础上,修改以后的代码如下,但是我做完了以后这样的做法不是很好,应该把分界值也当做传给分治的方法会好些,细心的朋友可以自己试一下,我在这里就不试了哈,大体上是一样的哦!

package com.jll;

public class FenZhi {

    int[] test;

    int n=10;

    public FenZhi(){
        test = new int[10];

        for(int i=0;i<n;i++){
            test[i]=(int)(Math.random()*100)+1;
            System.out.print(test[i]+"     ");
        }
        System.out.println();
    }

    public FenZhi(int n){
        if(n>0){
            this.n=n;
            test = new int[n];

            for(int i=0;i<n;i++){
                test[i]=(int)(Math.random()*100)+1;
            }
        }
    }

    public int signalFenZhiMajorizationFirst(int left,int right){
        if(left<0||left>n-1||right<0||right>n-1||left>=right){
            return -1;
        }

        if(right-left>=2){
            int middle = (right+left)/2;
            if(test[left]>test[middle]){
                int temp = test[middle];
                test[middle] = test[left];
                test[left] = temp;
            }
            if(test[left]>test[right]){
                int temp = test[left];
                test[left] = test[right];
                test[right] = temp;
            }
            if(test[middle]>test[right]){
                int temp = test[middle];
                test[middle] = test[right];
                test[right] = temp;
            }
            int temp = test[middle];
            test[middle] = test[left];
            test[left] = temp;
            int j=right-1;
            int i=left+1;

            while(i<j){
                while(test[j]>=test[left]&&i<j){
                    j--;
                }
                while(test[i]<=test[left]&&i<j){
                    i++;
                }

                if(i<j){
                    temp = test[i];
                    test[i]=test[j];
                    test[j]=temp;
                }
            }
            if(i==j){
                temp = test[i];
                test[i]=test[left];
                test[left]=temp;
            }

            /*if(i==j){
                temp = test[middle];
                test[middle]=test[i];
                test[i]=temp;
            }*/

            /*for(int m=0;m<n;m++){
                System.out.print(test[m]+"     ");
            }*/

            return i;
        }else {
            if(test[right]<test[left]){
                int temp = test[right];
                test[right] = test[left];
                test[left] = temp;
            }
            return right;
        }
    }

    public void quickSortMajorizationFirst(int left,int right){
        if(right-left<1){
            return ;
        }else{
            int point = this.signalFenZhiMajorizationFirst(left, right);
            System.out.println("the point is:"+point);
            quickSortMajorizationFirst(left,point-1);
            quickSortMajorizationFirst(point+1,right);
        }
    }

    public static void main(String[] args) {
        FenZhi f = new FenZhi();
        System.out.println(f.signalFenZhiMajorizationFirst(0, 9));
        System.out.println();
        f.quickSortMajorizationFirst(0,f.n-1);

        //f.quickSort(0,f.test.length-1);
        for(int i:f.test){
            System.out.print(i+" ");
        }
    }
}

代码运行如下:

17     95     40     64     18     78     23     73     84     40
1

the point is:4
the point is:1
the point is:3
the point is:7
the point is:6
the point is:9
17 18 23 40 40 64 73 78 84 95

以上就是我学习到的东西,记录一下,以备后面查阅

时间: 2024-08-26 22:07:06

快速排序和分治排序的相关文章

JavaScript 数据结构与算法之美 - 归并排序、快速排序、希尔排序、堆排序

1. 前言 算法为王. 想学好前端,先练好内功,只有内功深厚者,前端之路才会走得更远. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 JavaScript ,旨在入门数据结构与算法和方便以后复习. 之所以把归并排序.快速排序.希尔排序.堆排序放在一起比较,是因为它们的平均时间复杂度都为 O(nlogn). 请大家带着问题:快排和归并用的都是分治思想,递推公式和递归代码也非常相似,那它们的区别在哪里呢 ? 来阅读下文. 2. 归并排序(Merge Sort) 思想 排序一个数

啊哈!算法之快速排序与桶排序

啊哈!算法之快速排序与桶排序 1.快速排序算法 快速排序由 C. A. R. Hoare(东尼·霍尔,Charles Antony Richard Hoare)在1960 年提出,之后又有许多人做了进一步的优化.在数列种随机找出一个基准数,因为数列是杂乱的,所以取首项为基准数.从后往前找到比基准数大的位置,再从前往后找到比基准数小的位置,交换元素:右游标向前移动与左游标向后移动,它们相遇时用基准数的位置与相遇的位置交换.此时原来数列以相遇的位置被划分为了两个需要排序的数列,再次执行上述过程:当左

排序之分治排序

本算法是笔者研读算法导论分治内容伪代码所写,俗话说,它山之石,可以攻玉.算导对排序有非常详细的解释,而分治排序更是其中巧妙的一种排序算法.分治排序先把数组分成[l,mid]与(mid,r]两部分,多次划分直到每个部分只有1个元素.然后把这两部分进行比较排序.(由于上一次的排序,这两个分数组内部是有序的); 举例说数组:[7,3,5,4,6,2,1],定义INF = 100,大于数组每个元素 (1).第一次划分 [7,3,5,4] , [6,2,1] (2).对[7,3,5,4]进行第二次划分 [

排序:快速排序与选择排序

       在最近的学习中,对于排序算法进行了一定的学习,在这里对快速排序和选择排序的部分内容进行说明,其余内容在后期会进行补充,感谢大家提出宝贵意见. 宏定义如下: <strong><span style="font-size:18px;">#include <iostream> using namespace std; #define M 21 typedef int SqList[M];</span></strong>

算法有插入排序,堆排序,合并排序,快速排序和stooge排序

比较的算法有插入排序,堆排序,合并排序,快速排序和stooge排序, 先说一下比较结果 1,比较插入和stooge排序,stooge的表现如此之差,数组大小在2000时 InsertSort VS StoogeSort 's Running Time:     16ms:47672ms; Terribly! Isn't It? 所以在后面的比较中,没有带stooge这个垃圾算法 2,插入排序,堆排序,合并排序,快速排序运行时间对比 (网易博客的表格功能太差了,不爽,只好以文本对齐展现给大家了):

HDU 1157 Who&#39;s in the Middle (快速排序 or 任意排序)

Who's in the Middle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 9903    Accepted Submission(s): 4736 Problem Description FJ is surveying his herd to find the most average cow. He wants to k

快速排序和计数排序API

听说有十大排序算法,先学习一下快速排序和计数排序算法. 一:快速排序 快速排序主要就是每一个找到当前取出来的标尺的数的位置,然后把小于它的数放在左边(从小到大排),把大于它的数放在右边.然后利用递归分左右继续找位置放数字,这个过程有点类似之前的根据前序和中序找后序的题目.递归的出口就是当只有一个数的时候就不需要排了.取出来的位置就是他的位置. 代码: 找每一次的位置: int findpos(int l,int r){ int temp = data[l]; int i = l, j = r;

C++线性表通过结构体实现操作和结构体字符串快速排序和shell排序结合

#include<iostream> #include<string> #define ml 10 using namespace std; typedef struct{//定义Data数据项 std::string name; long num; }Data; struct Link{//定义结构体 Data data[ml+1]; int length; }L; void initLink(Link *p){//初始化,即便有数据可以覆盖写入增加效率 p->length

快速排序 VS compare排序

为了方便  ,我把bean写成了内部类 测试结论 ,快速排序吊打compare排序 ,可以自行测试 1 //测试调用 2 public static void main(String[] args) { 3 List<Student> list = new ArrayList<Student>(); 4 new test().add(list); 5 //记录旧数据 确定俩次排序使用的是同一数据 6 List<Student> stus = new ArrayList&