基础算法之快速排序(quick_sort)

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

  最开始我们学习编程,首先接触的排序算法应该都是冒泡排序,虽然这种算法代码量少且较好理解,但其时间复杂度相对较高,在面对大数据时代码运行速度明显变慢,因此今天我们来介绍一种冒泡排序的改进算法——快速排序

  该算法的实现主要基于以下几个步骤:

1:在待排序的数组中取一个基准数(可随机取,但通常为数组两端点或中间的数)

2:将数组中的数逐个与基准数比较,较大的置于基准数右侧,较小的置于基准数左侧

3:对基准数两侧数组不断重复上述两个步骤,直到每个子集只有一个元素即为全部有序(此处可用函数的递归实现)

下面以一道acwing上的模板题为例子进行讲解

这里附上原题链接: 785. 快速排序 - AcWing题库

  那我这里就以输入样例来简单分析一下算法的实现

1:首先取基准数,那这里我们选取数组中间的2为例

2:创建两个指针i,j,i指向数组左边界偏移1,j指向数组右边界偏移1(这里后面会解释,用到了do while循环),当i指向的数小于基准数时继续右移,直到遇到不比基准数小的数时停止,此时开始将j左移,直到遇到不比基准数大的数时停止。此时两个指针都已移动完毕,用swap函数交换两指针的位置

3:第一次排序完毕后,递归调用函数,对基准数的左边子区间和右边子区间进行上述两步骤排序,直至数组有序(即区间内只有一个元素)

下面我们以图解的方式帮助大家理解

首先确定基准数

 然后按照上述所讲将i,j进行移动(因为i已满足条件所以此次不移动)

交换i,j所指元素,此时第一次排序已完成,开始下一次递归(注意此时基准数右侧已有序故右侧递归无实际意义,我们只讲左侧的递归)

                                    

 此次根据之前所讲将1作为基准数,而此时i,j指针均已经满足条件停止,接下来进行交换

 可以看到此时数组已经全部排序完毕,函数执行完毕

 下面给出快速排序的模板供大家参考

void quick_sort(int q[], int l, int r)
{
    if (l = r) return;//如果只有一个数据便直接结束

    int i = l - 1;
    int j = r + 1;//因为这里使用了 do while循环所以要将l和r分别偏移1代码运行时才指向数组的实际边界
    int x = q[(l+r+1)/2];//取中间数为基准数
    while (i < j)//注意防止指针交叉
    {
        do i ++ ;
        while (q[i] < x);
        do j -- ;
        while (q[j] > x);//指针移动
        if (i < j)
         {
            swap(q[i], q[j]);//指针移动完后交换元素
         }
    }
       quick_sort(q, l, j);
       quick_sort(q, j + 1, r);
}

 本题完整代码

#include<iostream>
#include<cmath>
using namespace std;
const int N = 1e6 + 10;
int n; int q[N];
void quick_sort(int q[], int l, int r)
{
    if (l == r) return;
    int x = q[(l + r + 1) / 2];
    int i = l - 1;
    int j = r + 1;
    while (i < j)
    {
        do i++; while (q[i] < x);
        do j--; while (q[j] > x);
        if (i < j)
        {
            swap(q[i], q[j]);
        }
    }
    quick_sort(q, l, i - 1);
    quick_sort(q, i, r);
}
int main()
{
    int n = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &q[i]);
    quick_sort(q, 0, n - 1);
    for (int i = 0; i < n; i++) printf("%d", q[i]);
    return 0;
}

 

 

 

 

 


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

相关文章

c语言实现简单猜数字游戏(rand/do while的基本使用)

目录 1.引文 2.实现思路 3.代码实现及具体解析 1.关于猜数字游戏&#xff0c;我想很多人在小时候都玩过&#xff0c;这是一种起源于20世纪中期的游戏。而他的基本规则就是一个人随机给出一个数&#xff0c;然后让另一个人去猜测这个数字的具体大小&#xff0c;如果大了则回答…

三子棋的简单实现与其中的模块化设计思想

目录 1.背景简介 2.模块化设计思想及三子棋实现思路 3.具体代码分析 4.完整代码 1.背景简介&#xff1a; 相信大家小时候都应该和朋友玩过这个简单的游戏。三子棋是黑白棋的一种。三子棋是一种民间传统游戏&#xff0c;又叫九宫棋、圈圈叉叉、一条龙、井字棋等。将正方形对…

c语言数组简单实现童年回忆——扫雷

目录 1.扫雷简介 2.游戏实现思路 3.代码详细分析 1.扫雷简介 不知道大家再次看见这张图有什么感受&#xff0c;自从win10更新后将扫雷移除&#xff0c;似乎这个我们的童年回忆正与我们渐行渐远。而今天我们要做的就是利用C语言简单实现这个我们的童年回忆。 先简单介绍一下扫…

浅谈整数与浮点数在内存中的存储

目录 1.引言 2.一些基础知识&#xff08;原码、反码、补码、整数的存储&#xff09; 3.浮点数的存储机制 1.引言 想必大家经过一段时间的学习&#xff0c;对于整数在内存中的存储已经有所了解&#xff08;不了解我们接下来也会讲解&#xff09;&#xff0c;实际上整数在内存…

浅析部分指针笔试题

目录 1.前言 2.关于指针 2.题目具体解析 1&#xff1a;前言 有关c语言的学习&#xff0c;许多小伙伴们最害怕的应该莫过于指针了吧&#xff0c;而同时指针却也是我们笔试面试中较为常见的一类题型&#xff0c;那么在本篇文章&#xff0c;我将尽力为大家解决有关指针的问题&a…

浅析如何利用指针实现一些c语言库函数

1.前言 2.库函数的具体作用 3具体实现代码 1.前言 在一些互联网公司的笔试或者面试中&#xff0c;对库函数的考察几乎是必不可少的&#xff0c;或者会问一些库函数之间的区别&#xff0c;或者他们的具体实现方法&#xff0c;那么在本文我将抛砖引玉讲解部分c语言中的库函数的实…

位段、枚举与联合体

目录 1.位段 2.枚举 3.联合体 1.位段 1.1什么是位段 位段的声明和结构是类似的&#xff0c;有两个不同&#xff1a; 1.位段的成员必须是 int、unsigned int 或signed int 。 2.位段的成员名后边有一个冒号和一个数字。 比如我们有下面一串代码 struct A {int _a:2;int _b…

有关c语言动态内存管理

目录 1.为什么需要动态内存分配 2.有关动态内存函数介绍 3.常见的动态内存错误 1.为什么需要动态内存分配 关于这个问题&#xff0c;我们先看看我们之前是如何开辟内存的。 int val 20;//在栈空间上开辟四个字节 char arr[10] {0};//在栈空间上开辟10个字节的连续空间 但…