【算法基础】(一)基础算法 --- 快速排序

这篇具有很好参考价值的文章主要介绍了【算法基础】(一)基础算法 --- 快速排序。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

✨个人主页:bit me
✨当前专栏:算法基础
🔥专栏简介:该专栏主要更新一些基础算法题,有参加蓝桥杯等算法题竞赛或者正在刷题的铁汁们可以关注一下,互相监督打卡学习 🌹 🌹 🌹


 

💤一. 快速排序:(分治)

题目要求:

给定你一个长度为n的整数数列
请你使用快速排序对这个数列按照从小到大进行排序
并将排好的数列按顺序输出

输入格式:

输入一共两行,第一行包含整数n
第二行包含n个整数(所有整数均在1 ~ 10^9范围内),表示整个数列

输出格式:

输出共一行,包含n个整数,表示排好序的数列

数据范围:

1 <= n <= 100000

输入样例:

5
3 1 2 4 5

输出样例:

1 2 3 4 5

快排思路:

  1. 先确定分界点:左右极点分别为q[i],q[j],中间值为q[(i+j) / 2]
  2. 调整区间:定义一个任意值x,让小于x的值都挪到x左边,让大于x的值都挪到x右边
  3. 递归处理左右两段,让他们进行排序然后衔接,方法就是左右极限都定义一个指针,左指针往右走,遇到大于x的值就停下来,右指针往左走,遇到小于x的值就停下来,然后俩指针指向的值进行交换,直到相遇为止,这样左边就全是小于x的值,右边全是大于x的值,然后完成衔接,排序就完成了

导图:
【算法基础】(一)基础算法 --- 快速排序

  1. 首先我们需要输入第一行包含整数n,第二行包含n个整数:
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] q = new int[n];
for(int i=0; i<n; i++){
	q[i] = sc.nextInt();
}
  1. 对快速排序函数进行分类处理:

①:当左边界大于等于右边界的时候直接返回

if(l >= r) return;

②:取随机值x我们最好取左右边界的中间值,因为取左右边界值可能会超时,时间复杂度退化,当我们左右指针往中间挪的时候我们不要把起点定在左右边界处,要放在边界外面一位,方便我们处理边界,不容易发生混淆

int x = q[l + r >> 1], i = l - 1, j = r + 1;

③:当左指针没遇到右指针的时候,我们需要考虑到随机值x,当左指针小于x的时候就往右边走,当右指针大于x的时候就往左边走,如果左指针和右指针都停了的时候,就交换两边的数据,然后继续往后走

while(i < j){
    while( q[++i] < x );
    while( q[--j] > x) ;
    if(i < j){
        int t = q[i];
        q[i] = q[j];
        q[j] = t;
    }
}

④:对边界的处理

quickSort(q, l, j);
quickSort(q, j + 1, r);

在这里对边界进行一个小结:

quickSort(q, l, j);
quickSort(q, j + 1, r);

quickSort(q, l, i - 1);
quickSort(q, i, r);

  1. 是因为对于第一次处理后的数组,索引i左侧的数字都是小于等于x,但不包括q[i]。索引i右侧的数字都是大于等于x,包括q[i]。故区间分为[l,i-1]和[i,r]。
  2. 同理,对于第一次处理后的数组,索引j左侧的数字都是小于等于x,包括q[j]。索引j右侧的数字都是大于等于x,不包括q[j]。故区间分为[l,j]和[j+1,r]。

再对x位置小结:

  1. 如果区间取[l,i-1]和[i,r]这种,那么x不应该取左边界(l、(l+r)/2)。
    应取 x = q[r]; x = q[(l+r+1)/2];
  2. 如果区间取[l,j]和[j+1,r]这种,那么x不应该取右边界(如r、(l+r+1)/2)。
    应取 x = q[l]; x = q[(l+r)/2];
     
    自己选择其中一种即可。

附上总的代码文章来源地址https://www.toymoban.com/news/detail-413252.html

