莫顿曲线映射 二维到一维的变换 MD(莫顿)码 正向变换 线性四叉树

news2024/9/28 17:27:31

线性四叉树

(Linear Quadtree)是一种基于莫顿码(Morton Code)的数据结构,用于存储和处理二维空间中的信息。

莫顿码是一种将二维坐标映射为一维编码的方法,它将一个二维点的坐标表示为一个整数,使得相邻的二维点在一维空间中的编码也相邻。莫顿码通常用于空间索引和空间分区等应用中。

线性四叉树是基于莫顿码的一种四叉树实现方式,它将二维空间划分为一系列正方形区域,并将每个区域标记为叶子节点。每个叶子节点对应着一个莫顿码,通过莫顿码的前缀匹配可以快速定位到对应的叶子节点。线性四叉树的节点可以压缩为一个连续的数组,因此可以实现高效的存储和访问。

线性四叉树常用于地理信息系统(GIS)和计算机图形学等领域中,用于表示地图、图像和空间数据等信息。它具有高效的空间索引和查询能力,可以快速地进行空间范围查询、最近邻查询和空间聚类等操作。

线性四叉树则只存贮最后叶结点的信息,包括叶结点的位置编码/地址码、属性或灰度值

 线性四叉树 二维到一维 的变换的具体算法:

 

函数和结构体的定义 :

#include <stdio.h>
#include <math.h>

#define N 8
#define MAXSIZE 100

typedef struct          //栈的存储结构
{
    int data[MAXSIZE];
    int MD[MAXSIZE];
    int top;
}stack1;

void stackinitiate(stack1 *s);    //初始化栈
int getlines(int md);			//由MD码二进制计算行
int getrow(int md);		    	//由MD码二进制计算列
int getbinary(int md);          //获得MD码的二进制
void push (stack1 *q,int e,int n);     //入栈
void pri(stack1 q);                   //打印栈
void pop(stack1 *q,int i);          //出栈

函数的具体实现:

int getline(int md)                  //由二进制MD码,获得对应行
{
	int res=0;
	int i=0;
	while(md){
		md/=10;
		res+=md%10*pow(2,i++);
		md/=10;
	}
	return res;
}

int getrow(int md)                   //由二进制MD码,获得对应列
{
	int res=0;
	int i=0;
	while(md){
		res+=md%10*pow(2,i++);
		md/=100;
	}
	return res;
}

int getbinary(int md)            //由十进制MD码,获得二进制MD码
{
	double res=0;
	int i=0;
	while(md){
		int temp=md%2;
		res+=temp*pow(10,i++);
		md=md/2;
	}
	return res;
}


void push (stack1 *s,int e,int n)   //入栈
{
	
	s->data[s->top]=n;
	s->MD[s->top]=e;
	s->top++;
}

void pri(stack1 q)                     //从栈底打印整个栈
{
	for(int i=0;i!=q.top;i++){
		printf("%d,%d\n",q.MD[i],q.data[i]);
	}
}

void stackinitiate(stack1 *s)            //初始化栈
{
	s->top=0;
}

void pop(stack1 *q,int i){                 //出栈i个元素
	q->top-=i;
}

将二维的网格导填入到二维数组中,并初始化栈

int s[N][N]={                     //将PPT内的数据填入二维数组中
		{0,0,1,1,4,4,4,4},
		{0,0,1,1,4,4,4,4},
		{0,0,2,2,4,4,4,4},
		{0,0,2,2,4,4,4,4},
		{2,2,2,2,4,4,4,4},
		{0,0,0,0,4,4,4,4},
		{0,0,0,0,4,4,4,4},
		{0,0,0,0,4,4,4,4},
	};

	stack1 a;                              //创建栈  
	stackinitiate(&a);                     //初始化

按算法结果应该为这样:

核心算法:

int md=0;
	while(md<N*N){
		int i,j;                        //定义 i j 分别为 行 列
		int MD=getbinary(md);		    //获取MD码二进制
		i=getline(MD);			         //获取行
		j=getrow(MD);			         //获取列
	if(s[i][j]==s[i+1][j]&&s[i][j]==s[i][j+1]&&s[i][j]==s[i+1][j+1])   		//判断四个连续的单元是否相等  
	  {
		push(&a,md,s[i][j]);                   //相等,入栈
	  }
	else{
		for(int i=0;i<4;i++){                 //不相等,则按MD码大小入栈
			int MD=getbinary(md+i);
			int x=getline(MD);			   
		    int y=getrow(MD);
			push(&a,md+i,s[x][y]);
		}
	  } 	
		if(a.top>3){                              //判断栈顶四个元素是否相等
			int h=a.top-1;
			if(a.data[h]==a.data[h-1]&&a.data[h]==a.data[h-2]&&a.data[h]==a.data[h-3]){		
			   pop(&a,3);          //最上面三个元素出栈
		    }
		}
		md+=4;
	}
	pri(a);                //打印
	return 0;
}

 打印结果:

