查找数组中前K个大的和小的元素

来源:互联网 发布:想学做淘宝怎么学 编辑:程序博客网 时间:2024/05/12 23:48

一、查找第K大的元素的算法思想

将数组前K个元素构建一个小顶堆,扫描数组后面的元素,与堆顶元素比较,如果比堆顶元素大,就替换堆顶元素,并重新调整堆;否则继续扫描后续元素。最后将堆中的元素逆序排序。

    

二、查找第K小的元素

将数组前K个元素构建一个大顶堆,扫描数组后面的元素,与堆顶元素比较,如果比堆顶元素小,就替换堆顶元素,并重新调整堆;否则继续扫描后续元素。最后将堆中的元素升序排序。


/* * ===================================================================================== * *       Filename:  frontkthnumbers.cpp * *    Description:  找出数组中前K个大或小的数 * *        Version:  1.0 *        Created:  2012年11月25日 16时11分31秒 *       Revision:  none *       Compiler:  gcc * *         Author:  Xingwang Su (http://blog.csdn.net/njzhiyuan) *   Organization:   * * ===================================================================================== */#include <iostream>#include <vector>#include <string>extern "C" {#include <stdlib.h>#include <sysexits.h>}using namespace std;template <typename T>class ArrayElemt {public:explicit ArrayElemt(size_t pos, const T &val);explicit ArrayElemt(){}inline size_t get_pos();inline T get_val();inline bool operator < (const T &val) const;inline bool operator > (const T &val) const;template <typename C>friend inline bool operator < (const ArrayElemt<C> &a, const ArrayElemt<C> &b);template <typename C>friend inline bool operator < (const C &val, const ArrayElemt<C> &ae);template <typename C>friend inline bool operator > (const ArrayElemt<C> &a, const ArrayElemt<C> &b);template <typename C>friend inline bool operator > (const C val, const ArrayElemt<C> &ae);template <typename C>friend ostream & operator << (ostream &os, const ArrayElemt<C> &ae);private:size_t pos;T val;};template <typename T> ArrayElemt<T>::ArrayElemt(size_t pos, const T &val) : pos(pos), val(val) {}template <typename T>size_t ArrayElemt<T>::get_pos() {return pos;}template <typename T>T ArrayElemt<T>::get_val() {return val;}template <typename T>bool ArrayElemt<T>::operator < (const T &val) const {return this->val < val;}template <typename T>bool operator < (const ArrayElemt<T> &a, const ArrayElemt<T> &b) {return a.val < b.val;}template <typename T>bool operator < (const T &val, const ArrayElemt<T> &ae) {return val < ae.val;}template <typename T>bool ArrayElemt<T>::operator > (const T &val) const {return this->val > val;}template <typename T>bool operator > (const T &val, const ArrayElemt<T> &ae) {return val > ae.val;}template <typename T>bool operator > (const ArrayElemt<T> &a, const ArrayElemt<T> &b) {return a.val > b.val;}template <typename T>ostream & operator << (ostream &os, const ArrayElemt<T> &ae) {os << "[" << ae.pos << "] = " << ae.val;return os;}//计算左子树根节点下标,注意下标从0开始inline size_t left_child(size_t parent) {return parent * 2 + 1;}// 调整大顶堆template <class CD>void maxheap_adjust(vector<CD> &arr, size_t start, size_t end) {CD tmp = arr[start];for (size_t child = left_child(start); child < end; child = left_child(child)) {if (child < end - 1 && arr[child] < arr[child + 1]) ++child;if (tmp > arr[child])break;arr[start] = arr[child];start = child;}arr[start] = tmp;}//调整小顶堆template <class CD>void minheap_adjust(vector<CD> &arr, size_t start, size_t end) {CD tmp = arr[start];for (size_t child = left_child(start); child < end; child = left_child(child)){if (child < end - 1 && arr[child] > arr[child + 1])++child;if (tmp < arr[child])break;arr[start] = arr[child];start = child;}arr[start] = tmp;}template <class CD>void build_heap(vector<CD> &arr, void (*adjust)(vector<CD> &, size_t, size_t)) {for(size_t child = arr.size() / 2; child > 0; --child)adjust(arr, child, arr.size());//size_t类型变量的特殊性,其值总是大于等于0adjust(arr, 0, arr.size());}template <typename T>void heap_sort(vector<T> &arr, void (*adjust)(vector<T> &arr, size_t, size_t)) {build_heap(arr, adjust);for(size_t index = arr.size() - 1; index > 0; --index) {swap(arr[0], arr[index]);adjust(arr, 0, index);}}template <typename T>inline bool less_than(const ArrayElemt<T> &a, const T &b) {return a < b;}template <typename T>inline bool greater_than(const ArrayElemt<T> &a, const T &b) {return a > b;}template <typename T>vector<ArrayElemt<T> > findfrontkthnums(const vector<T> &arr, size_t kth, bool (*compare)(const ArrayElemt<T> &, const T &), void (*adjust)(vector<ArrayElemt<T> >&, size_t, size_t)) {vector<ArrayElemt<T> > frontend;size_t index;for(index = 0; index < kth; ++index) {frontend.push_back(ArrayElemt<T>(index, arr[index]));}build_heap(frontend, adjust);for(index = kth; index < arr.size(); ++index) {if (compare(frontend[0], arr[index])) {frontend[0] = ArrayElemt<T>(index, arr[index]);adjust(frontend, 0, kth);}}heap_sort(frontend, adjust);return frontend;}template <typename T>void createvalue(vector<T> &arr, int seed = 100) {size_t index = 0;srand((unsigned) time(NULL) + seed);while (index != arr.size()) {arr[index++] = static_cast<T>(rand() % seed);}}template <typename T>void display_vector(const vector<T> &arr, const string &prefix = "", const string &suffix = " ") {for(size_t index = 0; index != arr.size(); ++index)cout << prefix << arr[index] << suffix;cout << endl;}int main(int argc, char *argv[]) {vector<long> array(20);size_t kth = 5;vector<ArrayElemt<long> > frontend;createvalue(array);cout << "原始的数列如下:" <<endl;display_vector(array);frontend = findfrontkthnums(array, kth, less_than, minheap_adjust);cout << "前 " << kth << " 个大的元素是:" << endl;display_vector(frontend, "array", ", ");frontend = findfrontkthnums(array, kth, greater_than, maxheap_adjust);cout << "前 " << kth << " 个小的元素是:" << endl;display_vector(frontend, "array", ", ");cout << "排序后数列如下:" <<endl;heap_sort(array, maxheap_adjust);display_vector(array);return EX_OK;}


执行:

$ g++ --version
g++ (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2
Copyright © 2012 Free Software Foundation, Inc.
本程序是自由软件;请参看源代码的版权声明。本软件没有任何担保;
包括没有适销性和某一专用目的下的适用性担保。

$ g++ -o frontkthnumbers frontkthnumbers.cpp
$ ./frontkthnumbers
原始的数列如下:
3 65 1 4 97 48 4 85 47 5 4 36 97 22 26 91 67 2 61 5
前 5 个大的元素是:
array[12] = 97, array[4] = 97, array[15] = 91, array[7] = 85, array[16] = 67,
前 5 个小的元素是:
array[2] = 1, array[17] = 2, array[0] = 3, array[6] = 4, array[10] = 4,
排序后数列如下:
1 2 3 4 4 4 5 5 22 26 36 47 48 61 65 67 85 91 97 97















原创粉丝点击