此算法借用快速排序算法。

这个快速选择算法主要利用递归调用,数组存储方式。包含3个文件,头文件QuickSelect.h,库函数QuickSelect.c,测试文件TestQuickSelect。

其中Cutoff可以自己给定,这个当开始给定的数组(或者递归调用产生的子数组)的元素个数<=20个时,采用插入排序。一般认为当元素个数<=20时,插入排序更快。这个20不是固定的,在这附近浮动都可以的。

头文件QuickSelect.h

  1. #ifndef QuickSelect_H
  2. #define QuickSelect_H
  3. #define Cutoff 20
  4. typedef int ElementType;
  5. ElementType Median3(ElementType A[], int left, int right);
  6. void Swap(ElementType *p, ElementType*q);
  7. void InsertionSort(ElementType A[], int N);
  8. ElementType QuickSelect(ElementType A[],int k, int N);
  9. ElementType Qselect(ElementType A[],int k, int Left, int Right);
  10. void PrintMatrix(ElementType A[], int N);
  11. #endif // !QuickSelect_H

库函数QuickSelect.c

  1. #include "QuickSelect.h"
  2. #include<stdio.h>
  3. //通过三数中值分割法获得数组的枢纽元
  4. ElementType Median3(ElementType A[], int Left, int Right)
  5. {
  6. int Center = (Left + Right) / ;
  7. if (A[Left] > A[Right])
  8. Swap(&A[Left], &A[Right]);
  9. if (A[Left] > A[Center])
  10. Swap(&A[Left], &A[Center]);
  11. if (A[Center] > A[Right])
  12. Swap(&A[Center], &A[Right]);
  13. //上述三次交换使得:A[Left]<A[Center]<A[Right]
  14. Swap(&A[Center], &A[Right - ]);
  15. return A[Right - ];//返回枢纽元;
  16. }
  17.  
  18. //交换指针p和q各自指向的值;
  19. void Swap(ElementType * p, ElementType * q)
  20. {
  21. ElementType Tmp;
  22. Tmp = *p;
  23. *p = *q;
  24. *q = Tmp;
  25. }
  26.  
  27. //当开始给定的数组(或者递归调用产生的子数组)的元素个数<=20个时,采用插入排序。
  28. void InsertionSort(ElementType A[], int N)
  29. {
  30. int j, P;
  31. ElementType Tmp;
  32. for (P = ; P < N; P++)
  33. {
  34. Tmp = A[P];
  35. for (j = P; j > && A[j - ] > Tmp; j--)
  36. A[j] = A[j - ];
  37. A[j] = Tmp;
  38. }
  39. }
  40.  
  41. //快速选择算法驱动程序
  42. ElementType QuickSelect(ElementType A[],int k, int N)
  43. {
  44. return Qselect(A, k-, , N - );//该程序即为,输入,k,返回A[k]。因为A从0开始存储,如果想找第5个最小值,其实找的是A[4],所以当我们找第k个值时,应输入k-1。
  45. }
  46.  
  47. //快速选择核心算法
  48. ElementType Qselect(ElementType A[], int k, int Left, int Right)
  49. {
  50. int i, j;
  51. ElementType Pivot;
  52. if (Left + Cutoff - <= Right)//此处Cutoff-1是为了和N-1=Right对应上
  53. {
  54. Pivot = Median3(A, Left, Right);//调用枢纽元函数选取枢纽元
  55. i = Left; j = Right - ;
  56. for (; ;)
  57. {
  58. while (A[++i] < Pivot);
  59. while (A[--j] > Pivot);
  60. if (i < j) Swap(&A[i], &A[j]);
  61. else break;
  62. }
  63. Swap(&A[i], &A[Right - ]);
  64. if (k < i)
  65. Qselect(A, k, Left, i - );//对剩下小于枢纽元的元素递归排序
  66. else if (k>i)
  67. Qselect(A, k, i + , Right);//对剩下大于枢纽元的元素递归排序
  68. //当k=i时,即查询的值==枢纽元,则找到了,返回A[k]
  69. }
  70. else//当最后子数组只有Cutoff个,则采用插入排序。
  71. InsertionSort(A + Left, Right - Left + );
  72. return A[k];
  73. }
  74.  
  75. //打印数组
  76. void PrintMatrix(ElementType A[], int N)
  77. {
  78. for (int i = ; i < N; i++)
  79. printf("%d ", A[i]);
  80. }

测试文件TestQuickSelect

  1. #include "QuickSelect.h"
  2. #include <stdio.h>
  3. #include<time.h>
  4. #include<stdlib.h>
  5. #define N 100000
  6. int main()
  7. {
  8. ElementType A[N] ;
  9. int ID;
  10. srand((unsigned)time(NULL));
  11. for (int i = ; i < N; i++)
  12. {
  13. //A[i] = rand() % N;
  14. A[i] =N-i;//100000个数,倒序排
  15. }
  16.  
  17. printf("\n");
  18. //PrintMatrix(A, N);
  19. printf("请输入要查询的ID:");
  20. scanf_s("%d", &ID);
  21. printf("Result:%d",QuickSelect(A, ID, N));
  22. printf("\n");
  23. }