public static void main(String[] args){
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    int[] q = new int[n];
    for(int i=0; i<n; i++){q[i] = sc.nextInt();}

    quickSort(q, 0, n-1);
    for(int i=0; i<n; i++){System.out.print(q[i] + " ");}
}

public static void quickSort(int[] q, int l, int r){
    if(l >= r) return;
    int x = q[l + r >> 1], i = l - 1, j = r + 1;
    while(i < j){
        while( q[++i] < x );
        while( q[--j] > x) ;
        if(i < j){
            int t = q[i];
            q[i] = q[j];
            q[j] = t;
        }
    }
    quickSort(q, l, j);
    quickSort(q, j + 1, r);
}

 

💦二.第k个数

题目要求:

给定一个长度为 n 的整数数列,以及一个整数 k,请用快速选择算法求出数列从小到大排序后的第 k 个数。

输入格式:

第一行包含两个整数 n 和 k。
第二行包含 n 个整数(所有整数均在 1∼109 范围内),表示整数数列。

输出格式:

输出一个整数,表示数列的第 k 小数。

数据范围:

1≤n≤100000 ,
1≤k≤n

输入样例:

5 3
2 4 1 5 3

输出样例:

3

根据我们上述的快排思路,我们还可以再多分一步就可以

  1. 先确定分界点:左右极点,中间值
  2. 左边所有数<= x,右边所有数>= x
  3. 当我们找的k小于等于x的时候,就递归左边所有的数Left,反之,当k大于x的时候,就递归右边的所有的数Right
  1. 首先我们需要创建两个整数 n 和 k,创建数组arr来输入
Scanner s  =  new Scanner(System.in);
int n = s.nextInt();
int k = s.nextInt();
int[] arr = new int[n];
for(int i = 0;i < arr.length;i++){
    arr[i] = s.nextInt();
}
  1. 接下来我们需要按照快排函数来实现它,和上面一题思路一样代码也一样,模板照抄

①:分情况处理

