C语言实现正方形与三角形格点最近邻计算的技术问询
三角形格点最近邻计算的C语言实现思路
你已经完成正方形格点的最近邻计算,三角形格点的6个最近邻不需要引入角度,核心思路是先把一维格点标号转换成二维坐标,再根据三角形格点的偏移布局规则找到邻点坐标,最后转回一维标号,同时处理边界(周期性或非周期性均可)。
一、明确三角形格点的布局规则
最常用的是「偏移行」布局:
- 假设格点是L×L的二维网格,行号从0到L-1,列号从0到L-1
- 偶数行(r为0、2、4...)的格点与奇数行(r为1、3、5...)的格点横向偏移半个格距,这样每个内部点会有6个最近邻
二、一维标号与二维坐标的转换
你的正方形格点标号从1开始,对应转换公式:
// 一维标号i转二维坐标(r, c) int r = (i - 1) / L; int c = (i - 1) % L; // 二维坐标(r, c)转一维标号i int i = r * L + c + 1;
三、6个最近邻的坐标规则
针对偏移行布局,分奇偶行处理:
对于坐标(r, c),6个邻居的坐标如下:
- 同一行左邻:
(r, c-1) - 同一行右邻:
(r, c+1) - 上一行邻居:
- 若r是偶数:
(r-1, c)、(r-1, c-1) - 若r是奇数:
(r-1, c)、(r-1, c+1)
- 若r是偶数:
- 下一行邻居:
- 若r是偶数:
(r+1, c)、(r+1, c-1) - 若r是奇数:
(r+1, c)、(r+1, c+1)
- 若r是偶数:
四、边界处理(以周期性边界为例)
如果是周期性边界(类似你正方形代码里的循环边界),用取模运算把超出范围的坐标拉回网格内:
- 列坐标:
c = (c + L) % L;(处理c<0或c>=L的情况) - 行坐标:
r = (r + L) % L;(处理r<0或r>=L的情况)
如果是非周期性边界,直接判断坐标是否在0~L-1范围内,超出则标记为无邻居即可。
五、C语言实现示例
先优化你原来的正方形代码(去掉全局变量,用数学计算替代循环处理边界),再实现三角形格点的邻居计算:
#include <stdio.h> #include <stdlib.h> #define L 5 // L×L格点规模 // 正方形格点最近邻计算(优化版) void square_neighbours(int i) { int r = (i - 1) / L; int c = (i - 1) % L; // 右邻居 int nr_c = (c + 1) % L; int nr = r * L + nr_c + 1; printf("右邻点: %d\n", nr); // 左邻居 int nl_c = (c - 1 + L) % L; int nl = r * L + nl_c + 1; printf("左邻点: %d\n", nl); // 上邻居 int nu_r = (r - 1 + L) % L; int nu = nu_r * L + c + 1; printf("上邻点: %d\n", nu); // 下邻居 int nd_r = (r + 1) % L; int nd = nd_r * L + c + 1; printf("下邻点: %d\n", nd); } // 三角形格点最近邻计算(周期性边界) void triangle_neighbours(int i) { int r = (i - 1) / L; int c = (i - 1) % L; int neighbours[6]; int idx = 0; // 同一行左右邻居 int c_left = (c - 1 + L) % L; neighbours[idx++] = r * L + c_left + 1; int c_right = (c + 1) % L; neighbours[idx++] = r * L + c_right + 1; // 上一行邻居 int r_up = (r - 1 + L) % L; if (r % 2 == 0) { // 偶数行上邻 neighbours[idx++] = r_up * L + c + 1; int c_up_left = (c - 1 + L) % L; neighbours[idx++] = r_up * L + c_up_left + 1; } else { // 奇数行上邻 neighbours[idx++] = r_up * L + c + 1; int c_up_right = (c + 1) % L; neighbours[idx++] = r_up * L + c_up_right + 1; } // 下一行邻居 int r_down = (r + 1) % L; if (r % 2 == 0) { // 偶数行下邻 neighbours[idx++] = r_down * L + c + 1; int c_down_left = (c - 1 + L) % L; neighbours[idx++] = r_down * L + c_down_left + 1; } else { // 奇数行下邻 neighbours[idx++] = r_down * L + c + 1; int c_down_right = (c + 1) % L; neighbours[idx++] = r_down * L + c_down_right + 1; } // 输出结果 printf("三角形格点的6个最近邻:\n"); for (int k = 0; k < idx; k++) { printf("%d ", neighbours[k]); } printf("\n"); } int main(void) { int site; printf("L×L格点,L=%d,总点数=%d\n", L, L*L); printf("请输入格点标号(1~%d): ", L*L); scanf("%d", &site); if (site < 1 || site > L*L) { printf("输入的标号超出范围!\n"); return 1; } printf("\n---正方形格点最近邻---\n"); square_neighbours(site); printf("\n---三角形格点最近邻---\n"); triangle_neighbours(site); return 0; }
关键说明
- 全程无需角度计算:所有逻辑都是基于二维坐标的整数运算,完全不需要三角函数
- 布局可灵活调整:如果你的三角形格点是奇数行偏移,只需要修改奇偶行的邻居规则即可
- 边界模式可切换:代码默认用周期性边界,若需要非周期性边界,去掉坐标取模,直接判断坐标是否在0~L-1范围内即可
内容的提问来源于stack exchange,提问作者Auyk
相关产品推荐
相关产品推荐

