A New Data Structure: Priority Array

· · 算法·理论

1. 前言

本文为笔者原创的乱搞文章,如有雷同,纯属偶然。转载请注明出处。

2. 引入

有时候我们要求一些数里前 k 大的数,其中 k 为一个较小的常数,不值得使用 \Theta(n \log n) 的排序算法。于是想到线性查找。

```cpp for(int i=1;i<=n;i++) { if(a[i]>Max1) { Max2=Max1; Max1=a[i]; } else if(a[i]>Max2) Max2=a[i]; } ``` $k=4$ 时: ```cpp for(int i=1;i<=n;i++) { if(a[i]>Max1) { Max4=Max3; Max3=Max2; Max2=Max1; Max1=a[i]; } else if(a[i]>Max2) { Max4=Max3; Max3=Max2; Max2=a[i]; } else if(a[i]>Max3) { Max4=Max3; Max3=a[i]; } else if(a[i]>Max4) Max4=a[i]; } ``` 可以想象当 $k=8$ 时代码会有多少冗长。 # 3. Priority Array 于是想到可以用一种暴力~~乱搞~~的数据结构去取代这些多余的代码,支持快速插入一个数,查询第 $k$ 大的数。 不难想到暴力维护一个大小为 $\Theta(k)$ 数组,每次从末端插入一个数然后暴力冒泡到前面。我称他为优先数组(Priority Array)。 这个数据结构可以 $\Theta(k)$ 插入一个数,$\Theta(1)$ 查询第 $k$ 大的数,空间复杂度 $\Theta(k)$,其中 $k$ 为一个较小的常数。时间当 $\Theta(k)<\Theta(\log n)$ 时要优于排序或者堆,空间上优于堆,支持在线查询。 # 4. 实现 ```cpp template<typename T,size_t s> struct priority_array { T a[s+2]; size_t n; priority_array(void) { n=0; memset(a,0,sizeof(a)); } size_t size(void) { return n; } bool empty(void) { return n==0; } void insert(T x) { if(n<=s)n++; a[n]=x; size_t y=n; while(y&&a[y-1]<a[y]) { swap(a[y],a[y-1]); y--; } } T top(const int&x)const& { assert(x<=s); return a[x]; } }; ``` 定义一个 int 型,大小为 $5$ 的优先数组: ```cpp priority_array<int,5>pa; ``` 也可以定义其他类型的,例如: ``` priority_array<long long,5>pa; priority_array<string,10>pa; priority_array<pair<int,int>,2>pa; struct S { int x,y,z; bool operator<(const S&i)const& { return x<i.x||x==i.x&&y<i.y; }//记得重载小于运算符 } priority_array<S,10>pa; ``` 这些都是可以的。 插入一个数 $x$:```pa.insert(x);``` 返回第 $k$ 大的数:```pa.top(k);``` 其中 $k$ 是 0-index 的。 返回优先数组的大小:`pa.size();` 返回是否为空:`pa.empty();` # 总结 优先数组这种数据结构能够快速简洁地求出一些数里面第 $k$ 大的数~~虽然没用~~。