zoukankan      html  css  js  c++  java
  • 求矩阵四叉树的四进制和十进制Morton码

        Yogurt是一名学GIS的学生,今天要跟大家分享的是四叉树这种空间索引方式的Morton编码方法,接下来我将在小课堂中简单介绍一下空间索引以及其几种编码方式~~

    ---------------------------------------------------------yogurt小课堂开课啦--------------------------------------------------------

        GIS所涉及到的都是有关空间的数据信息,即也属于所谓的大数据了,那么怎么将客观的物体对象存储到计算机中,以及怎么从计算机中读取所需要的数据呢?

        首先我们要知道计算机的存储器有内存和外存,内存空间小但是读写快,外存空间大却读写慢,访问外存所花费的时间是访问内存的十万倍以上!在GIS的实际应用中大量的数据都是存储在外存上的,想象一下如果这些数据全都杂乱无章的堆放在那里,那么每需要查询一个数据就需要扫描整个数据文件,这样访问磁盘的代价是非常大的,严重影响了系统效率!所以,我们必须记录好每个数据存放的位置,以便于组织和管理,在这个过程中就需要用到索引技术啦!

        【(这里引自我老师的课件哈,低调低调!!!)

        从传统的索引技术观点来看,可以把空间索引技术大致分为四大类:基于R树,基于Hashing,基于二叉树,基于空间填充。

        在建立索引时,按照划分区域是否与空间对象的分布特征有关的标准,空间索引又可以分为两大类:无关的(网格索引、四叉树),有关的(BSP树、KD树、KDB树、R树及其变种树)。

        我们来看看几种索引方法的实际应用:

        (1)ESRI的ArcSDE采用的是固定格网索引;

        (2)目前国内外主要的空间数据库如ESRI的ArcView,Mapinfo公司的Maoinfo和Informix的GeoSpatial DataBlade采用的是R树系列作为空间索引的方式;

        (3)Oracle公司的Spatial同时采用固定格网索引以及R树索引;

        (4)中国地质大学的MapGIS和中科院的SuperMap采用的是四叉树。

         以上来自我的一个大牛老师的PPT~~】

        好啦,既然今天要讲矩阵四叉树的Morton编码,那么接下来就介绍一下四叉树以及Morton码的编码规则吧:

       【四叉树】:

        区域型物体的四叉树表示方法最早出现在加拿大地理信息系统CGIS中,20世纪80年代以来,四叉树在图象分割、数据压缩、 地理信息系统等方面进行了大量的研究,对四叉树数据结构提出了许多编码方案。四叉树分为常规四叉树与线性四叉树,下图简单的说明了两者的区别:(不要嫌弃我字丑!!!)

        编码规定:

           

       【线性四叉树的编码方式】: 例如有这样一个矩阵线性四叉树,以红色圈中的9的编码为例,有自上而下的方法和自下而上的方法:

           

       (1)基于深度和层次码线性四叉树编码:(自上而下的方法)

       层次码:第一层(在位置2,用两位二进制表示为:10),第二层(在位置1,用两位二进制表示为:01),第三层(在位置2,用两位二进制表示为:10);

       深度码:有3层深,(用四位二进制表示为:0011);

       “9”的位置编码为:10 01 10 0011,该位置码的十进制为2^0+2^1+2^5+2^6+2^9=611.

       (2)基于四进制的线性四叉树编码:

       (自上而下的方法):第一层2,第二层1,第三层2,位置码:212

       (自下而上的方法,说明四进制编码的过程):二进制的行列号Iyb、Ixb(从第0行0列开始),四进制编码M=2*Iyb+ Ixb;那么这里就是:第5行(101)第2列(010):M=2*101+10=212

       (3)基于十进制的线性四叉树编码:

       (自下而上的方法,说明四进制编码的过程):二进制的行列号Iyb、Ixb(从第0行0列开始),十进制编码M=奇数位用列号填充,偶数位用行号填充;那么这里就是:第5行(101)第2列(010):M=10 01 10

       (4)在相邻四个码中若属性值相同,进行合并,除去最低位得到合并后的新编码。

    -----------------------------------------------------------下课啦!!!--------------------------------------------------------------

    编写该程序的思路:

    第一步:读入矩阵四叉树,并将其输出;

    第二步:利用four_decimal函数得到每一个位置的四进制M码,利用Change函数得到规定格式的三位四进制M码;最后利用checkcombine_four函数,将属性值一样的位置的M码合并,并输出;

    第三步:同第二步类似,利用ten_decimal函数得到每一个位置的十进制M码,利用checkcombine_ten函数,将属性值一样的位置的M码合并,并输出。

    具体实现过程:

    (1)将十进制行列号转换为二进制:利用函数Tobinary :

    (2)得到四进制M码:利用函数four_decimal:

    (3)得到十进制M码:利用函数ten_decimal:(注意按位交错)

    (4)对属性值一样的M码进行合并的处理操作checkcombine_ten:(以十进制为例)

    在第二层里:(方法与第一层类似,只是合并条件变成了w==2)

    最后输出数组即可,对于四进制的M码,由于合并时还要除去最低位的,所以需要特殊处理(便于输出):如在合并第一层时,给第二三位赋予标志值99999999:

     

    合并第二层时,给第三位赋予标志值99999999:

     

    输出时:

    好啦,接下来是整体代码:

    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    
    typedef int newc[3];
    typedef int ceng[2];
    
    void read(int a[][8]);                             //读入矩形四叉树
    int Tobinary(int k);                               //将十进制的行列号k转换为二进制.
    int eq(int m, int n);                              //判断m和n是否相等,相等则返回1,否则返回0.
    void judge_four(int a[][8], newc b[][8], ceng c[4]);//判断数组c表示的矩形范围内的值是否一样,若一样就更新数组b.
    void judge_ten(int a[][8], int b[][8], ceng c[4]); 
    void checkcombine_four(int a[][8], newc b[][8]);   //将属性值一样的单元进行合并.
    void checkcombine_ten(int a[][8], int b[][8]);     
    void Change(int m[][8], newc n[][8]);              //将四进制的M码按照规定格式输出.
    void four_decimal(int b[][8]);                     //四进制编码.
    void ten_decimal(int c[][8]);                      //十进制编码.
    void output_i(int a[][8]);                         //输出int型数组.
    void output_c(newc a[][8]);                        //输出newc型数组.
    
    void main()
    {
        int a[8][8], b[8][8], c[8][8];
        newc bb[8][8];
        read(a);
        printf("矩阵四叉树为:
    ");
        output_i(a);
    
        four_decimal(b);
        Change(b, bb);
        checkcombine_four(a,bb);
        printf("
    四叉树对应的四进制编码为:
    ");
        output_c(bb);
    
        ten_decimal(c);
        checkcombine_ten(a,c);
        printf("
    四叉树对应的十进制编码为:
    ");
        output_i(c);
    }
    
    void read(int a[][8])
    {
        FILE *fp = fopen("四叉树.txt","r");
        if (!fp)
            exit;
        else
        for (int i = 0; i < 8;i++)
        for (int j = 0; j < 8; j++)
            fscanf(fp, "%d", &a[i][j]);
        fclose(fp);
    }
    
    int Tobinary(int k)
    {
        int s[10],rem,i=0,t=0;
        do
        {
            rem = k % 2;
            k = k / 2;
            s[i++] = rem;
        } while (k != 0);   //当十进制数是0时也要进行一遍此循环,所以必须用do……while循环,而不是while循环
        for (int j = --i; j >= 0; j--)
        {
            t += s[j] * pow(10.0, j);
        }
        return t;
    }
    
    int eq(int m, int n)
    {
        if (m == n)
            return 1;
        else
            return 0;
    }
    
    void judge_four(int a[][8], newc b[][8], ceng c[4])
    {
        for (int i = 0; i < 4; i++)
        {
            int w = 0;
            for (int m = c[i][0]; m <c[i][0] + 2; m++)
            for (int n = c[i][1]; n <c[i][1] + 1; n++)
                w += eq(a[m][n], a[m][n + 1]);
            if (w == 2)//4个值属性一样
            {
                for (int m = c[i][0]; m <c[i][0] + 2; m++)
                for (int n = c[i][1]; n < c[i][1] + 2; n++)
                {
                    *b[m][n] = *b[(c[i][0])][(c[i][1])];
                    *(b[m][n] + 1) = *(b[(c[i][0])][(c[i][1])] + 1);
                    *(b[m][n] + 2) = 99999999;
                }
            }
        }
    }
    
    void judge_ten(int a[][8], int b[][8], ceng c[4])
    {
        for (int i = 0; i < 4; i++)
        {
            int w = 0;
            for (int m = c[i][0]; m <c[i][0]+2; m++)
            for (int n = c[i][1]; n <c[i][1]+1; n++)
                w += eq(a[m][n], a[m][n + 1]);
            if (w == 2)//4个值属性一样
            {
                for (int m = c[i][0]; m <c[i][0] + 2; m++)
                for (int n = c[i][1]; n < c[i][1] + 2; n++)
                {
                    b[m][n] = b[(c[i][0])][(c[i][1])];
                }
            }
        }
    }
    
    void checkcombine_ten(int a[][8], int b[][8])
    {
        //第一层
        ceng c[4] = { { 0, 0 }, { 0, 4 }, { 4, 0 }, { 4, 4 } };
        for (int i = 0; i < 4; i++)
        {
            int w = 0;
            for (int m = c[i][0]; m < 4; m++)
            for (int n = c[i][1]; n < 3; n++)
                w += eq(a[m][n], a[m][n + 1]);
            if (w == 12)//16个值属性一样
            {
                for (int m = c[i][0]; m < c[i][0] + 4; m++)
                for (int n = c[i][1]; n < c[i][1] + 4; n++)
                {
                    b[m][n] = b[(c[i][0])][(c[i][1])];
                }
            }
        }
        //第二层
        ceng d[4] = { { 0, 0 }, { 0, 2 }, { 2, 0 }, { 2, 2 } },
            e[4] = { { 0, 4 }, { 0, 6 }, { 2, 4 }, { 2, 6 } },
            f[4] = { { 4, 0 }, { 4, 2 }, { 6, 0 }, { 6, 2 } },
            g[4] = { { 4, 4 }, { 4, 6 }, { 6, 4 }, { 6, 6 } };
        judge_ten(a, b, d);
        judge_ten(a, b, e);
        judge_ten(a, b, f);
        judge_ten(a, b, g);
    }
    
    void checkcombine_four(int a[][8], newc b[][8])
    {
        //第一层
        ceng c[4] = { { 0, 0 }, { 0, 4 }, { 4, 0 }, { 4, 4 } };
        for (int i = 0; i < 4; i++)
        {
            int w = 0;
            for (int m = c[i][0]; m < 4; m++)
            for (int n = c[i][1]; n < 3; n++)
                w += eq(a[m][n], a[m][n + 1]);
            if (w == 12)//16个值属性一样
            {
                for (int m = c[i][0]; m < c[i][0] + 4; m++)
                for (int n = c[i][1]; n < c[i][1] + 4; n++)
                {
                    *b[m][n] =*b[(c[i][0])][(c[i][1])];
                    *(b[m][n] + 1) =99999999;
                    *(b[m][n] + 2) =99999999;
                }
            }
        }
        //第二层
        ceng d[4] = { { 0, 0 }, { 0, 2 }, { 2, 0 }, { 2, 2 } },
            e[4] = { { 0, 4 }, { 0, 6 }, { 2, 4 }, { 2, 6 } },
            f[4] = { { 4, 0 }, { 4, 2 }, { 6, 0 }, { 6, 2 } },
            g[4] = { { 4, 4 }, { 4, 6 }, { 6, 4 }, { 6, 6 } };
        judge_four(a, b, d);
        judge_four(a, b, e);
        judge_four(a, b, f);
        judge_four(a, b, g);
    }
    
    void Change(int m[][8], newc n[][8])
    {
        int t[3];
        int q;
        for (int i = 0; i < 8;i++)
        for (int j = 0; j < 8; j++)
        {
            q = m[i][j];
            t[0] = q / 100;
            q = q % 100;    
            t[1] = q / 10;
            q = q % 10;
            t[2] = q;
            *n[i][j] = *t;             //数组赋值,数组名称不能直接做左值
            *(n[i][j] + 1) = *(t + 1);
            *(n[i][j] + 2) = *(t + 2);
        }
    }
    
    void four_decimal(int b[][8])
    {
        for (int i = 0; i < 8;i++)
        for (int j = 0; j < 8;j++)
        {
            int m=Tobinary(i);
            int n=Tobinary(j);
            b[i][j] = 2 * m + n;
        }
    }
    
    void ten_decimal(int c[][8])
    {
        for (int i = 0; i < 8; i++)
        for (int j = 0; j < 8; j++)
        {
            int m = Tobinary(i);
            int n = Tobinary(j);
            int t[8];
            t[0] = m / 1000;
            m = m % 1000;
            t[2] = m / 100;
            m = m % 100;
            t[4] = m / 10;
            m = m % 10;
            t[6] = m;
    
            t[1] = n / 1000;
            n = n % 1000;
            t[3] = n / 100;
            n = n % 100;
            t[5] = n / 10;
            n = n % 10;
            t[7] = n;
    
            int y = 0;
            for (int w = 0; w < 8; w++)
            {
                y+= t[w] * pow(2.0,7-w);
            }    
            c[i][j] = y;
        }
    }
    
    void output_i(int a[][8])
    {
        for (int i = 0; i < 8; i++)
        {
            for (int j = 0; j < 8; j++)
            {
                printf("%6d", a[i][j]);
            }
            printf("
    ");
        }
    }
    
    void output_c(newc a[][8])
    {
        for (int i = 0; i < 8; i++)
        {
            for (int j = 0; j < 8; j++)
            if (*(a[i][j] + 1)==99999999&&*(a[i][j] + 2)==99999999)
                printf("%6d", *a[i][j]);
            else if (*(a[i][j] + 2) == 99999999)
                printf("%5d%d", *a[i][j], *(a[i][j] + 1));
            else
                printf("%4d%d%d", *a[i][j], *(a[i][j] + 1), *(a[i][j] + 2));
            printf("
    ");
        }
    }
    View Code

    最后结果:

  • 相关阅读:
    浅析Java源码之LinkedList
    浅析Java源码之ArrayList
    Vue源码终笔-VNode更新与diff算法初探
    Vue源码后记-更多options参数(2)
    Vue源码后记-更多options参数(1)
    Vue源码后记-其余内置指令(3)
    Vue源码后记-其余内置指令(2)
    Vue源码后记-其余内置指令(1)
    Vue源码后记-vFor列表渲染(3)
    Linux/CentOS 7 timezone 修改
  • 原文地址:https://www.cnblogs.com/to-sunshine/p/6430485.html
Copyright © 2011-2022 走看看