博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据结构与算法-----快速排序
阅读量:5132 次
发布时间:2019-06-13

本文共 3883 字,大约阅读时间需要 12 分钟。

  快速排序的原理是,每一次排序都找一个基准数,然后比基准数大的元素,放到基准数的右侧,比基准数小的元素放到基准的左侧,那么最核心的就是找到基准数的位置, 把基准数放到它应在的位置。现在我们对6 1 2 7 9 3 4 5 10 8 进行排序。

   首先找一个基准数,就是一个参照数, 用来进行比较。 为了简单起见,那就选第一个数6作为基准数好了,我们要做的事就是找到6 所在的位置,让6右边的数比它大,让6左边的数比它小 如下形式。

  3 1 2 5 4 6 7 9 10 8 

  我们怎么才能找到6 应该在的位置呢? 方法很简单,那就是从序列3 1 2 5 4 6 7 9 10 8 的两端进行探测。先从序列的右侧进行查找, 只要找到一个比基准数6大的数就停下来,然后再从序列的左边进行查找,只要找到一个比基准数6小的数就停止,这时交换它们两个的位置。 这时我们可以用两个变量i 和 j 分别指向序列的最左侧和最右侧。刚开始的时候,变量i 指向序列的最左边,就是数字6, j指向序列的最右边,指向数字8, 如下图所示

 

  首先j 从右向左移动,只要找到比6小的数就停止下来,j到了5的位置。这时i 再从左向右出发, 只要找到比6大的数就停止下来,所以它到了7的位置

  这时交换这两个数的位置

 

  第一次交换结束,序列变成了 6, 1, 2, 5, 9 , 3 5, 7, 10, 8.  数字5 和数字7进行了交换。现在j 接着向左走,到了4的位置就停下来,因为4也比6小。这时i 接着从左向右走,到了9的位置,9比6 大。

  然后再交换它们的位置

  又一次的交换结束了,我们的序列变成了 6 1 2 5 4 3 9 7 10 8 。 现在接着继续探测, j 接着向左走,到了3的位置就停止了,它比6小。 接着i向右走,突然发现i和j 相遇了,都到了3的位置上,表明探测结束了。

  基准数6的位置应该在3的位置上,我们来交换3和6位置

  到这时我们终于找到的6的位置,比6大的数在它的右侧,比6小的数在它的左侧。

  现在用代码把上面的步骤实现一下,我们有10个数字,用数组给它们存起来是最好不过了。我们要声明一个变量let arr = [6, 1, 2, ..]; 其次声明一个函数quickSort 用于快速排序。在函数内部声明4个变量:base 用于保存基准数, 还有上面的进行移动的i, j. 进行交换的变量t. 我们首先要做的是让i, j 分别指向数组的头部或末尾, 头部就是0, 但是末尾要传入进来,所以函数需要两个参数left, right. 现在要做的就是移动和比较,移动和比较的过程肯定是循环,而循环的结束条件是 i 和 j 相等, 只要i 和j 不相等就要循环。

