随机化快速排序 python C C++ 图解 代码 及解析

news2024/9/24 9:21:23

 一,概念及其介绍

快速排序由 C. A. R. Hoare 在 1960 年提出。

随机化快速排序基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

二,复杂度说明

时间复杂度: O(n log n)

随机化快速排序的平均时间复杂度为 O(nlog n),最坏情况下的时间复杂度为 O(n^2),但这种最坏情况出现的概率极低。

在平均情况下,每次划分都能将数组大致平均分成两部分,使得递归的深度为 log n 级别。每次划分操作的时间复杂度为 O(n),所以总的平均时间复杂度为 O(nlog n)。

然而,在最坏情况下,例如数组已经有序,每次划分都选择到了最小或最大的元素作为基准,导致划分极不均匀,递归深度达到 $n$ 级别,时间复杂度就变为 O(n^2)。

空间复杂度:O(log n)  

空间复杂度方面,随机化快速排序的空间复杂度主要取决于递归调用栈的空间。在平均情况下,空间复杂度为 O(log n),用于存储递归过程中的函数调用信息。

在最坏情况下,空间复杂度为 O(n)。

三,过程图示

四.代码及解析

4.1 python 

思路:

先定义一个函数,在传入的数组中随机选一个数,将比它小的元素放到他左边,比他大的放到右边,实现方式就是从列表首和尾分别开始遍历,直到左边找到一个比选定分割数大的数,右边找到一个比它小的,交换两个数的位置直到分区完成返回选定的分区数

将整个数组传入后分区,再对返回的分区数两边分别分区,用函数递归调用实现,直到子数组只有一个元素

知识点:

这段代码第一个函数是传入一个列表,在函数中直接对列表进行操作,每次返回的是分区所随机选定的中间数,第二个函数是利用函数递归,将列表不断分为两段,递归进行操作

import random

def partition(arr, low, high):
    # 随机选一个数作为分割点
    pivot = arr[random.randint(low, high)]
    i = low - 1
    j = high + 1

    while True:
        i += 1
        # 从左边找到一个比pivot大的数
        while arr[i] < pivot:
            i += 1
        # 从右边找到一个比pivot小的数
        j -= 1
        while arr[j] > pivot:
            j -= 1
        # 分区已经完成
        if i >= j:
            return j
        # 交换位置
        arr[i], arr[j] = arr[j], arr[i]

def quick_sort_randomized(arr, low, high):
    # 判断是否还有需要排序的子数组(即子数组至少包含两个元素)
    if low < high:
        pi = partition(arr, low, high)
        quick_sort_randomized(arr, low, pi) # 左半部分子数组(从 low 到 pi )进行递归排序
        quick_sort_randomized(arr, pi + 1, high)

# 测试示例
arr = [12, 11, 13, 5, 6]
n = len(arr)
quick_sort_randomized(arr, 0, n - 1)
print("排序后的数组:", arr)
排序后的数组: [5, 6, 11, 12, 13]

4.2 C

思路:

分区函数选择数组最后一个元素作为分区轴,然后遍历从 low 到 high - 1 的元素。

如果当前元素小于或等于枢轴,就将 i 递增,并交换 arr[i] 和 arr[j] 的位置,这样小于枢轴的元素就逐渐被移到了左边。最后,将枢轴与 arr[i + 1] 交换位置,使得枢轴处于正确的位置,即左边的元素都小于枢轴,右边的元素都大于枢轴,并返回枢轴的新位置 i + 1

quickSort 函数:首先检查当前的子数组是否至少有两个元素(low < high)。如果是,调用 partition 函数对当前子数组进行分区,得到分区点的索引 pi 。然后对左半部分子数组(从 low 到 pi - 1)和右半部分子数组(从 pi + 1 到 high)分别进行递归调用 quickSort 函数,以完成整个数组的排序。通过不断地分区和递归,最终将数组排序

这里还需要额外定义一个函数用来交换两个元素在数组中的位置。

注意点:

1.交换函数中传入的是两个指针,通过修改指针所指向的内存地址的元素值来进行交换元素