结果一致,证明没有问题

 关于中间的函数实现,我采用了比较愚蠢的方法,下面我搜集了各类资料,展示使用位运算的实现

十进制MD码 转化为 二进制MD码

uint32_t decimal_to_binary(uint32_t md) {
    uint32_t binary = 0;
    uint32_t bit = 1;
    while (md > 0) {
        if (md & 1) {
            binary += bit;
        }
        bit <<= 1;  // 左移一位,相当于乘以2
        md >>= 1;   // 右移一位,相当于除以2
    }
    return binary;
}
  • 首先判断 md 的最后一位是否为1,如果是,就在二进制数的对应位上加上当前位的权值 bit
  • 然后将 bit 左移一位,相当于将当前位的权值乘以2。
  • 接着将 md 右移一位,相当于将当前位去掉,准备处理下一位。

二进制MD码转 行列号(这里的行为偶数,奇数为列)

#include <stdio.h>

void getRowColumn(int md, int level) {
    int row = 0;
    int col = 0;

    for (int i = 1; i <= level/2 +1; i++) {
        row |= (md & (1 << (2 * i -1))) >> i;
        col |= (md & (1 << (2 * i -2))) >> i-1;
    }

    printf("Row: %d, Column: %d\n", row, col);
}

int main() {
    int md = 0b100;  // 二进制的MD码
    int level = 3;   // 二进制码的长度

    getRowColumn(md, level);
	
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/637076.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux常用命令——gpasswd命令

在线Linux命令查询工具 gpasswd Linux下工作组文件的管理工具 补充说明 gpasswd命令是Linux下工作组文件/etc/group和/etc/gshadow管理工具。 语法 gpasswd(选项)(参数)选项 -a&#xff1a;添加用户到组&#xff1b; -d&#xff1a;从组删除用户&#xff1b; -A&#xf…

STC8/15单片机复位功能介绍

STC8/15单片机复位功能介绍 📑复位简介 🌼STC15系列 STC15系列单片机有7种复位方式:外部RST 引脚复位,软件复位,掉电复位/上电复位(并可选择增加额外的复位延时180mS,也叫MAX810专用复位电路,其实就是在上电复位后增加一个180mS复位延时),内部 低压检测复位,MAX810专…

晶体热学性能研究的方法:第一性原理声子谱计算

晶体热学性能研究的方法&#xff1a;第一性原理声子谱计算 第一性原理声子谱计算是一种基于量子力学的计算方法&#xff0c;用于研究物质中声子的性质和行为。声子是晶体中的量子态&#xff0c;它描述了晶体中原子振动的性质。声子谱计算可以提供关于晶体结构、热力学性质、相变…

分享一些宝藏软件给你

如果你正在寻找一些好玩又有用的软件&#xff0c;那么这篇文章就是为你准备的。下面&#xff0c;我将为大家介绍几款免费的宝藏软件&#xff0c;满足你对于各种软件的需求。 分享一&#xff1a;虚假截图助手 虚假截图助手是一个可以为多个平台伪造屏幕截图的网站。注意&#…

FQL40N50-ASEMI代理安森美原装MOS管FQL40N50

编辑&#xff1a;ll FQL40N50-ASEMI代理安森美原装MOS管FQL40N50 型号&#xff1a;FQL40N50 品牌&#xff1a;ON/安森美 封装&#xff1a;TO-264 最大漏源电流&#xff1a;40A 漏源击穿电压&#xff1a;500V RDS&#xff08;ON&#xff09;Max&#xff1a;110mΩ 引脚数…

webpack自动引入打包资源HtmlWebpackPlugin

在之前的章节中我们每次打包完之后都是手动的在public/index.html中通过<script>的方式手动引入的dist/js/main.js文件。用过框架开发的小伙伴应该都有体会过&#xff0c;比如vue-cli,每次打包完我们直接将dist目录下的文件整个拷贝直接部署到服务器下就行了&#xff0c;…

(一)初识 Kafka

文章目录 1.发布与订阅消息系统&#xff08;1&#xff09;什么是发布与订阅消息系统&#xff08;2&#xff09;为什么 Kafka 是数据驱动型应用程序的关键组件 2. Kafka 介绍&#xff08;1&#xff09;消息和批次&#xff08;2&#xff09;消息模式&#xff08;3&#xff09;主题…

如何防范银行网点潜在风险?这4点一定要记牢

银行作为金融机构&#xff0c;具有重要的资金和客户信息&#xff0c;其安全性和监控是至关重要的。银行网点监控能够有效保护银行资产&#xff0c;确保员工和客户的安全&#xff0c;预防潜在的犯罪行为。 客户案例 上海市某银行在全国多地拥有大量分支机构和网点。他们面临着需…

使用Red Hat Insights注册RedHat系统

文章目录 前因Step 1: 确认所选择的系统Step 2: 将系统注册到Red Hat InsightsStep 3:具体操作演示 前因 使用SSH命令远程连接红帽系统&#xff0c;提示需要使用下面提示的命令进行系统注册订阅。 C:\Users\xyb>ssh -i xybdiy-aws-key.pem ec2-user18.179.118.78 The authen…

vue中重写并自定义console.log

0. 背景 在vue2项目中自定义console.log并输出文件名及行、列号 1. 实现 1.1 自定义console.log export default {// 输出等级: 0-no, 1-error, 2-warning, 3-info, 4-debug, 5-loglevel: 5,// 输出模式: 0-default, 1-normal, 2-randommode: 1,// 是否输出图标hasIcon: fal…

数组判断某个属性是否都相同

一、 // 判断属性是否存在isPropertyAllSame(array, property) {if (array.length 0) {return true; // 空数组默认属性全部相同}const firstPropertyValue array[0][property]; // 取第一个元素的属性值for (let i 1; i < array.length; i) {if (array[i][property] ! f…

5.2.10 IP分组的转发(一)

5.2.10 IP分组的转发&#xff08;一&#xff09; 我们已经知道对于IP协议来说提供的是无连接、不可靠、尽力而为的IP分组交付服务&#xff0c;这里我们就学习一下一个IP分组是如何从源主机交付给目的主机的。如果在因特网上有两台主机发送数据的时候&#xff0c;分组究竟是如何…

轻松下载google drive大文件 IDM微操教程

背景 在google drive使用chrome浏览器自带的下载工具&#xff0c;下载时总是报错&#xff1a; 于是在网上搜索"下载google drive 大文件"&#xff0c;看到有人提到了IDM和gdown。最终用IDM解决了需求。从下图可见&#xff0c;文件有99GB&#xff0c;每秒下载速度10…

媒体分类详解,企业做活动可以邀请哪些媒体?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体分类可以根据不同的维度进行划分。以下是一些常见的媒体分类方式&#xff1a; 1. 传统媒体&#xff1a; - 报纸&#xff1a;报纸是最传统的媒体形式之一&#xff0c;以印刷纸质媒体为…

华为OD机试真题 JavaScript 实现【DNA序列】【牛客练习题】

一、题目描述 一个 DNA 序列由 A/C/G/T 四个字母的排列组合组成。 G 和 C 的比例&#xff08;定义为 GC-Ratio &#xff09;是序列中 G 和 C 两个字母的总的出现次数除以总的字母数目&#xff08;也就是序列长度&#xff09;。在基因工程中&#xff0c;这个比例非常重要。因为…

SpringBoot:SpringBoot启动加载过程 ④

一、思想 我们看到技术上高效简单的使用&#xff0c;其实背后除了奇思妙想的开创性设计&#xff0c;另一点是别人帮你做了复杂繁琐的事情。 二、从官网Demo入手 官网就一行代码。这个就是它的启动代码。 1、SpringBootApplication注解 ①. 三个核心注解的整合。 SpringBootCon…

什么是微带线和带状线

在电路板设计中&#xff0c;微带线和带状线分别是用于传输信号的两种常见的传输线路。虽然在许多方面它们很相似&#xff0c;但是它们的物理结构、传输速率、特性阻抗等方面存在很大的差异。 本文将介绍微带线和带状线的基本概念、特性和应用场景&#xff0c;并比较它们的优缺…

Snap版本的CUPS将在Ubuntu 23.10 中默认使用

导读CUPS 是一个用于 Linux 系统的开源模块化打印系统&#xff0c;最初由 Michael Sweet 开发。在 2007 年&#xff0c;苹果公司收购了 CUPS&#xff0c;并聘请了 Michael Sweet 继续开发。 CUPS 是一个用于 Linux 系统的开源模块化打印系统&#xff0c;最初由 Michael Sweet …

搭建一个免费代理IP池,妈妈再也不用担心我没有IP用了

背景 爬虫工作才刚刚开始&#xff0c;突然IP被限制了&#xff0c;怎么办&#xff1f;他们告诉我&#xff0c;可以去买代理IP呀。 可是我翻了5遍裤兜&#xff0c;查了8张银行卡&#xff0c;却只有1块钱 &#xff0c;根本买不起啊。 突然&#xff0c;隔壁部门的同事的姐姐的妈妈…

k8s pod state terminating学习笔记

文章目录 背景解决方式个人思考 背景 今天服务器重启失败&#xff0c;于是去检查k8s状态&#xff0c;发现pod一直处于terminating状态。 多次尝试删除pod但是失败了&#xff0c;于是想到可能是k8s node卡住了导致接收不到kill命令。 解决方式 所以reboot k8s node&#xff0…