您的位置:首页 > 其它

优先级队列

2016-07-11 20:53 218 查看
#ifndef PRIORITY_QUEUE_H_
#define PRIORITY_QUEUE_H_
#include <stdint.h>
#include <iostream>

#define EXCHANGE(a,b,t) do{t=a;a=b;b=t;}while(0)

// bMax = true  : 最大优先级队列
// bMax = false : 最小优先级队列
template<typename T,uint32_t S,bool bMax = true>
class PriorityQueue
{
public:
PriorityQueue();
~PriorityQueue();
int32_t Push(T &data);
int32_t Pop();
T &Front();
bool Empty(){ return size == 0; }
uint32_t Size(){ return size; }
public:
void Dump(const uint32_t length = S);
private:
void MaxHeapify(T arr[],const uint32_t size,const uint32_t i);
void MinHeapify(T arr[],const uint32_t size,const uint32_t i);
uint32_t Parent(uint32_t i){ return i / 2; }
uint32_t Right(uint32_t i){ return i * 2 + 1; }
uint32_t Left(uint32_t i){ return i * 2; }
private:
typedef void (PriorityQueue::*Heapify)(T arr[], const uint32_t size, const uint32_t i);
bool Less(T &left, T &right);
T *arr;
uint32_t size;
Heapify pHeapify;
};

template<typename T, uint32_t S, bool bMax /*= true*/>
bool PriorityQueue<T, S, bMax>::Less(T &left, T &right)
{
if (bMax == true)
{
return left < right;
}
return left > right;
}

template<typename T, uint32_t S, bool bMax /*= true*/>
int32_t PriorityQueue<T, S, bMax>::Pop()
{
if (size == 0){return -1;}
else if (size == 1){ size = 0; }
else
{
arr[0] = arr[--size];
(this->*pHeapify)(arr, size, 0);
}
//Dump(size);
return 0;
}

template<typename T, uint32_t S, bool bMax /*= true*/>
int32_t PriorityQueue<T, S, bMax>::Push(T &data)
{
if (size >= S){ return -1; }
int32_t i = size++;
arr[i] = data;
T tmp;
while (i > 0 && Less(arr[Parent(i)],arr[i]))
{
EXCHANGE(arr[Parent(i)], arr[i], tmp);
i = Parent(i);
}
//Dump(size);
return 0;
}

template<typename T, uint32_t S, bool bMax /*= true*/>
void PriorityQueue<T, S, bMax>::Dump(const uint32_t length /*= S*/)
{
std::cout << size << ":";
for (uint32_t i = 0; i < length;++i)
{
std::cout << arr[i] << " ";// << std::endl;
}
std::cout << std::endl;
}

template<typename T, uint32_t S, bool bMax = false>
T & PriorityQueue<T, S, bMax>::Front()
{
return arr[0];
}

template<typename T, uint32_t S, bool bMax /*= true*/>
void PriorityQueue<T, S, bMax>::MinHeapify(T arr[], const uint32_t size, const uint32_t i)
{
uint32_t left = Left(i), right = Right(i), smallest = i;
if (left < size && arr[left] < arr[i])smallest = left;
if (right < size && arr[right] < arr[smallest])smallest = right;
T tmp;
if (i != smallest)
{
EXCHANGE(arr[i], arr[smallest], tmp);
MinHeapify(arr, size, smallest);
}
}

template<typename T, uint32_t S, bool bMax /*= true*/>
void PriorityQueue<T, S, bMax>::MaxHeapify(T arr[], const uint32_t size, const uint32_t i)
{
uint32_t left = Left(i), right = Right(i), largest = i;
if (left < size && arr[left] > arr[i])largest = left;
if (right < size && arr[right] > arr[largest])largest = right;
T tmp;
if (i != largest)
{
EXCHANGE(arr[i], arr[largest], tmp);
MaxHeapify(arr, size, largest);
}
}

template<typename T, uint32_t S, bool bMax /*= true*/>
PriorityQueue<T, S, bMax>::~PriorityQueue()
{
delete[] arr;
arr = NULL;
}

template<typename T, uint32_t S, bool bMax /*= true*/>
PriorityQueue<T, S, bMax>::PriorityQueue()
{
arr = new T[S];
size = 0;
pHeapify = bMax ? &PriorityQueue::MaxHeapify : &PriorityQueue::MinHeapify;
}

#endif


测试代码

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <malloc.h>
#include <memory.h>
#include "PriorityQueue.h"

#define MAX_SIZE (100000 + 1)

// 生成不重复的随机数序列写入文件
void gen_test_data(uint32_t cnt)
{
if (cnt > MAX_SIZE){ printf("cnt too largr\n"); return; }
uint32_t i = 0, m = 0, n = 0;
int32_t *arr = (int32_t*)malloc(sizeof(int32_t)* cnt);
while (i < cnt){ arr[i] = i; ++i; }
char file_name[256];
sprintf_s(file_name, 256, "test_data_%d.txt", cnt);
FILE *fp = NULL;
fopen_s(&fp,file_name, "w");
if (NULL == fp){ printf("open %s error!\n", file_name); return; }
int32_t tmp = 0;
i = 0;
while (i < cnt)
{
m = rand() % cnt;
n = rand() % cnt;
if (m != n)EXCHANGE(arr[m], arr
, tmp);
++i;
}
i = 0;
while (i < cnt)fprintf(fp, "%d ", arr[i++]);
fclose(fp);
printf("gen %s finished\n", file_name);
}

// 读取文件
void read_data(int32_t arr[], const int32_t size, int32_t *cnt, const int32_t data_cnt)
{
FILE *fp = NULL;
*cnt = 0;
char file_name[256];
if (data_cnt > size){ printf("data_cnt too largr\n"); return; }
sprintf_s(file_name, 256, "test_data_%d.txt", data_cnt);
fopen_s(&fp,file_name, "r");
if (NULL == fp){ printf("open %s error!\n", file_name); return; }
while (!feof(fp) && *cnt < size)
{
fscanf_s(fp, "%d ", &arr[*cnt]);
(*cnt)++;
}
fclose(fp);
}

void dump2(int32_t arr[], const uint32_t start, const uint32_t end)
{
uint32_t i = start;
for (; i < end; ++i)
{
printf("%d ", arr[i]);
}
printf("\n");
}

int32_t main(int32_t argc, char *argv[])
{
int32_t cnt = 0;
const uint32_t data_cnt = 10000;
int32_t *arr = (int32_t*)malloc(sizeof(int32_t)*data_cnt);
gen_test_data(data_cnt);
read_data(arr, MAX_SIZE, &cnt, data_cnt);
PriorityQueue<int32_t, data_cnt,false> priq;
// 寻找最小(最大)的K个数
uint32_t k = 10;
for (int32_t i = 0; i < cnt; ++i)
{
priq.Push(arr[i]);
if (priq.Size() > k)
{
priq.Pop();
}
}
priq.Dump(priq.Size());
printf("\n");
getchar();
delete[] arr;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: