快速排序—Java实现

news/2024/5/19 23:36:50 标签: 快速排序

基本思想:

  1. 先从数列中取出一个数作为基准数
  2. 分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边
  3. 再对左右区间重复第二步,直到各区间只有一个数

快速排序=挖坑填数+分治法


实例:
数组a[]如下,取第一个数作为基准点
这里写图片描述
初始时,i=0; j=9; key=a[i]=72
因为已经将a[0]保存到key种,可以理解为在a[0]上挖了一个坑,可以将其他数据填进来。

从j开始,从后往前找一个小于或者等于key的数。当j=8时,满足条件,将a[8]挖出,在填到上一个坑a[0]中。a[0]=a[8];i++;这样a[0]这个坑就解决了。但又有了一个新坑a[8]。这次从i开始从前往后找一个大于或者等于key的数,当i=3,满足条件,将a[3]挖出再填到上一个坑中a[8]=a[3]; j–;
数组变为:
这里写图片描述
红色数字为移动后的数值,红色为新产生的坑

此时,i=3, j=7, key=72
在重复以上步骤,先从后往前,在从前往后
从j开始向前找,当j=5,符合条件,将a[5]挖出填到上一个坑中,a[3] = a[5]; i++;

从i开始向后找,当i=5时,由于i==j退出。

此时,i = j = 5,而a[5]刚好又是上次挖的坑,因此将key填入a[5]。
此时数组变为:
这里写图片描述
蓝色数字为第二次改动后的数值
可以看出a[5]前面的数字都小于它,a[5]后面的数字都大于它。因此再对a[0…4]和a[6…9]这二个子区间重复上述步骤就可以了。

递归和非递归实现代码如下:

import java.util.Arrays;
import java.util.Stack;

public class Quick {
    //找基准点
    public static int partition(int []arr,int start,int end) {
        int key=arr[start];
        while (start<end) {
            //开始从后往前找
            while (arr[end]>=key && end>start) {
                end--;
            }
            arr[start]=arr[end];//从后往前找到小于key的值
            //开始从前往后找
            while (arr[start]<=key && start<end) {
                start++;
            }
            arr[end]=arr[start];//从前往后找,找到一个大于key的数
        }
        arr[start]=key;
        return start;
    }
    //递归实现
    public static void quick(int arr[],int start,int end) {
        if (start<end) {
            int index=partition(arr, start, end);
            quick(arr, start, index-1);
            quick(arr, index+1, end);
        }
    }
    //非递归实现
    public static void non_quick(int[] arr,int start,int end) {
        Stack<Integer> stack=new Stack<>();
        if(start<end) {
            stack.push(end);
            stack.push(start);
            while (!stack.isEmpty()) {
                int left=stack.pop();
                int right=stack.pop();
                int index=partition(arr, left, right);
                if (left<index-1) {
                    stack.push(index-1);
                    stack.push(left);
                }
                if (right>index+1) {
                    stack.push(right);
                    stack.push(index+1);
                }
            }
        }
    }
    public static void main(String[] args) {
        int[] a1= {9,5,3,7,6,1,4,2,0,5,11,12};
        int[] a= {9,5,3,7,6,1,4,2,0,5,11,12};
        int start=0;
        int end=a1.length-1;
        quick(a1, start, end);
        System.out.println(Arrays.toString(a1));
        non_quick(a, start, end);
        System.out.println(Arrays.toString(a));
    }
}

时间复杂度
最坏时O(n^2)
最好为O(nlogn)

空间复杂度:
若每次划分均匀,复杂度为O(logn)
最坏为:O(n)


http://www.niftyadmin.cn/n/1236735.html

相关文章

我们最常看到的世界地图并不真实-墨卡托投影理解

墨卡托投影简介 墨卡托投影&#xff0c;是正轴等角圆柱投影&#xff0c;又称等角圆柱投影&#xff0c;圆柱投影的一种&#xff0c;由荷兰地图学家墨卡托&#xff08;G. Mercator&#xff09;于1569年创拟。为地图投影方法中影响最大的。 设想一个与地轴方向一致的圆柱切于或割于…

顺序查找—Java实现

说明&#xff1a;顺序查找适用于存储结构为顺序存储或链式存储的线性表 基本思想&#xff1a;顺序查找也称为线性查找&#xff0c;属于无序查找算法。从数据结构线形表的一端开始&#xff0c;顺序扫描&#xff0c;依次将扫描到的结点关键字与给定值key相比较&#xff0c;若相等…

什么是流?C++流类和流对象

程序中常用的 cin 和 cout&#xff0c;分别用于从键盘输入数据和向屏幕输出数据&#xff08;简称为标准 I/O&#xff09;。除此之外&#xff0c;程序还可以从文件中读入数据&#xff0c;以及向文件中写入数据&#xff08;简称为文件 I/O)。 数据输入和输出的过程也是数据传输的…

二分查找—Java实现

说明&#xff1a;元素必须时有序的&#xff0c;如果是无序的要先进行无序操作 基本思想&#xff1a;也称为折半查找&#xff0c;属于有序查找算法。每次取数组的中间值作为比较对象&#xff0c;如果小于a[mid] 则在数组的右边继续比较&#xff0c;如果大于a[mid] 则在数组的左…

差值查找—Java实现

在介绍差值查找之前&#xff0c;首先考虑一个新问题&#xff0c;为什么上述算法一定要是折半&#xff0c;而不是折四分之一或者折更多呢&#xff1f;   打个比方&#xff0c;在英文字典里面查“apple”&#xff0c;你下意识翻开字典是翻前面的书页还是后面的书页呢&#xff1…

论文中的公式大小调整相关整理

原文地址&#xff1a;http://www.mathtype.cn/jiqiao/piliang-xiugai-zitidaxiao.html MathType应用在论文中时&#xff0c;有时会因为排版问题批量修改公式字体和大小&#xff0c;一个一个的修改不仅费时费力&#xff0c;还容易出现错误&#xff0c;本教程将详解如何在 MathT…

斐波那契查找—Java实现

基本思想&#xff1a;也是二分查找的一种提升算法&#xff0c;通过运用黄金比例的概念在数列中选择查找点进行查找&#xff0c;提高查找效率。同样地&#xff0c;斐波那契查找也属于一种有序查找算法。 相对于折半查找&#xff0c;一般将待比较的key值与第mid&#xff08;lowh…

数学符号在论文中的格式规范

一&#xff0c;使用斜体的情况&#xff1a; 1) 变量(variables)应该用斜体表示&#xff1a;例如T表示温度(temperature)&#xff0c;r表示速率(rate). 注意&#xff1a;即便用变量来作为形容词的组成部分&#xff0c;依然要保持斜体&#xff0c; 举例&#xff1a;In this eq…