let arr = [6, 1, 2, 7, 9, 3, 4, 5, 10, 8];        // 函数接受两个参数left, right, 指定排序时进行移动的 i, j 的位置        function quickSort(left, right) {            let base;   // 基准数变量            let i, j;   // 进行移动的变量,寻找值            let t;      // 用于进行交换            base = arr[left];   // 序列最左边的数设为基准数            i = left;           // 把序列最左边的数赋给i            j = right;          // 把序列最右边的数赋值给j            // 只要i 和 j 不相等就要循环            while (i !== j) {                // 右侧的j 向左移动,找到一个比基准数小的值就停止                while (arr[j] >= base && i < j) {                    j--;                }                // 左侧的 i 向右移动,找到一个比基准数大的值就停止                while (arr[i] <= base && i < j) {                    i++;                }                // 当 i 和j 都找到值以后,交换它们两个位置,当然 i < j 时,如果i等于j,则是基准数的交换了                 if (i < j) {                    t = arr[i];                    arr[i] = arr[j];                    arr[j] = t;                }            }            // 当循环结束后,我们发现基准数应有的位置, 就是i的位置            arr[left] = arr[i];            arr[i] = base;        }

  现在我们找到了基准数的位置,同时也把原来的序列分成了两个序列, 左边的序列 3 1 2 5 4; 右边的序列9 7 10 8; 可以分别对两个序列进行排序。我们还是采用找基准数的方法进行排序,这时对于左边的序列我们还是把第一个数3作为基准数,然后把序列的最左侧的值3赋给i, 最右边的数4赋值给j,  进行移动。 j 是从右向左移动, 到了2的位置,这时i 再向右移动,i 和 j 重合, 把3,2 位置进行交换 2 1 3 5 4.   

  现在3 又把序列分为了两个部分,2 1 和 5 4,  现在再把2 1 找基准数的方式进行排列。2 作为基准数,然后把序列2,1 最左边的数2赋值 i ,最右边的数1 赋值给j 进行移到,j 移动到了2的位置,i 本来就在2, 交换,变了1, 2. 这时按基准数2 进行序列分割, 但右边只有1了。最左侧的数和最右侧的数相等了,所以就不用进行排序了。右边的序列进行排序,也是这个逻辑。

  你会发现,我们所做的和上面的代码是一模一样的事情,只是序列更短了,直到只有一个数值,我们仍然可以调用quickSort, 这就是一个递归,递归结束的条件就是序列只有 一个数。

let arr = [6, 1, 2, 7, 9, 3, 4, 5, 10, 8];// 函数接受两个参数left, right, 指定排序时进行移动的 i, j 的位置function quickSort(left, right) {    let base;   // 基准数变量    let i, j;   // 进行移动的变量,寻找值    let t;      // 用于进行交换    base = arr[left];   // 序列最左边的数设为基准数    i = left;           // 把序列最左边的数赋给i    j = right;          // 把序列最右边的数赋值给j    console.log(left, right);    // 这是后面的递归的结束的条件, 因为序列只有一个数的时候,就不用排序了,对于左侧的序列 left =0, i -1 = -1    if (left > right) {        return;    }    // 只要i 和 j 不相等就要循环    while (i !== j) {        // 右侧的j 向左移动,找到一个比基准数小的值就停止        while (arr[j] >= base && i < j) {            j--;        }        // 左侧的 i 向右移动,找到一个比基准数大的值就停止        while (arr[i] <= base && i < j) {            i++;        }        // 当 i 和j 都找到值以后,交换它们两个位置,当然 i < j 时,如果i等于j,则是基准数的交换了         if (i < j) {            t = arr[i];            arr[i] = arr[j];            arr[j] = t;        }    }    // 当循环结束后,我们发现基准数应有的位置, 就是i的位置    arr[left] = arr[i];    arr[i] = base;    quickSort(left, i - 1);   // 继续对左边的序列进行排序, i就是基准数6的位置,它不用排列,所以要减1    quickSort(i + 1, right);  // 对右边的序列进行排序, 要 i + 1;}quickSort(0, arr.length - 1); // 调用排序函数console.log(arr);            // 输出结果

 

转载于:https://www.cnblogs.com/SamWeb/p/8092656.html

你可能感兴趣的文章
js 类数组转化数组
查看>>
数据库如何部署上线阅读总结
查看>>
linux下文件权限的介绍
查看>>
前端之Bootstrap
查看>>
SharePoint 2010 Logging Improvements
查看>>
最近在做淘宝客
查看>>
Shell脚本获取C语言可执行程序返回值
查看>>
ASCII 32个控制字符含义
查看>>
zoj2589
查看>>
tensorflow TypeError: Can not convert a float32 into a Tensor or Operation
查看>>
node.js初识11
查看>>
spring security自定义拒绝访问页面
查看>>
LINQ基础学习2
查看>>
窗口输入
查看>>
又一个月了
查看>>
Linux无法登录,显示module is unknown,一闪而过
查看>>
Revolving Digits(hdu4333)
查看>>
设计模式其中12种总结
查看>>
CLOSE_WAIT、CLOSE_WAIT原因,危害,如何避免
查看>>
.Net Core 2.0生态(4):Entity Framework Core 2.0 特性介绍和使用指南
查看>>