C++實(shí)現(xiàn)四叉樹(shù)效果(附源碼下載)
什么是四叉樹(shù)?

如圖,設(shè)想,
紅框表示地圖,星星表示單位,黃框表現(xiàn)范圍,
要處理地圖中范圍內(nèi)的單位,最直接的做法是篩選所有單位。
通過(guò)上圖可以看到一個(gè)顯而易見(jiàn)的問(wèn)題,大部分單位都不需要被處理。
如果把地圖分成塊,只篩選范圍覆蓋的塊中的單位,這樣就可以減少很多不必要的篩選。

四叉樹(shù)可以有效解決這個(gè)問(wèn)題。
樹(shù)的每一層都把地圖劃分四塊,根據(jù)地圖尺寸來(lái)決定樹(shù)的層數(shù),層數(shù)越大劃分越細(xì)。
當(dāng)需要對(duì)某一范圍的單位篩選時(shí),只需要定位到與范圍相交的樹(shù)區(qū)域,再對(duì)其區(qū)域內(nèi)的對(duì)象篩選即可。
四叉樹(shù)的實(shí)現(xiàn)
#pragma once
#include "base.h"
#include "math.h"
template <class Value>
class Tree4 {
private:
struct Pointer {
Tree4 *LT, *RT, *LB, *RB;
Pointer() :LT(nullptr), RT(nullptr), LB(nullptr), RB(nullptr)
{ }
~Pointer()
{
SAFE_DELETE(LT);
SAFE_DELETE(RT);
SAFE_DELETE(LB);
SAFE_DELETE(RB);
}
};
public:
Tree4(const MATH Rect &rect, size_t n = 0): _rect(rect)
{
STD queue<Tree4 *> queue;
queue.push(this);
for (auto c = 1; n != 0; --n, c *= 4)
{
for (auto i = 0; i != c; ++i)
{
auto tree = queue.front();
tree->Root();
queue.pop();
queue.push(tree->_pointer.LT);
queue.push(tree->_pointer.RT);
queue.push(tree->_pointer.LB);
queue.push(tree->_pointer.RB);
}
}
}
template <class Range>
bool Insert(const Value * value, const Range & range)
{
auto tree = Contain(range);
auto ret = nullptr != tree;
if (ret) { tree->_values.emplace_back(value); }
return ret;
}
template <class Range>
bool Remove(const Value * value, const Range & range)
{
auto tree = Contain(range);
auto ret = nullptr != tree;
if (ret) { ret = tree->Remove(value); }
return ret;
}
template <class Range>
bool Match(const Range & range, const STD function<bool(Value *)> & func)
{
if (!MATH intersect(_rect, range))
{
return true;
}
for (auto & value : _values)
{
if (!func(const_cast<Value *>(value)))
{
return false;
}
}
auto ret = true;
if (!IsLeaf())
{
if (ret) ret = _pointer.LT->Match(range, func);
if (ret) ret = _pointer.RT->Match(range, func);
if (ret) ret = _pointer.LB->Match(range, func);
if (ret) ret = _pointer.RB->Match(range, func);
}
return ret;
}
template <class Range>
Tree4 * Contain(const Range & range)
{
Tree4<Value> * ret = nullptr;
if (MATH contain(STD cref(_rect), range))
{
if (!IsLeaf())
{
if (nullptr == ret) ret = _pointer.LT->Contain(range);
if (nullptr == ret) ret = _pointer.RT->Contain(range);
if (nullptr == ret) ret = _pointer.LB->Contain(range);
if (nullptr == ret) ret = _pointer.RB->Contain(range);
}
if (nullptr == ret)
ret = this;
}
return ret;
}
private:
void Root()
{
_pointer.LT = new Tree4(MATH Rect(_rect.x, _rect.y, _rect.w * 0.5f, _rect.h * 0.5f));
_pointer.LB = new Tree4(MATH Rect(_rect.x, _rect.y + _rect.h * 0.5f, _rect.w * 0.5f, _rect.h * 0.5f));
_pointer.RT = new Tree4(MATH Rect(_rect.x + _rect.w * 0.5f, _rect.y, _rect.w * 0.5f, _rect.h * 0.5f));
_pointer.RB = new Tree4(MATH Rect(_rect.x + _rect.w * 0.5f, _rect.y + _rect.h * 0.5f, _rect.w * 0.5f, _rect.h * 0.5f));
}
bool Remove(const Value * value)
{
auto iter = STD find(_values.begin(), _values.end(), value);
auto ret = _values.end() != iter;
if (ret) { _values.erase(iter); }
return ret;
}
bool IsLeaf()
{
return nullptr == _pointer.LT
|| nullptr == _pointer.RT
|| nullptr == _pointer.LB
|| nullptr == _pointer.RB;
}
Tree4(const Tree4 &) = delete;
Tree4(Tree4 &&) = delete;
Tree4 &operator=(const Tree4 &) = delete;
Tree4 &operator=(Tree4 &&) = delete;
private:
MATH Rect _rect;
Pointer _pointer;
STD list<const Value *> _values;
};
代碼簡(jiǎn)潔,通俗易懂,承讓。
效果圖

左側(cè)全圖遍歷,右側(cè)四叉樹(shù)遍歷,通過(guò)左上角的開(kāi)銷時(shí)間,差異很明顯。
以上所述是小編給大家介紹的C++實(shí)現(xiàn)四叉樹(shù)效果(附源碼下載),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
C++學(xué)習(xí)進(jìn)階之Makefile基礎(chǔ)用法詳解
Makefile 通常指的是一個(gè)含有一系列命令(directive)的,通過(guò) Make自動(dòng)化編譯工具,幫助 C/C++ 程序?qū)崿F(xiàn)自動(dòng)編譯目標(biāo)文件的文件,這篇文章主要給大家介紹了關(guān)于C++學(xué)習(xí)進(jìn)階之Makefile基礎(chǔ)用法的相關(guān)資料,需要的朋友可以參考下2021-07-07
C++中inet_pton、inet_ntop函數(shù)的用法
這篇文章主要介紹了C++中inet_pton、inet_ntop函數(shù)的用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
C++超詳細(xì)講解標(biāo)準(zhǔn)庫(kù)
C++強(qiáng)大的功能來(lái)源于其豐富的類庫(kù)及庫(kù)函數(shù)資源。C++標(biāo)準(zhǔn)庫(kù)(C++ Standard Library, 亦可稱作,C++標(biāo)準(zhǔn)程序庫(kù))的內(nèi)容總共在50個(gè)標(biāo)準(zhǔn)頭文件中定義。在C++開(kāi)發(fā)中,要盡可能地利用標(biāo)準(zhǔn)庫(kù)完成2022-06-06
C/C++?函數(shù)的存儲(chǔ)位置和占用空間詳解
Lambda函數(shù)的代碼部分在代碼段中,被捕獲的變量存儲(chǔ)在Lambda函數(shù)對(duì)象的內(nèi)部,這些變量的存儲(chǔ)位置取決于Lambda函數(shù)對(duì)象的存儲(chǔ)位置,這篇文章主要介紹了C/C++函數(shù)的存儲(chǔ)位置和占用空間,需要的朋友可以參考下2023-06-06
關(guān)于C語(yǔ)言中參數(shù)的傳值問(wèn)題
C語(yǔ)言中參數(shù)的傳值一直比較含糊,今天在網(wǎng)上看到三個(gè)面試題的詳解,感覺(jué)講的很好,就拿來(lái)記下,方便學(xué)習(xí)和記憶2013-10-10

