热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用快排一次划分求第k小、使用优先级队列、使用堆

快排#includeusingnamespacestd;****************************************Partitio

快排

#include
using namespace std;/**************************************
*
* Partition() 快排的一次划分函数
*
*/
// 把小的插入头部位置,可用于链表
int Partition(int* ar, int left, int right) {int i &#61; left - 1, j &#61; left;int tmp &#61; ar[j];while (j <&#61; right) {if (ar[j] <&#61; tmp) {std::swap(ar[i &#43; 1], ar[j]);i &#43;&#61; 1;}j &#43;&#61; 1;}std::swap(ar[left], ar[i]);return i;
}// 双指针单方向推进
int Partition1(int* ar, int left, int right)
{int i &#61; left, j &#61; left &#43; 1;int tmp &#61; ar[i];while (i < right && j < right){while (j <&#61; right && ar[j] <&#61; tmp) j&#43;&#43;; // 大值if (j > right) break;i &#61; j &#43; 1;while (i <&#61; right && ar[i] > tmp) i&#43;&#43;; // j后小值if (i > right) break;std::swap(ar[i], ar[j]);//j&#43;&#43;;}std::swap(ar[j - 1], ar[left]);return j - 1;
}// 双指针&#xff0c;两边夹逼推进
int Partition2(int* ar, int left, int right)
{int i &#61; left, j &#61; right;int tmp &#61; ar[i];while (i < j){while (i < j && ar[j] > tmp) j--;if (i >&#61; j) break;while (i < j && ar[i] <&#61; tmp) i&#43;&#43;;if (i >&#61; j) break;std::swap(ar[i], ar[j]);}std::swap(ar[i], ar[left]);return i;
}// 快排中间层&#xff0c;递归调用一次划分
void QuickPass(int* ar, int left, int right)
{if (left < right){int pos &#61; Partition(ar, left, right);QuickPass(ar, 0, pos - 1);QuickPass(ar, pos &#43; 1, right);}
}
// 快排接口
void QuickSort(int* ar, int n)
{if (nullptr &#61;&#61; ar || n < 1) return;QuickPass(ar, 0, n - 1);
}int main()
{int arr[] &#61; { 4,5,2,3,4,4,3,1,7,8,4,9,10,6 };QuickSort(arr, sizeof(arr) / sizeof(arr[0]));for (int a : arr)std::cout << a << &#39; &#39;;std::cout << std::endl;return 0;
}

有关快排优化&#xff1a;参考&#xff1a;万字长文带你走进快速排序的前世今生【拓跋阿秀】

  1. 非递归
  2. 优化基准选取位置&#xff0c;如三位取中法等
  3. 设定一个阈值&#xff0c;在阈值范围内使用插入排序&#xff08;插入排序在元素比较少时效率最高&#xff09;
  4. 三向切分。



使用快排的的一次划分&#xff0c;我们可以实现寻找无序数列中的第K小。

#include
using namespace std;
int OnePartition(int* ar, int left, int right)
{int midVal &#61; ar[left]; // 基准while (left < right){while (left < right){if (ar[right] >&#61; midVal) right--;else {swap(ar[right], ar[left&#43;&#43;]); break;}}while (left < right){if (ar[left] <&#61; midVal) left&#43;&#43;;else {swap(ar[left], ar[right--]); break;}}}return left;
}
int Select_K(int* ar, int left, int right, int pos)
{int i &#61; OnePartition(ar, left, right);if (i < pos - 1) i &#61; Select_K(ar, i &#43; 1, right, pos); // 右边else if (i > pos - 1) i &#61; Select_K(ar, left, i - 1, pos); //左边else return ar[i];
}int main()
{int arr[] &#61; { 67,12,89,23,90,100 ,34,78,56,45 };int n &#61; sizeof(arr) / sizeof(arr[0]);//cout <for (int i &#61; 1; i < 11; i&#43;&#43;)cout << i << ": " << Select_K(arr, 0, n - 1, i) << endl;return 0;
}/*输出&#xff1a;1: 122: 233: 344: 455: 566: 677: 788: 899: 9010: 100
*/

除此之外&#xff0c;我们可以使用优先级队列&#xff0c;或直接使用数据结构堆。

优先级队列&#xff0c;大数优先级高&#xff08;底层大根堆实现&#xff09;。使用小数优先级高的方式也可以实现下列算法。

#include
#include
#include
using namespace std;// 第k大
int KthLargest(int arr[], int n, int k)
{if (nullptr &#61;&#61; arr || n <&#61; 0 || k > n) return -1;//priority_queue pq; // 默认产生大根堆,数据大的优先priority_queue<int, vector<int>, less<int>> pq;for (int i &#61; 0; i < n; i&#43;&#43;){pq.push(arr[i]); // 把数据加入优先级队列中}// 把第1大&#xff0c;第2大&#xff0c;第3....&#xff0c;到第k次时为第k大while (k > 1){pq.pop();k--;}return pq.top();
}
// 第k小
int KthSmall(int arr[], int n, int k)
{if (nullptr &#61;&#61; arr || n <&#61; 0 || k > n) return -1;priority_queue<int> pq;for (int i &#61; 0; i < n; i&#43;&#43;){pq.push(arr[i]); // 把数据加入优先级队列中}k &#61; n - k &#43; 1; // 求第k小&#xff0c;把n-k&#43;1的大数据出队&#xff0c;剩下的就是第k小while (k > 1){pq.pop();k--;}return pq.top();
}int main()
{int arr[] &#61; { 67,12,89,23,90,100 ,34,78,56,45 };int n &#61; sizeof(arr) / sizeof(arr[0]);for (int i &#61; 1; i <&#61; n; i&#43;&#43;)cout << i << ":\t small " << KthSmall(arr, n, i)<< "\t big" << KthLargest(arr, n, i) << endl;return 0;
}
/*输出&#xff1a;1: small 12 big1002: small 23 big903: small 34 big894: small 45 big785: small 56 big676: small 67 big567: small 78 big458: small 89 big349: small 90 big2310: small 100 big12*/

直接使用数据结构堆。

#include
#include
#include
using namespace std;// 第k大
int KthLargest(int arr[], int n, int k)
{if (nullptr &#61;&#61; arr || n <&#61; 0 || k > n) return -1;// std::make_heap(arr, arr &#43; n); // 在一个迭代器范围内构造一个堆&#xff08;默认最大堆&#xff09;std::make_heap(arr, arr &#43; n, less<int>()); // 创建大根堆while (k > 1){pop_heap(arr, arr &#43; n); // 弹出堆顶元素&#xff0c;并把它放到末尾位置n--;make_heap(arr, arr &#43; n, less<int>()); // 将剩余元素调整为堆k--;}return arr[0];
}
// 第k小
int KthSmall(int arr[], int n, int k)
{if (nullptr &#61;&#61; arr || n <&#61; 0 || k > n) return -1;//n &#61; n - 1; // 将长度变成下标std::make_heap(arr, arr &#43; n, greater<int>()); // 创建小根堆while (k > 1){pop_heap(arr, arr &#43; n); // 弹出堆顶元素&#xff0c;并把它放到末尾位置n--;make_heap(arr, arr &#43; n, greater<int>()); // 将剩余元素调整为堆k--;}return arr[0];
}int main()
{int arr[] &#61; { 67,12,89,23,90,100 ,34,78,56,45 };int brr[] &#61; { 67,12,89,23,90,100 ,34,78,56,45 };int n &#61; sizeof(arr) / sizeof(arr[0]);for (int i &#61; 1; i <&#61; n; i&#43;&#43;)cout << i << ":\t small " << KthSmall(arr, n, i)<< "\t big" << KthLargest(arr, n, i) << endl;return 0;
}/*输出&#xff1a;1: small 12 big1002: small 23 big903: small 34 big894: small 45 big785: small 56 big676: small 67 big567: small 78 big458: small 89 big349: small 90 big2310: small 100 big12
*/


推荐阅读
  • 本文将深入探讨 iOS 中的 Grand Central Dispatch (GCD),并介绍如何利用 GCD 进行高效多线程编程。如果你对线程的基本概念还不熟悉,建议先阅读相关基础资料。 ... [详细]
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • 本报告对2018年湘潭大学程序设计竞赛在牛客网上的时间数据进行了详细分析。通过统计参赛者在各个时间段的活跃情况,揭示了比赛期间的编程频率和时间分布特点。此外,报告还探讨了选手在准备过程中面临的挑战,如保持编程手感、学习逆向工程和PWN技术,以及熟悉Linux环境等。这些发现为未来的竞赛组织和培训提供了 valuable 的参考。 ... [详细]
  • 题目解析给定 n 个人和 n 种书籍,每个人都有一个包含自己喜好的书籍列表。目标是计算出满足以下条件的分配方案数量:1. 每个人都必须获得他们喜欢的书籍;2. 每本书只能分配给一个人。通过使用深度优先搜索算法,可以系统地探索所有可能的分配组合,确保每个分配方案都符合上述条件。该方法能够有效地处理这类组合优化问题,找到所有可行的解。 ... [详细]
  • 深入解析Android 4.4中的Fence机制及其应用
    在Android 4.4中,Fence机制是处理缓冲区交换和同步问题的关键技术。该机制广泛应用于生产者-消费者模式中,确保了不同组件之间高效、安全的数据传输。通过深入解析Fence机制的工作原理和应用场景,本文探讨了其在系统性能优化和资源管理中的重要作用。 ... [详细]
  • 本文介绍了 NOI Open Judge 6049 购书问题的详细解法,代码简洁易懂,并附有详细的注释和解释。 ... [详细]
  • 本文详细介绍了如何使用Python的多进程技术来高效地分块读取超大文件,并将其输出为多个文件。通过这种方式,可以显著提高读取速度和处理效率。 ... [详细]
  • 零拷贝技术是提高I/O性能的重要手段,常用于Java NIO、Netty、Kafka等框架中。本文将详细解析零拷贝技术的原理及其应用。 ... [详细]
  • 本文介绍如何使用线段树解决洛谷 P1531 我讨厌它问题,重点在于单点更新和区间查询最大值。 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • Java高并发与多线程(二):线程的实现方式详解
    本文将深入探讨Java中线程的三种主要实现方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并分析它们之间的异同及其应用场景。 ... [详细]
  • 检查在所有可能的“?”替换中,给定的二进制字符串中是否出现子字符串“10”带 1 或 0 ... [详细]
  • poj 3352 Road Construction ... [详细]
  • 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4277。作者:Bob Lee,日期:2012年9月15日。题目描述:给定n个木棍,求可以组成的不同三角形的数量,最多15根木棍。 ... [详细]
  • Python 程序转换为 EXE 文件:详细解析 .py 脚本打包成独立可执行文件的方法与技巧
    在开发了几个简单的爬虫 Python 程序后,我决定将其封装成独立的可执行文件以便于分发和使用。为了实现这一目标,首先需要解决的是如何将 Python 脚本转换为 EXE 文件。在这个过程中,我选择了 Qt 作为 GUI 框架,因为之前对此并不熟悉,希望通过这个项目进一步学习和掌握 Qt 的基本用法。本文将详细介绍从 .py 脚本到 EXE 文件的整个过程,包括所需工具、具体步骤以及常见问题的解决方案。 ... [详细]
author-avatar
手机用户2602932547
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有