在n個數中找出K個最大的數
主要思想:在n個數中找k個最大(小)的數,肯定要用到最小堆、最大堆的思想,而這種思想在C中STL中的優先隊列(priority_queue)中體現比較明顯,優先隊列底層實現就是運用了最大堆、最小堆原理,如果要求用c實現的話,可以直接用。如果用C語言實現的話,就需要自己定於堆的一系列操作,自己實現最大堆、最小堆。
實現一:C++實現
直接調用STL中的priority_queue.
vector<int>search_max_K(vector<int>vec,int k)
{
priority_queue<int, vector<int>, greater<int> >que;
for (int i = 0; i < k; i++)
que.push(vec[i]);
for (int i = k; i < vec.size(); i++)
{
if (vec[i]>que.top())
{
que.pop();
que.push(vec[i]);
}
}
vector<int>result;
while (!que.empty())
{
result.push_back(que.top());
que.pop();
}
return result;
}
注:STL中的堆的使用方法
STL裏面的堆操作一般用到的只有4個:make_heap();、pop_heap();、push_heap();、sort_heap(); 他們的頭文件函數是#include <algorithm>
(1)make_heap();函數原型是:void make_heap(first_pointer,end_pointer,compare_function);
一個參數是數組或向量的頭指針,第二個是數組或向量的尾指針(注意這裏是尾後指針或尾後迭代器,而不是最後一個元素的地址)。第三個參數是比較函數,在缺省的時候,默認是大跟堆(注意如果要自定義比較函數話:最大堆用小於函數;最小堆用大於函數)。
作用:把這一段的數組或向量做成一個堆的結構。堆的範圍是[first,last) 注意不包括last尾後指針或尾後迭代器
(2)pop_heap();函數原型是:void pop_heap(first_pointer,end_pointer,compare_function);
作用:pop_heap()不是真的把最大(最小)的元素從堆中彈出來。而是重新排序堆。它把first和last-1這兩個堆元素交換位置,然後將[first,last-1)的之間的元素做成一個堆,不包括last-1。
(3)push_heap();函數原型是: void pushheap(first_pointer,end_pointer,compare_function);
作用:push_heap()假設由[first,last-1)是一個有效的堆,然後,再把堆中的新元素last-1加進來,做成一個堆,堆的範圍變成[first,last)。
(4)用的不多。sort_heap();函數原型是:void sort_heap(first_pointer,end_pointer,compare_function);
作用:sort_heap對[first,last)中的序列進行排序。它假設這個序列是有效堆。(當然,經過排序之後就不是一個有效堆了)
linkhttps://blog.csdn.net/my_lovely_lemon_tree/article/details/78007316
linkhttps://blog.csdn.net/xiajun07061225/article/details/8553808
實現二:C語言實現
手動實現最小堆所有操作(堆的插入、刪除、調整、建立等操作)
主要的函數:
vector<int>Get_Max_K(vector<int>vec, int k)
{
vector<int>num_k(vec.begin(), vec.begin()+k);
CreatHeap(&num_k[0], k);
for (int i = k; i < vec.size(); i++)
{
if (vec[i]>=num_k[0])
{
num_k[0] = vec[i];
HeapAdjust(&num_k[0], 0, k);
}
}
vector<int>result(num_k.begin(), num_k.begin()+k);
return result;
}
定義的子函數:
#include<iostream>
#include<functional>
#include<vector>
#include<set>
#include<queue>
#include<hash_map>
using namespace std;
//hash_map<const char*, int>f_ip;
void HeapAdjust(int *heap, int top, int n);
vector<int>search_max_K(vector<int>vec,int k)
{
priority_queue<int, vector<int>, less<int> >que;
for (int i = 0; i < k; i++)
que.push(vec[i]);
for (int i = k; i < vec.size(); i++)
{
if (vec[i]<que.top())
{
que.pop();
que.push(vec[i]);
}
}
vector<int>result;
while (!que.empty())
{
result.push_back(que.top());
que.pop();
}
return result;
}
//自己寫最小堆進行實現,其中包括插入、刪除、調整等子操作
//堆的插入
/*
* 堆插入算法。(小頂堆)
* 先將num插入堆尾,易知從新數據的父結點到根結點是一個有序的序列,
* 將num插入到該有序序列當中,該過程爲直接插入排序。
* 未插入前數據長度爲n。
*/
void HeapInsert(int *heap, int n, int num)
{
int i, j;
heap[n] = num;//num插入堆尾
i = n;
j = (n - 1) / 2;//j指向i的父結點
//注意不要漏掉i!=0的條件。因爲必須保證i有父結點j。j>=0並不能保證i!=0。
//如果沒有此條件,當i=0時,j=0,若heap[0]>num,程序就會陷入死循環。
while (j >= 0 && i != 0)
{
if (heap[j] <= num)
break;
heap[i] = heap[j];
i = j;
j = (i - 1) / 2;
}
heap[i] = num;
}
//堆元素的刪除
/*
* 堆刪除算法。(刪除堆頂元素)
* n表示未刪除前堆中數據的總數。
*/
void HeapDelete(int *heap, int n)
{
//使用堆尾元素直接覆蓋堆頂元素。
heap[0] = heap[n - 1];
//從堆頂到堆尾(此時堆中只有n-1個元素)進行堆調整。
HeapAdjust(heap, 0, n - 1);
}
/*
* 堆調整算法。(小頂堆)
* 已知heap[top]結點的左右子樹均爲堆,調整堆中元素,使以heap[top]爲根結點的樹爲堆。
* n爲堆中元素總數。
*/
void HeapAdjust(int *heap, int top, int n)
{
int j = 2 * top + 1; //左孩子結點
int temp = heap[top];
while (j < n)
{
if (j + 1 < n&&heap[j + 1] < heap[j])
j++; //使j指向左右孩子中較小的結點。
if (heap[j] >= temp)
break;
heap[top] = heap[j];
top = j;
j = 2 * top + 1;
}
heap[top] = temp;
}
//堆的建立
/*
* 建堆算法。
* 將無序數組array[]轉換爲堆。
*/
void CreatHeap(int *array, int n)
{
int i;
//最後一個結點的編號爲n-1,該結點的父節點(n-2)/2爲最後一個非終端結點。
//但是感覺這裏的n不是頂點的個數,而應該是存儲數組最後一個的索引,即最後一個頂點對應數組中的位置。
//從結點(n-2)/2到根結點,依次進行堆調整。
for (i = (n - 2) / 2; i >= 0; i--)
{
HeapAdjust(array, i, n);
}
}
vector<int>Get_Max_K(vector<int>vec, int k)
{
vector<int>num_k(vec.begin(), vec.begin()+k);
CreatHeap(&num_k[0], k);
for (int i = k; i < vec.size(); i++)
{
if (vec[i]>=num_k[0])
{
num_k[0] = vec[i];
HeapAdjust(&num_k[0], 0, k);
}
}
vector<int>result(num_k.begin(), num_k.begin()+k);
return result;
}
int main()
{
int a[] = { 1, 2, 1, 3, 4, 5, 6, 9, 6, 9, 4, 9 };
vector<int>vec(a,a+12);
//vector<int>result = search_max_K(vec, 4);
vector<int>result = Get_Max_K(vec, 4);
return 0;
}