if(left >= right) return left;
int x = arr[(left + right) / 2],i = left - 1,j = right + 1;
while(i < j){
    while(arr[++i] < x);
    while(arr[--j] > x);
    if(i < j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

②:边界问题

int sl = j - left + 1;
if(k <= sl) return quickSort(arr,left,j,k);
else return quickSort(arr,j+1,right,(k-sl));

在这里sl代表小于x的区域,它的范围个数是 j - left + 1,当k值小于第一区域个数时,返回的就是第一个区域的个数数值,当它个数范围比第一区域大的时候,就在大于x的区域找,第二个区域的范围就是 j + 1到 right,然后返回值为k - sl

附上总的代码

public static void main(String[] args){
    Scanner s  =  new Scanner(System.in);
    int n = s.nextInt();
    int k = s.nextInt();
    int[] arr = new int[n];
    for(int i = 0;i < arr.length;i++){
        arr[i] = s.nextInt();
	}
    int result = quickSort(arr,0,n-1,k);
    System.out.print(arr[result]);
}

public static int quickSort(int[] arr,int left,int right,int k){
    if(left >= right) return left;
    int x = arr[(left + right) / 2],i = left - 1,j = right + 1;
    while(i < j){
        while(arr[++i] < x);
        while(arr[--j] > x);
        if(i < j){
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    int sl = j - left + 1;
    if(k <= sl) return quickSort(arr,left,j,k);
    else return quickSort(arr,j+1,right,(k-sl));
}

到了这里,关于【算法基础】(一)基础算法 --- 快速排序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【排序算法】快速排序的基本算法

            快速排序是应用最广泛的排序算法,流行的原因是它实现简单,适用于各种不同的输入数据且在一般应用中比其他排序算法都要快得多。快速排序引人注目的特点是原地排序,只需要一个很小的辅助栈,且将长度为N的数组排序所需时间和NlgN成正比。另外,快速排序

    2024年01月22日
    浏览(51)
  • 【排序算法】归并排序与快速排序

           🔥🔥 欢迎来到小林的博客!!       🛰️博客主页:✈️小林爱敲代码       🛰️博客专栏:✈️ 算法训练笔记       🛰️社区 :✈️ 进步学堂       🛰️欢迎关注:👍点赞🙌收藏✍️留言 今天给大家分享两种排序,一种是

    2024年01月19日
    浏览(39)
  • 【排序算法(三)】交换排序(冒泡排序&&快速排序)

    ​ ​📝个人主页:@Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:数据结构 🎯 长路漫漫浩浩,万事皆有期待 上一篇博客:【排序算法(二)】选择排序(直接选择排序堆排序) 冒泡排序属于交换排序,所谓 交换排序 就是就是根据序列中两个记录

    2023年04月22日
    浏览(44)
  • 排序算法1:冒泡排序、快速排序、插入排序

    排序算法:交换类排序,插入类排序、选择类排序、归并类排序 交换类排序:冒泡排序、快速排序 一、冒泡排序  时间复杂度:内层是ji,外层是从0到n-1,运行的总次数是1+2+3+4+...+n-1,即O() 空间复杂度:O(1),没有使用额外空间,不会因为n的变化而变化 如果数组本身有序,最

    2024年02月21日
    浏览(46)
  • 【算法】排序——选择排序和交换排序(快速排序)

     ========================================================================= 主页点击直达: 个人主页 我的小仓库: 代码仓库 C语言偷着笑: C语言专栏 数据结构挨打小记:初阶数据结构专栏 Linux被操作记:Linux专栏 LeetCode刷题掉发记:LeetCode刷题 算法头疼记:算法专栏  =========================

    2024年02月08日
    浏览(46)
  • 【算法系列 | 5】深入解析排序算法之——快速排序

    你只管努力,其他交给时间,时间会证明一切。 文章标记颜色说明: 黄色 :重要标题 红色 :用来标记结论 绿色 :用来标记一级论点 蓝色 :用来标记二级论点 决定开一个算法专栏,希望能帮助大家很好的了解算法。主要深入解析每个算法,从概念到示例。 我们一起努力

    2024年02月08日
    浏览(47)
  • 排序算法二 归并排序和快速排序

    目录 归并排序 快速排序 1 挖坑法​编辑 2 Hoare法 快排的优化 快排的非递归方法 七大排序算法复杂度及稳定性分析 归并排序是建立在归并操作上的一种有效的排序算法,将以有序的子序列合并,得到完全有序的序列,即先使每个子序列有序,在使子序列段间有序.若将两个有序的

    2024年02月07日
    浏览(40)
  • 【排序算法系列】快速排序

    文章中的部分照片来源于哔站 黑马程序员阿伟老师 处,仅用学习,无商用,侵权联系删除! 要想学习快速排序,前提必须了解 递归算法 概况 快速排序是一种高效的排序算法,它采用了分治的策略。 基本思想 是选择一个基准数,通过一趟排序将待排序序列划分成两个子序

    2024年02月20日
    浏览(36)
  • 排序算法:快速排序(递归)

    所属专栏:C++初阶 引言:这里所说的快速排序有三种,第一种是 霍尔大佬 自创的,还有一种叫做 挖坑法 ,另外一种叫 前后指针法 1.这里我们先把中间值定位数组中的首元素的值,设为key变量, 大于key的放右边,小于key的放左边 2.定义left为从数组0下标开始找大于key的数,如

    2024年04月09日
    浏览(46)
  • 快速排序-排序算法

    算法思想 快速排序采用的仍然是 分治 的思想。 Step1.每次在无序的序列中选取一个基准数。 Step2.然后将大于和小于基准数的元素分别放置于基准数两边。(前面部分的元素均小于或等于基准数,后面部分均大于或等于基准数) Step3.然后采用分治法(递归)分别对两侧部分重

    2024年01月25日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包