找到第k个最小元----快速选择的更多相关文章

  1. 在未排序的数组中找到第 k 个最大的元素

    在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 输出: 5 ...

  2. 【一起刷LeetCode】在未排序的数组中找到第 k 个最大的元素

    题目描述 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 ...

  3. 选取第K大数的快速选择算法和注意事项

    快速选择算法,是一种能在大致O(N)的时间内选取数组中第k大或者k小的算法.其基本思路与快速排序算法类似,也是分治的思想. 其实这个算法是个基础算法,但是不常用,所以今天编的时候错了POJ2388,才 ...

  4. [程序员代码面试指南]第9章-在两个长度相等的排序数组中找到第k小的数(二分)

    题目 给定两个有序数组arr1和arr2,再给定一个整数k,返回所有的数中第k小的数. 题解 利用题目"在两个长度相等的排序数组中找到第上中位数"的函数 分类讨论 k < 1 ...

  5. 比列的数目更多,以便找到第一k小值

    问题叙述性说明:现有n作为一个有序序列(2,3,9),(3,5,11,23),(1,4,7,9,15,17,20),(8,15,35,9),(20,30,40),第k小值. 问题分析:可用多路归并排序 ...

  6. 215. Kth Largest Element in an Array【Medium】【找到第 k 大的元素】

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  7. 算法总结之 在两个排序数组中找到第K小的数

    给定两个有序数组arr1 和 arr2 ,再给定一个int K,返回所有的数中第K小的数 要求长度如果分别为 N M,时间复杂度O(log(min{M,N}),额外空间复杂度O(1) 解决此题的方法跟 ...

  8. 【Leetcode 堆、快速选择、Top-K问题 BFPRT】有序矩阵中第K小的元素(378)

    题目 给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素. 请注意,它是排序后的第k小元素,而不是第k个元素. 示例: matrix = [ [ 1, 5, 9], [ ...

  9. 【Leetcode 堆、快速选择、Top-K问题 BFPRT】数组中的第K个最大元素(215)

    这道题很强大,引出了很多知识点 题目 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5 ...

随机推荐

  1. Ubuntu下使用nvm

    写在前面:刚写着写着博客就跨年了,希望新的一年大家万事如意,一切向"前"看! 安装 wget -qO- https://raw.githubusercontent.com/crea ...

  2. ASP.NET Aries 入门开发教程9:业务表单的开发

    前言: 经过前面那么多篇的列表的介绍,终于到了大伙期待的表单开发了. 也是本系列的最后一篇文章了! 1:表单页面的权限设置与继承 对于表单页面,权限的设置有两种: 1:你可以选择添加菜单(设置为不显示 ...

  3. 如何在nuget上传自己的包+搭建自己公司的NuGet服务器(新方法)

    运维相关:http://www.cnblogs.com/dunitian/p/4822808.html#iis 先注册一个nuget账号https://www.nuget.org/ 下载并安装一下Nu ...

  4. python爬取github数据

    爬虫流程 在上周写完用scrapy爬去知乎用户信息的爬虫之后,github上star个数一下就在公司小组内部排的上名次了,我还信誓旦旦的跟上级吹牛皮说如果再写一个,都不好意思和你再提star了,怕你们 ...

  5. 个人网站对xss跨站脚本攻击(重点是富文本编辑器情况)和sql注入攻击的防范

    昨天本博客受到了xss跨站脚本注入攻击,3分钟攻陷--其实攻击者进攻的手法很简单,没啥技术含量.只能感叹自己之前竟然完全没防范. 这是数据库里留下的一些记录.最后那人弄了一个无限循环弹出框的脚本,估计 ...

  6. 小兔JS教程(三)-- 彻底攻略JS回调函数

    这一讲来谈谈回调函数. 其实一句话就能概括这个东西: 回调函数就是把一个函数当做参数,传入另一个函数中.传进去的目的仅仅是为了在某个时刻去执行它. 如果不执行,那么你传一个函数进去干嘛呢? 就比如说对 ...

  7. spring无法读取properties文件数据

    只讲述异常点,关于怎么配置文件,这里不做说明.   1. controller中无法读取config.properties文件 controller中注入的@Value配置是从servlet-cont ...

  8. 易用BPM时代,软件开发者缘何选择H3?

    近年来,企业级软件开发市场暗流汹涌,呈现出多种态势.软件开发团队规模趋于小型化,工作方式趋于快捷化,超过半数的软件开发者在工作中会选择使用易用的软件开发工具.随着流程管理越来越受到企业的重视,流程开发 ...

  9. 2016年中国微信小程序专题研究报告

    2016年12月29日,全球领先的移动互联网第三方数据挖掘和分析机构iiMedia Research(艾媒咨询)权威首发<2016年中国微信小程序专题研究报告>. 报告显示,82.6%手机 ...

  10. excel常用技巧

    复制表格时,如果要加上行标和列标.页面布局->工作表选项:标题,勾上打印->复制下拉框->复制为图片加上打印样式 一行长拆成几行短或几行短变成一行长的文本拆分,可以通过:填充-> ...