zoukankan      html  css  js  c++  java
  • 四叉树

      1 #include <cmath> 
      2 #include <vector>
      3 #include <iostream>
      4 #include <algorithm>
      5 
      6 using namespace std;
      7 
      8 const int NUME_PLANETS = 10;//星球数量
      9 const int TIME_COUNT = 20;
     10 const int BORDER_LIMIT = 3200;//所有坐标绝对值都不超过3200
     11 
     12 const double G = 1e-3;//万有引力常量
     13 const double pi = acos(-1.0);//圆周率
     14 
     15 double sqr(double x) {//平方
     16     return x * x;
     17 };
     18 
     19 //二维向量
     20 class Vector {
     21 public:
     22     double x, y;
     23 
     24     Vector():x(0), y(0){}
     25     Vector(double x, double y):x(x), y(y){}
     26     ~Vector() {}
     27 
     28     void operator = (const Vector &v) {
     29         x = v.x;
     30         y = v.y;
     31     }
     32 
     33     Vector operator + (const Vector &v) {
     34         return Vector(x + v.x, y + v.y);
     35     }
     36 
     37     Vector operator - (const Vector &v) {
     38         return Vector(x - v.x, y - v.y);
     39     }
     40 
     41     Vector operator * (double f) {
     42         return Vector(x * f, y * f);
     43     }
     44 
     45     Vector operator / (double f) {
     46         //return (*this) * (1.0 / f);
     47         return Vector(x / f, y / f);
     48     }
     49 
     50     double length() {//返回长度的平方
     51         return sqr(x) + sqr(y);
     52     }
     53 
     54     void factor() {//将该向量变为单位向量
     55         double len = sqrt(length());
     56         x /= len;
     57         y /= len;
     58     }
     59 
     60     void print() {
     61         cout << "(" << x << "," << y << ")";
     62     }
     63 };
     64 
     65 //星球结构体
     66 class Planet {
     67 public:
     68     Vector pos;//位置
     69     Vector v;//速度
     70     Vector a;//加速度
     71     double m;//质量
     72 };
     73 
     74 //封装四叉树 
     75 namespace QuatTree {
     76     const int SON = 4;//儿子个数,使用常量易于拓展,比如想拓展为八叉树只需要修改此常量为8即可
     77     const int SIZE = 1e5 + 5;//预开SIZE个Node节点备用,应保证 SIZE >= NUME_PLANETS * log2(N), N表示初始边界大小
     78 
     79     //四叉树的节点
     80     struct Node {
     81         double mass;//质量
     82         Vector center;//重心
     83         bool isleaf;//是否为叶子节点
     84         Node* child[SON];
     85         /*当前节点的四个儿子节点,分布如下
     86          * 01
     87          * 23
     88          */
     89         
     90         Node():mass(0), isleaf(0), center(){
     91             for (int i = 0; i < SON; i ++)
     92                 child[i] = NULL;
     93         }
     94         ~Node() {}
     95 
     96         void init(Planet *p);//使用一个星球对四叉树节点进行初始化
     97         void update();//使用四个儿子节点的信息更新当前节点的信息
     98     };
     99 
    100     Node *null = new Node();//空指针,使用自定义null而不用NULL可以减少 if(Node == NULL) 的判断
    101     Node *root;//四叉树的根
    102 
    103     void Node::init(Planet *p) {
    104         mass = p -> m;
    105         isleaf = 1;
    106         center = p -> pos;
    107         child[0] = null;
    108         child[1] = null;
    109         child[2] = null;
    110         child[3] = null;
    111     }
    112 
    113     void Node::update() {
    114         mass = 0;
    115         isleaf = 1;
    116         center.x = center.y = 0;
    117         for (int i = 0; i < SON; i ++) {
    118             if (child[i] == null) continue;
    119             isleaf = 0;
    120             mass += child[i] -> mass; 
    121             center.x += child[i] -> mass * (child[i] -> center).x;
    122             center.y += child[i] -> mass * (child[i] -> center).y;
    123         }
    124         center.x /= mass;
    125         center.y /= mass;
    126     }
    127 
    128     Node pool[SIZE];//内存池
    129     int count;//内存池的计数器
    130 
    131     void init() {//四叉树初始化
    132         count = 0;
    133         root = null;
    134     }
    135 
    136     Node *getNewNode() {//从内存池中获得一个Node指针
    137         return &(pool[count ++]);
    138     }    
    139 
    140     void insert(Node *&o, Planet *p, 
    141         double lx = -BORDER_LIMIT, double rx = BORDER_LIMIT, 
    142         double ly = -BORDER_LIMIT, double ry = BORDER_LIMIT) {
    143         //当前处理的二位平面为 lx <= x < rx, ly <= y < ry
    144         if (o == null) {
    145             o = getNewNode();
    146             o -> init(p);
    147             return;
    148         }
    149         double midx = (lx + rx) / 2, midy = (ly + ry) / 2;
    150         if ((p -> pos).x < midx) {
    151             if ((p -> pos).y < midy) insert(o -> child[0], p, lx, midx, ly, midy);
    152             else insert(o -> child[2], p, lx, midx, midy, ry);
    153         }    
    154         else {
    155             if ((p -> pos).y < midy) insert(o -> child[1], p, lx, midx, ly, midy);
    156             else insert(o -> child[3], p, lx, midx, midy, ry);
    157         }
    158         o -> update();
    159     }
    160 
    161     Planet calc(Planet *p, Node *o, int tim = 1000) {
    162         //计算星球p,在已建好的四叉树o中,经过时间tim之后的状态
    163 
    164     }
    165 
    166     vector<Planet> getQuatTree(vector<Planet> planets, int tim = 1000) {
    167         //星球集合planets经过时间tim后的状态,tim单位为ms,默认为1000ms
    168         init();//初始化
    169         int n = planets.size();//获得星球数量
    170 
    171         for (int i = 0; i < n; i ++) {
    172             insert(root, &planets[i]);
    173         }
    174 
    175         vector<Planet> result(n);
    176         for (int i = 0; i < n; i ++) {
    177             result[i] = calc(&planets[i], root, tim);
    178         }
    179 
    180         return result;
    181     }
    182 } 
    183 
    184 int main() {
    185     vector<Planet> planets(NUME_PLANETS);
    186     int num = NUME_PLANETS;
    187 
    188     /*生成所有星球初始值
    189      */ 
    190 
    191     /*每隔一定时间进行一次计算即可,使用方法如下
    192      * for (int i = 0; i < times; i ++) {//计算times次
    193      *     planets = QuatTree::getQuatTree(planets);
    194      *        print(planets);//输出所有星球信息
    195      * }
    196      */
    197     return 0;
    198 }
  • 相关阅读:
    web.xml中<security-constraint>安全认证标签说明
    TPS与QPS
    Idea无法加载主类
    动态历史
    领导之路
    aven依赖分析,jar包冲突解决利器intellij idea插件Maven Helper强烈建议安装
    Maven 电脑每次重启 mvn -v 都显示 不是命令
    IntelliJ IDEA 最新版 2019.1 安装与激活
    @Param注解的使用
    Mybatis通用Mapper介绍与使用
  • 原文地址:https://www.cnblogs.com/ytytzzz/p/11061866.html
Copyright © 2011-2022 走看看