2.分区函数中定义i=low-1后,交换i和j的元素之前要先将i++

3.最后i遍历过的元素都是比轴小,交换过来的,所以要把轴放到i+1的位置

4.求数组长度可以用int n = sizeof(arr) / sizeof(arr[0]);这样的格式

5.i 变量:

它被初始化为 low - 1 。其作用是标记小于或等于枢轴元素的边界位置。在遍历过程中,每当遇到小于或等于枢轴的元素,就将 i 递增,并将该元素与 arr[i] 交换位置,从而将小于或等于枢轴的元素逐渐移到数组的左侧。

j 变量:

它从 low 开始,逐步递增到 high - 1 。用于逐个检查数组中的元素,与枢轴进行比较,并根据比较结果决定是否与 arr[i] 交换位置

#include <stdio.h>

// 交换函数
void swap(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

// 分区函数
int partition(int arr[], int low, int high) {
    int pivot = arr[high];
    int i = (low - 1);

    for (int j = low; j <= high - 1; j++) {
        if (arr[j] <= pivot) {
            i++;
            swap(&arr[i], &arr[j]);
        }
    }
    swap(&arr[i + 1], &arr[high]);
    return (i + 1);
}

// 快速排序函数
void quickSort(int arr[], int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}

// 打印数组函数
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++)
        printf("%d ", arr[i]);
    printf("\n");
}

// 测试示例
int main() {
    int arr[] = {12, 11, 13, 5, 6};
    int n = sizeof(arr) / sizeof(arr[0]);

    printf("排序前的数组为: ");
    printArray(arr, n);

    quickSort(arr, 0, n - 1);

    printf("排序后的数组为: ");
    printArray(arr, n);

    return 0;
}

4.3 C++

思路:

partition 函数:

选择数组的最后一个元素作为枢轴。通过遍历,将小于等于枢轴的元素移动到数组的左边,大于枢轴的元素移动到数组的右边。最终将枢轴放置在正确的位置,并返回该位置的索引。

quickSort 函数:

如果待排序的子数组至少包含两个元素,就进行分区操作。根据分区得到的枢轴位置,对左子数组和右子数组分别递归调用 quickSort 函数。这样不断递归地对子数组进行排序,最终使整个数组有序

注意点:

1.交换函数传入两个引用,引用是变量的别名,通过修改引用可以修改变量的值 ,从而达到交换的目的

2.计算数组长度 int n = sizeof(arr) / sizeof(arr[0]);

3.i 变量:

它被初始化为 low - 1 。其作用是标记小于或等于枢轴元素的边界位置。在遍历过程中,每当遇到小于或等于枢轴的元素,就将 i 递增,并将该元素与 arr[i] 交换位置,从而将小于或等于枢轴的元素逐渐移到数组的左侧。

j 变量:

它从 low 开始,逐步递增到 high - 1 。用于逐个检查数组中的元素,与枢轴进行比较,并根据比较结果决定是否与 arr[i] 交换位置

#include <iostream>

// 交换函数
void swap(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

// 分区函数
int partition(int arr[], int low, int high) {
    int pivot = arr[high];
    int i = (low - 1);

    for (int j = low; j <= high - 1; j++) {
        if (arr[j] <= pivot) {
            i++;
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[i + 1], arr[high]);
    return (i + 1);
}

// 快速排序函数
void quickSort(int arr[], int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);

        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}

// 打印数组函数
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++)
        std::cout << arr[i] << " ";
    std::cout << std::endl;
}

