常见算法温习之快速排序

news/2024/5/19 21:14:10 标签: 算法, 快速排序

博客内容中的排序以升序排列为例


算法理解">1. 算法理解

快排的基本思想是:

  • 从原始序列Array(集合S)中选取一个元素(称之为枢纽元pivot)
  • 将剩余的元素分为两个集合S1和S2,其中S1中元素全都小于或等于pivot,S2中的元素全都大于或等于pivot
  • 递归分别对S1和S2执行上述两步

1.1 选取pivot
通常不加考虑地可以直接选取序列的第一个元素作为pivot,但是极端情况下,当原始序列恰好以降序排列时,快排时间复杂度将达到O(N^2)。比较好的方法是“三数中值分割法”,即选取序列的第0个、最后一个和最中间一个这三个元素,按照升序排列(left, center, right),选取中值(center)作为pivot,这样可以一定程序上缓解上述“坏情况”。

1.2 分割策略
快排可以通俗理解为“挖坑”和“填坑”的过程。

  • 因为选取了Array[center]作为pivot,所以相当于空出来了一个坑,首先将Array[left]的值填到center位置,则left位置就空出来了(“挖坑”)
  • 从最后一个元素开始往前(左)遍历,找到第一个小于或等于pivot的元素位置(标为位置 j),将该位置的元素填到left位置
  • 从left开始往后(右)遍历,找到第一个大于或等于pivot元素的位置(标为位置 i),将该位置的元素之值填到位置 j
  • 循环执行2、3步,直至i=j,将pivot的值填入位置i中,则pivot左边的元素均小于等于pivot(集合S1),pivot右边的元素均大于等于pivot(集合S2)
  • 对集合S1和S2分别递归执行上述四步

2. C++实现

#include <iostream>

using namespace std;

void swap(int *pa, int *pb)
{
    int temp = *pa;
    *pa = *pb;
    *pb = temp;
}


int median3(int a[], int left, int center, int right)
{
    if (a[left] > a[center]) swap(&a[left], &a[center]);
    if (a[left] > a[right]) swap(&a[left], &a[right]);
    if (a[center] > a[right]) swap(&a[center], &a[right]);

    return a[center];
}

void quicksort(int a[], int left, int right)
{
    if (left >= right) return;

    int center = (left + right) / 2;
    int pivot = median3(a, left, center, right);
    a[center] = a[left]; //将第0个元素空出来
    int i = left;
    int j = right;

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

    a[i] = pivot;
    quicksort(a, left, i-1);
    quicksort(a, i+1, right);
}

int main()
{
    int n, i;
    cout << "请输入序列元素个数" << endl;
    cin >> n;
    int *a = new int(n);

    cout << "请输入序列元素" << endl;
    for (i = 0; i < n; i++)
        cin >> a[i];

    quicksort(a, 0, n - 1);

    for (i = 0; i < n; i++)
        cout << a[i] << ' ';
    cout << endl;

    return 0;
}

算法复杂度分析">3. 算法复杂度分析

最优情况下,集合S1和S2的元素数目每次都比较均匀,则时间复杂度为O(NlogN),最坏情况上面已经分析过,平均情况下是O(NlogN),分析过程可参照二叉树。
就空间复杂度来说,主要是递归造成的栈空间的调用,最好情况下递归树的深度为log2n,其空间复杂度也就为O(logn),最坏情况,需要进行n‐1递归调用,其空间复杂度为O(n),平均情况,空间复杂度也为O(logn)。


参考:
1. 《数据结构与算法分析——C语言描述》
2. http://blog.csdn.net/weshjiness/article/details/8660583


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

相关文章

linux-shell父子进程

用户登录到Linux系统后&#xff0c;系统将启动一个用户shell。在这个shell中&#xff0c;可以使用shell命令声明变量&#xff0c;也可以创建并运行 shell脚本程序。运行shell脚本程序时&#xff0c;系统将创建一个子shell。此时&#xff0c;系统中将有两个shell&#xff0c;一个…

php判断变量是否 有值,判断变量有没有值问题

$name $_POST[name];前端提交一个 $name 变量&#xff0c;要是判断 $name 有没有值或者不存在一般怎么写&#xff1f;是:if(isset($name)){}还是:if(!empty($name)){}回复内容&#xff1a;$name $_POST[name];前端提交一个 $name 变量&#xff0c;要是判断 $name 有没有值或者…

常见算法问题之NextPermutation

题目来源于leetcode 31 1. 问题描述 依据字典序升序&#xff0c;找出序列的下一序列。例如&#xff08;左边是输入&#xff0c;右边是输出&#xff09;&#xff1a; 1 2 3 --- 1 3 2 1 5 1 --- 5 1 1 3 2 1 --- 1 2 3 2. 算法描述 for (i 0; i < size(array); i)j max{…

tp5 怎么跳转php页面,TP5的页面跳转与重定向.md

1、页面跳转的目标有哪些&#xff1f;调用方法&#xff1a;$this->success(提示,地址);$this->error(提示,地址);index.php文件内容&#xff1a;namespace app\index\controller;class Index extends \think\Controller{public function index(){return 欢迎来到PHP中文网…

记一道数学题。。。

题目来源于实验室某大神 的女票 的面试题。。。解题思路参照另一大神 这是一道递归题&#xff0c; 记n匹马的期望是f(n),显然有f(1)1, f(2)1/2。 n3时&#xff0c;相当于在n2的基础上又增加了一匹马&#xff0c;则这匹马的速度有三种情况&#xff08;最慢&#xff0c;适中&…

oracle 开启本地服务器配置,图解如何配置Oracle本地Net服务名

在进行团队开发的时候&#xff0c;一般团队的每一个人只需要安装一个客户端即可&#xff0c;没有必要安装一个Oracle 数据库服务器&#xff0c;而数据库服务器是属于共享的&#xff0c;此时&#xff0c;我们就需要配置客户端。客户端的配置可以有以下两种方式&#xff1a;第一种…

【转载】代码之谜(一)- 有限与无限(从整数的绝对值说起)

本博客为转载&#xff0c;原博客作者为justjavac 链接&#xff1a;http://justjavac.iteye.com/blog/1698691 一、引子 开始本章之前我先提个问题&#xff1a;“如果一个整数的绝对值等于它自己&#xff0c;那么这个数是几&#xff1f;”如果你回答是 0 和 所有正数&#xff0c…

正则表达式(基础篇)

/i (忽略大小写)/g (全文查找出现的所有匹配字符)/m (多行查找)/gi(全文查找、忽略大小写)/ig(全文查找、忽略大小写) .   是另一个元字符&#xff0c;匹配除了换行符以外的任意字符 *  同样是元字符&#xff0c;不过它代表的不是字符&#xff0c;也不是位置&#xff0c;而…