快速排序之三数取中法

---恢复内容开始---

快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

基本步骤

三数取中

  在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。

 根据枢纽值进行分割

 

代码实现

package sortdemo;

import java.util.Arrays;

/**
 * Created by chengxiao on 2016/12/14.
 * 快速排序
 */
public class QuickSort {
    public static void main(String[] args) {
        int[] arr = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
        quickSort(arr, 0, arr.length - 1);
        System.out.println("排序结果:" + Arrays.toString(arr));
    }

    /**
     * @param arr
     * @param left  左指针
     * @param right 右指针
     */
    public static void quickSort(int[] arr, int left, int right) {
        if (left < right) {
            //获取枢纽值,并将其放在当前待处理序列末尾
            dealPivot(arr, left, right);
            //枢纽值被放在序列末尾
            int pivot = right - 1;
            //左指针
            int i = left;
            //右指针
            int j = right - 1;
            while (true) {
                while (arr[++i] < arr[pivot]) {
                }
                while (j > left && arr[--j] > arr[pivot]) {
                }
                if (i < j) {
                    swap(arr, i, j);
                } else {
                    break;
                }
            }
            if (i < right) {
                swap(arr, i, right - 1);
            }
            quickSort(arr, left, i - 1);
            quickSort(arr, i + 1, right);
        }

    }

    /**
     * 处理枢纽值
     *
     * @param arr
     * @param left
     * @param right
     */
    public static void dealPivot(int[] arr, int left, int right) {
        int mid = (left + right) / 2;
        if (arr[left] > arr[mid]) {
            swap(arr, left, mid);
        }
        if (arr[left] > arr[right]) {
            swap(arr, left, right);
        }
        if (arr[right] < arr[mid]) {
            swap(arr, right, mid);
        }
        swap(arr, right - 1, mid);
    }

    /**
     * 交换元素通用处理
     *
     * @param arr
     * @param a
     * @param b
     */
    private static void swap(int[] arr, int a, int b) {
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
} 

排序结果

排序结果:[1, 2, 3, 4, 5, 6, 7, 8]

总结

  快速排序是一种交换类的排序,它同样是分治法的经典体现。在一趟排序中将待排序的序列分割成两组,其中一部分记录的关键字均小于另一部分。然后分别对这两组继续进行排序,以使整个序列有序。在分割的过程中,枢纽值的选择至关重要,本文采取了三位取中法,可以很大程度上避免分组"一边倒"的情况。快速排序平均时间复杂度也为O(nlogn)级。

---恢复内容结束---

原文地址:https://www.cnblogs.com/zwb2jcy/p/8920353.html

时间: 2024-10-29 03:35:48

快速排序之三数取中法的相关文章

【数据结构】大量数据(20万)的快速排序的递归与非递归算法、三数取中思想

快速排序的挖坑法与prev.cur法,我们在上一篇博客的第6个排序中讲的非常详细,http://10740184.blog.51cto.com/10730184/1774508[数据结构]常用排序算法(包括:选择排序,堆排序,冒泡排序,选择排序,快速排序,归并排序) 有兴趣的话,相信聪明的你,一看就会秒懂快速排序的思想. 下面,我们将快速排序优化: 1.三数取中来优化快速排序 优化原因: 快速排序的擦差不多每次将序列一分为二,时间复杂度是O(n*lgn). 我们思考,快速排序的时间复杂度是O(n

poj 3349:Snowflake Snow Snowflakes(哈希查找,求和取余法+拉链法)

Snowflake Snow Snowflakes Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 30529   Accepted: 8033 Description You may have heard that no two snowflakes are alike. Your task is to write a program to determine whether this is really true. Y

计蒜客第五场 UCloud 的安全秘钥(中等) (尺取游标法

每个 UCloud 用户会构造一个由数字序列组成的秘钥,用于对服务器进行各种操作.作为一家安全可信的云计算平台,秘钥的安全性至关重要.因此,UCloud 每年会对用户的秘钥进行安全性评估,具体的评估方法如下: 首先,定义两个由数字序列组成的秘钥 aa 和 bb近似匹配(\approx≈) 的关系.aa 和 bb 近似匹配当且仅当同时满足以下两个条件: |a|=|b|∣a∣=∣b∣,即 aa 串和 bb 串长度相等. 对于每种数字 cc,cc 在 aa 中出现的次数等于 cc 在 bb 中出现的次

【实操】进制转换:除基倒取余法

一.原理:除基倒取余法 以10进制转2进制为例:输入一个十进制数n,每次用n除以2,把余数记下来,再用商去除以2...依次循环,直到商为0结束,把余数倒着依次排列,就构成了转换后的二进制数. 所有进制之间的转换都是如此,2可以换成任何数字.十进制转二进制.八进制.十六进制.64进制,全部如下. 二.具体的JAVA实现: 2.1 10进制数字转n进制: public class Main { public static void main (String[] args) { int n = 64;

WPF换肤之三:WPF中的WndProc

原文:WPF换肤之三:WPF中的WndProc 在上篇文章中,我有提到过WndProc中可以处理所有经过窗体的事件,但是没有具体的来说怎么可以处理的. 其实,在WPF中,要想利用WndProc来处理所有的事件,需要利用到SourceInitialized  Event,首先需要创建一个HwndSource对象,然后利用其AddHook方法来将所有的windows消息附加到一个现有的事件中,这个就是WndProc. void WSInitialized(object sender, EventAr

Chrome扩展开发之三——Chrome扩展中的数据本地存储和下载

目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制和通信方式 3.Chrome扩展开发之三——Chrome扩展中的数据本地存储和下载 4.Chrome扩展开发之四——Gmail API的简单介绍 5.Chrome扩展开发之五——OAuth2的理解 6.Chrome扩展开发之六——GmailAssist核心功能的实现(包括Gmail API的使用中的

POJ 3070 + 51Nod 1242 大斐波那契数取余

POJ 3070 #include "iostream" #include "cstdio" using namespace std; class matrix { public: int a[2][2]; matrix() { a[0][0]=a[1][0]=a[0][1]=1; a[1][1]=0; } }; matrix multi(matrix a,matrix b) { matrix temp; int i,j,k; for(i=0;i<2;i++)

中法20年秘密军火交易 航母差点变成法国货

最近几周,法国海军的西北风级登陆舰访华.中国是否会购买这种两栖攻击舰的话题备受军迷热议.实际上,中国从法国购买武器装备,并不是一个新鲜的事情.近20年来,虽然有武器禁运的阻碍,但法国仍然通过特殊渠道对华出口了不少装备.本期节目我们就为大家讲述中法两国的秘密武器贸易.http://www.ximalaya.com/zhubo/27532308/ http://www.ximalaya.com/zhubo/27532310/ http://www.ximalaya.com/zhubo/2753231

九度OJ 1097 取中值

题目1097:取中值 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:4379 解决:1188 题目描述: 存在两组数组,和4个数字a,b,c,d,要求做如下操作,将第一个数组第a个数到第b个数,第二个数组的第c个数到第d个数放到一个数组中,求出合并后数组的中间值,如果有两个中间值,取下标较小的那个. 输入: 第一行一个整数t表示有t个测试数据 第二行两个整数,表示两个数组的长度, 接下来两行表示两个数字的值, 最后一行有四个整数a,b,c,d. 数组长度不会超过1000000. 输出