// 测试示例
int main() {
    int arr[] = {12, 11, 13, 5, 6};
    int n = sizeof(arr) / sizeof(arr[0]);

    std::cout << "排序前的数组为: ";
    printArray(arr, n);

    quickSort(arr, 0, n - 1);

    std::cout << "排序后的数组为: ";
    printArray(arr, n);

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1966382.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

真假公主:一场容貌相似引发的宫廷阴谋

真假公主&#xff1a;一场容貌相似引发的宫廷阴谋 从古至今&#xff0c;每个人的心思都不相同&#xff0c;正如他们的面貌各不相同一样。即使人们的外貌没有明显的差异&#xff0c;但他们的内心和性格却是难以改变的。 话说人的面貌是最为独特的&#xff0c;因为每个人都是由不…

LNMP黄金架构搭建部署论坛网站

哈哈哈哈哈我终于部署出来了一个属于自己的论坛&#xff0c;虽然不怎么懂 部署Linux环境 关闭防火墙Systemctl stop firewalldSystemctl disable firewalld关闭selinuxSetence 0查看selinuxGeteforce 部署nginx环境 Yum i install httpd过滤apache的端口号看是否有80端口N…

移动自组织网络(MANET)与互联网连接的网关选择方案文献综述

以下内容节选自这篇综述论文《Gateway Selection Scheme for MANET to Internet Connectivity: A Survey》由Ritu Singh和Jay Prakash撰写&#xff0c;主要探讨了移动自组织网络&#xff08;MANET&#xff09;与互联网连接的网关选择方案。 在接下来的部分中&#xff0c;我们对…

gstreamer实现视频的3D旋转(一)的实现思路

效果&#xff1a; 一、实现思路 首先我们要知道&#xff0c;gstreamer有OpenGL相关的插件&#xff0c;网址如下&#xff1a; GstOpengl (gstreamer.freedesktop.org) 其中&#xff0c;有不少有趣的插件&#xff0c;比如我发现的gltransformation插件&#xff0c;可以实现OpenG…

甄选范文“论层次式架构在系统中的应用”软考高级论文系统架构设计师论文

论文真题 层次架构作为软件系统设计的一种基本模式,对于实现系统的模块化、可维护性和可扩展性具有至关重要的作用。在软件系统的构建过程中,采用层次架构不仅可以使系统结构更加清晰,还有助于提高开发效率和质量。因此,对层次架构的理解和应用是软件工程师必备的技能之一…

普元Devops学习笔记-devops对接jenkins提示crumb不可用问题

前言 普元devops需要对接jenkins&#xff0c;对接jenkins后&#xff0c;devops会调用jenkins的提供的API。 问题 新版本的jenkins提供跨域保护&#xff0c;即大名鼎鼎的CSRF问题。 因此&#xff0c;普元devops调用jenkins的时候&#xff0c;会出现跨域问题。 后台报错信息如…

Python Socket 编程基础

在计算机网络的世界里&#xff0c;Socket 编程是实现不同计算机之间通信的一种基础而强大的方式。Python 作为一种广泛使用的编程语言&#xff0c;其内置的 socket 库使得进行网络编程变得简单而直观。本文将带你走进 Python Socket 编程的世界&#xff0c;通过构建简单的客户端…

若依分离版本部署流程—开启HTTPS访问。

目录 前言 一、申请证书 二、后端打包 三、前端打包 四、服务器部署 ① Redis启动 ② 运行Jar包 ③ 上传ssl证书到服务器 ④ Nginx配置前端部分 五、访问 前言 在若依分离版本的项目部署过程中&#xff0c;跟大多数前后端分离项目差不多&#xff0c;都是前后端分别打包到服…

大型边缘物联平台实战系列01-为什么我们放弃Springboot选择了Nestjs?

引言 我真的很爱Nestjs&#xff0c;那是一种很纯粹、很理性的爱&#xff0c;四年了&#xff0c;我每天都在用它…哦&#xff0c;不对&#xff0c;是我们都在用它。 四年前&#xff0c;在那场剑拔弩张的技术选型会议上&#xff0c;经过十几轮Battle&#xff0c;楼主力排众议将…

MySQL:ORDER BY 排序查询

通过 ORDER BY 条件查询语句可以查询到符合用户需求的数据&#xff0c;但是查询到的数据一般都是按照数据最初被添加到表中的顺序来显示。 基本语法 在MySQL中&#xff0c;排序查询主要通过ORDER BY子句实现。其基本语法如下&#xff1a; SELECT column1, column2, ... FR…

阿里云上进行开发

目的&#xff1a; 直接在阿里云的ECS上面写代码学代码&#xff0c;而不是在本机上写好以后进行部署。 已有前提&#xff1a; 1&#xff0c;WSL 2&#xff0c; vscode 3&#xff0c;阿里云 47.120.66.77 4&#xff0c;通过WSL的 ssh root47.120.66.77 远程登录阿里云。 …

我的《Java全栈高级架构师高薪就业课》学完有什么收获?

我的《Java全栈高级架构师高薪就业课》上线了~ 这是一套Java全栈微服务架构、以实战项目驱动的课程&#xff01;包含34个模块&#xff0c;1514课时。对标阿里P7级别技术栈而研发&#xff0c;有着循序渐进的学习体系&#xff0c;助你开启Java进阶之旅。 学完我的这套《Java全栈高…

学习测试16-仪表项目

项目框架 项目地址 车厂&#xff1a;oem 主机厂 厂商 – 长城魏牌、问界、小米 车型&#xff1a;魏牌c01 供应商&#xff1a;XXX有限公司 人员&#xff1a;总动15人&#xff0c;两种车型&#xff0c;两个组&#xff0c;4人写用例&#xff08;30天&#xff0c;每天100条&#x…

关于实时ODS层数仓搭建的三个问题

目录 问题一&#xff1a;数据同步的实时性无法满足 问题二&#xff1a;批量数据同步计算处理效率低 问题三&#xff1a;没有稳定的数据传输管道 FineDataLink的解决方案 实战案例-销售部门与财务部门数据同步 设置ODS层实时同步任务 设置DW层增量数据同步 设置 DM 层任务汇总 关…

基于YOLOv5的智能路面病害检测系统

随着城市化进程的加速发展&#xff0c;公路基础设施的维护变得日益重要。路面病害&#xff0c;如裂缝、坑洼等&#xff0c;不仅影响行车安全&#xff0c;还会缩短道路使用寿命。因此&#xff0c;快速准确地检测并评估这些病害成为了一个关键任务。本项目旨在开发一款基于YOLOv5…

【常用小机器】下载保存语雀文档

安装工具 npm i -g yuque-dl检查安装&#xff1a; yuque-dl -h私有库 通过别人私有知识库 分享的链接&#xff0c;需使用-t添加token&#xff08;cookie中_yuque_session的值&#xff09;才能下载 yuque-dl "https://www.yuque.com/yuque/thyzgp" -t "abcd.…

GD32 ADC模数转换器

前言&#xff1a; ... 1&#xff1a;简介 12 位 ADC 是一种采用逐次逼近方式的模拟数字转换器。它有 18 个多路复用通道&#xff0c;可以转换来自 16 个外部通道和 2 个内部通道的模拟信号。模拟看门狗允许应用程序来检测输入电压是否超出用户设定的高低阈值。各种通道的 A/D …

解决m-tabbar部分页面元素浮动导致第一个单元格元素点击失效问题

工作中遇到一个神奇的bug&#xff0c;代码没有问题点击第一个单元格的时候无法正常点击&#xff0c;通过调试工具定位发现是m-tabbar组件的m-tabbar-box元素有浮动导致了点击失效。 解决办法1&#xff1a; 设置元素的z-index大于tabbar的&#xff0c;这样要对页面元素底部做一…

VMware虚拟机设置桥接网络固定IP

VMware虚拟机设置桥接网络固定IP 在VMware虚拟机中设置桥接网络并固定IP地址&#xff0c;主要涉及到几个步骤&#xff1a;设置虚拟网络编辑器、配置虚拟机的网络适配器&#xff0c;以及修改虚拟机内的网络配置文件。以下是详细的步骤说明&#xff1a; 设置虚拟网络编辑器 以…

[ BLE4.0 ] 伦茨ST17H66开发-ADC采集电压数据-ADC中断采集-ADC单端输入与差端输入

目录 一、前言 二、采集模式 三、详细步骤 3.1 引脚选择 3.2 代码实现 3.2.1 导入库文件 3.2.2 模式选择 3.2.3 bypass模式 3.2.4 attenuation模式 3.2.5 代码配置 四、效果展示 一、前言 使用单片机面对数据采集时&#xff0c;往往设计到模拟量的采集&#xff0c;因此&…