如何在不使用希尔伯特指数的情况下对希尔伯特曲线上的点进行排序?
Posted
技术标签:
【中文标题】如何在不使用希尔伯特指数的情况下对希尔伯特曲线上的点进行排序?【英文标题】:How to sort points along a Hilbert curve without using Hilbert indices? 【发布时间】:2020-12-16 22:49:52 【问题描述】:我正在尝试实现论文 Fast Hilbert Sort Algorithm without Using Hilbert Indices (https://www.researchgate.net/profile/Takeshi_Shinohara/publication/313074453_Fast_Hilbert_Sort_Algorithm_Without_Using_Hilbert_Indices/links/5b8468bd299bf1d5a72b9a0c/Fast-Hilbert-Sort-Algorithm-Without-Using-Hilbert-Indices.pdf?origin=publication_detail) 中描述的算法,但我无法得到正确的结果。
下面是我的python代码(bitset及其成员函数在C++中翻转和测试,请参考https://en.cppreference.com/w/cpp/utility/bitset):
N=9 # 9 points
n=2 # 2 dimension
m=3 # order of Hilbert curve
b=m-1
def BitTest(x,od,maxlen=3):
bit=format(x,'b').zfill(maxlen)
return int(bit[maxlen-1-od])
def BitFlip(b,pos,):
b ^= 1 << pos
return b
def partition(A,st,en,od,ax,di):
i = st
j = en
while True:
while i < j and BitTest(A[i][ax],od)==di:
i = i + 1
while i < j and BitTest(A[j][ax],od)!=di:
j = j - 1
if i >= j:
return i
A[i], A[j] = A[j], A[i]
def HSort(A,st,en,od,c,e,d,di,cnt):
if en<=st:
return
p =partition(A,st,en,od,(d+c)%n,BitTest(e,(d+c)%n))
if c==n-1:
if b==0:
return
d2= (d+n+n-(di if(di==2) else cnt+2))%n
e=BitFlip(e,d2)
e=BitFlip(e,(d+c)%n)
HSort(A,st,p-1,b-1,0,e,d2,False,0)
e=BitFlip(e,(d+c)%n)
e=BitFlip(e,d2)
d2= (d+n+n-(di if(di==cnt+2) else 2))%n
HSort(A,p+1,en,b-1,0,e,d2,False,0)
else:
HSort(A,st,p-1,b,c+1,e,d,False,(di if(di==1) else cnt+1))
e=BitFlip(e,(d+c)%n)
e=BitFlip(e,(d+c+1)%n)
HSort(A,p+1,en,b,c+1,e,d,True,(di if(di==cnt+1) else 1))
e=BitFlip(e,(d+c+1)%n)
e=BitFlip(e,(d+c)%n)
array = [[2,2],[2,4],[3,4],[2,5],[3,5],[1,6],[3,6],[5,6],[3,7]]
HSort(array,st=0,en=N-1,od=m-1,c=0,e=0,d=0,di=False,cnt=0)
print(array)
【问题讨论】:
我在一个项目中大量使用希尔伯特曲线来定义访问给定图像上每个像素的路径,无论是在解析输入图像时还是在将输入图像从频域通过其时域表示为音频,因此熟悉生成和使用曲线...请解释sort
的意思...通常希尔伯特曲线点的序列在合成时排序...将是如果你用更多细节更新你的问题,也许还有一个样本输入和所需输出的手工示例
如果您有一个 2D 网格,该网格上的给定点表示希尔伯特曲线上的一个点,您是否要问如何在不参考规范预排序希尔伯特曲线列表的情况下识别直接相邻点? ...如果这不是一个方便的研究项目,那么这个预先排序的清单将为您提供下一点...您可能会发现这个 repo 很有帮助github.com/google/hilbert
【参考方案1】:
该文档有错字,应将常量“b”替换为“od”。 这是 C++ 中的工作代码:
#include <iostream>
#include <vector>
#include <array>
constexpr std::int32_t m = 3;
constexpr std::int32_t n = 2;
bool test_bit(std::int32_t value, std::int32_t pos)
const auto result = value & (1 << pos);
return result;
void flip_bit(std::int32_t &value, std::int32_t pos)
value ^= 1 << pos;
std::int32_t partition(std::vector<std::array<std::int32_t, 2>> &A, std::size_t st, std::size_t en, std::int32_t od, std::int32_t ax, bool di)
std::int32_t i = st - 1;
std::int32_t j = en + 1;
while(true)
do
i = i + 1;
while(i < j && test_bit(A[i][ax], od) == di);
do
j = j - 1;
while(i < j && test_bit(A[j][ax], od) != di);
if(j <= i)
return i; //partition is complete
std::swap(A[i], A[j]);
void hilbert_sort(std::vector<std::array<std::int32_t, 2>> &A, std::size_t st, std::size_t en, std::int32_t od, std::int32_t c, std::int32_t &e, std::int32_t
d, bool di, std::int32_t cnt)
std::int32_t p;
std::int32_t d2;
if(en <= st)
return;
p = partition(A, st, en, od, (d + c) % n, test_bit(e, (d + c) % n));
if(c == n - 1)
if(od == 0)
return;
d2 = (d + n + n - (di ? 2 : cnt + 2)) % n;
flip_bit(e, d2);
flip_bit(e, (d + c) % n);
hilbert_sort(A, st, p - 1, od - 1, 0, e, d2, false, 0);
flip_bit(e, (d + c) % n);
flip_bit(e, d2);
d2 = (d + n + n - (di ? cnt + 2 : 2)) % n;
hilbert_sort(A, p, en, od - 1, 0, e, d2, false, 0);
else
hilbert_sort(A, st, p - 1, od, c + 1, e, d, false, di ? 1 : cnt + 1);
flip_bit(e, (d + c) % n);
flip_bit(e, (d + c + 1) % n);
hilbert_sort(A, p, en, od, c + 1, e, d, true, di ? cnt + 1 : 1);
flip_bit(e, (d + c + 1) % n);
flip_bit(e, (d + c) % n);
int main()
std::vector<std::array<std::int32_t, 2>> points = 2,2,2,4,3,4,2,5,3,5,1,6,3,6,5,6,3,7;
std::int32_t e = 0;
hilbert_sort(points, 0, points.size() - 1, m - 1, 0, e, 0, false , 0);
for(const auto &point : points)
std::clog << "(" << point[0] << ", " << point[1] << ")\n";
return 0;
您似乎也有一个拼写错误“p+1”,它应该只是“p”。 这是一个有效的python代码:
N=9 # 9 points
n=2 # 2 dimension
m=3 # order of Hilbert curve
def BitTest(x,od):
result = x & (1 << od)
return int(bool(result))
def BitFlip(b,pos):
b ^= 1 << pos
return b
def partition(A,st,en,od,ax,di):
i = st
j = en
while True:
while i < j and BitTest(A[i][ax],od) == di:
i = i + 1
while i < j and BitTest(A[j][ax],od) != di:
j = j - 1
if j <= i:
return i
A[i], A[j] = A[j], A[i]
def HSort(A,st,en,od,c,e,d,di,cnt):
if en<=st:
return
p = partition(A,st,en,od,(d+c)%n,BitTest(e,(d+c)%n))
if c==n-1:
if od==0:
return
d2= (d+n+n-(2 if di else cnt + 2)) % n
e=BitFlip(e,d2)
e=BitFlip(e,(d+c)%n)
HSort(A,st,p-1,od-1,0,e,d2,False,0)
e=BitFlip(e,(d+c)%n)
e=BitFlip(e,d2)
d2= (d+n+n-(cnt + 2 if di else 2))%n
HSort(A,p,en,od-1,0,e,d2,False,0)
else:
HSort(A,st,p-1,od,c+1,e,d,False,(1 if di else cnt+1))
e=BitFlip(e,(d+c)%n)
e=BitFlip(e,(d+c+1)%n)
HSort(A,p,en,od,c+1,e,d,True,(cnt+1 if di else 1))
e=BitFlip(e,(d+c+1)%n)
e=BitFlip(e,(d+c)%n)
array = [[2,2],[2,4],[3,4],[2,5],[3,5],[1,6],[3,6],[5,6],[3,7]]
HSort(array,st=0,en=N-1,od=m-1,c=0,e=0,d=0,di=False,cnt=0)
print(array)
【讨论】:
以上是关于如何在不使用希尔伯特指数的情况下对希尔伯特曲线上的点进行排序?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Turtle [Python 3] 制作最有效的希尔伯特曲线?