IGraph使用实例——图属性设置1

 1 概述

在图论中,图由顶点(vertices)和边(edges)组成,可以是无向的或有向的。图的属性是用来提供关于图、顶点或边的额外信息的数据。以下是从图论角度对图的属性的描述:

图的属性(Graph Attributes)

图的属性是与整个图相关的信息,而不是与图中的个别顶点或边相关。这些属性可以用来描述图的整体特征,例如:

  • 图的标识符(ID):一个唯一的标识符,用于区分不同的图。
  • 图的名称(Name):图的一个描述性名称,例如“社交网络图”或“交通网络图”。
  • 图是否规则(Regularity):布尔值,表示图中的所有顶点是否具有相同数量的边。
  • 其他可能的属性包括图的类型(例如,是否是有向图或无向图)、图的权重信息等。

顶点的属性(Vertex Attributes)

顶点属性是与图中的每个顶点相关的信息。这些属性可以用来描述顶点的特征,例如:

  • 顶点的值(Value):与顶点相关的数值,可能表示顶点的重要性、权重或其他数值度量。
  • 顶点的颜色(Color):在某些应用中,顶点可能被赋予颜色,用于可视化或其他目的。
  • 顶点的标签(Label):一个字符串或数字,用于标识或分类顶点。
  • 其他可能的属性包括顶点的度数(与顶点相连的边的数量)、顶点的类型(例如,在社交网络中,顶点可能代表不同类型的用户)等。

边的属性(Edge Attributes)

边属性是与图中的每条边相关的信息。这些属性可以用来描述边的特征,例如:

  • 边的权重(Weight):表示边的强度或成本,常用于表示距离、成本或流量。
  • 边的颜色(Color):与边相关的颜色,可能用于可视化或表示边的类型。
  • 边的标签(Label):用于标识或分类边的字符串或数字。
  • 边的方向(Direction):对于有向图,边的方向表示从一个顶点指向另一个顶点的关系。
  • 其他可能的属性包括边的类型(例如,在交通网络中,边可能代表不同类型的道路)等。

在实际应用中,图的属性可以根据具体的领域和需求进行定制。属性的引入使得图能够更丰富地表达信息,便于进行更复杂的分析和处理。

2 运行环境

操作系统:win10 64位

编程语言:C/C++

编译平台:vs2019  x64 debug | release

igraph版本: 0.10.12

3 示例代码

这段代码的主要作用是演示如何使用igraph库来创建一个图(graph),设置图的属性(包括图的属性、顶点的属性和边的属性),然后打印出这些属性。

下面print_attributes方法实现了图数据打印功能。函数首先初始化一些向量和字符串向量来存储属性名称和类型,然后通过igraph_cattribute_list函数获取图的属性列表。之后,它遍历图的属性、顶点和边,打印出它们的属性名称和值。

// 定义函数print_attributes,接受一个指向igraph_t结构的指针作为参数
void print_attributes(const igraph_t *g) {
    // 声明变量用于存储图、顶点和边的属性类型和名称
    igraph_vector_int_t gtypes, vtypes, etypes;
    igraph_strvector_t gnames, vnames, enames;
    igraph_integer_t i, j;

    // 初始化图、顶点和边的属性类型向量
    igraph_vector_int_init(&gtypes, 0);
    igraph_vector_int_init(&vtypes, 0);
    igraph_vector_int_init(&etypes, 0);
    // 初始化图、顶点和边的属性名称字符串向量
    igraph_strvector_init(&gnames, 0);
    igraph_strvector_init(&vnames, 0);
    igraph_strvector_init(&enames, 0);

    // 获取图的属性列表
    igraph_cattribute_list(g,
                           &gnames, &gtypes,
                           &vnames, &vtypes,
                           &enames, &etypes);

    // 打印图属性
    for (i = 0; i < igraph_strvector_size(&gnames); i++) {
        printf("%s=", igraph_strvector_get(&gnames, i)); // 打印属性名称
        // 根据属性类型打印数值或字符串
        if (VECTOR(gtypes)[i] == IGRAPH_ATTRIBUTE_NUMERIC) {
            igraph_real_printf(GAN(g, igraph_strvector_get(&gnames, i))); // 打印数值属性
            putchar(' ');
        } else {
            printf("\"%s\" ", GAS(g, igraph_strvector_get(&gnames, i))); // 打印字符串属性
        }
    }
    printf("\n"); // 换行

    // 打印顶点属性
    for (i = 0; i < igraph_vcount(g); i++) {
        printf("Vertex %" IGRAPH_PRId ": ", i); // 打印顶点编号
        for (j = 0; j < igraph_strvector_size(&vnames); j++) {
            printf("%s=", igraph_strvector_get(&vnames, j)); // 打印属性名称
            // 根据属性类型打印数值或字符串
            if (VECTOR(vtypes)[j] == IGRAPH_ATTRIBUTE_NUMERIC) {
                igraph_real_printf(VAN(g, igraph_strvector_get(&vnames, j), i)); // 打印数值属性
                putchar(' ');
            } else {
                printf("\"%s\" ", VAS(g, igraph_strvector_get(&vnames, j), i)); // 打印字符串属性
            }
        }
        printf("\n"); // 换行
    }

    // 打印边属性
    for (i = 0; i < igraph_ecount(g); i++) {
        printf("Edge %" IGRAPH_PRId " (%" IGRAPH_PRId "-%" IGRAPH_PRId "): ", i, IGRAPH_FROM(g, i), IGRAPH_TO(g, i)); // 打印边编号和端点
        for (j = 0; j < igraph_strvector_size(&enames); j++) {
            printf("%s=", igraph_strvector_get(&enames, j)); // 打印属性名称
            // 根据属性类型打印数值或字符串
            if (VECTOR(etypes)[j] == IGRAPH_ATTRIBUTE_NUMERIC) {
                igraph_real_printf(EAN(g, igraph_strvector_get(&enames, j), i)); // 打印数值属性
                putchar(' ');
            } else {
                printf("\"%s\" ", EAS(g, igraph_strvector_get(&enames, j), i)); // 打印字符串属性
            }
        }
        printf("\n"); // 换行
    }

    // 销毁之前初始化的向量和字符串向量
    igraph_strvector_destroy(&enames);
    igraph_strvector_destroy(&vnames);
    igraph_strvector_destroy(&gnames);
    igraph_vector_int_destroy(&etypes);
    igraph_vector_int_destroy(&vtypes);
    igraph_vector_int_destroy(&gtypes);
}

下面的程序首先创建了一个有向图,然后设置了图的属性,包括数值类型、字符串类型和布尔类型。接着,它为一条边设置了颜色属性,并使用向量为所有顶点设置了属性"y"的值。之后,它为顶点0单独设置了属性"y"的值,并删除了图的布尔属性"is_regular"。最后,程序打印了图的最终属性。

#include <igraph.h>
#include <string.h>
#include <stdlib.h>

int main(void) {
    igraph_t graph;         // 声明一个igraph_t类型的图变量
    igraph_vector_t y;      // 声明一个igraph_vector_t类型的向量变量

    /* 启用属性处理 */
    igraph_set_attribute_table(&igraph_cattribute_table);

    /* 创建一个有向图,包含3个顶点和3条边 */
    igraph_small(&graph, 3, IGRAPH_DIRECTED, 0,1, 1,2, -1);

    /* 设置图属性 */
    /* 设置数值类型的图属性 */
    SETGAN(&graph, "id", 10); 
    /* 设置字符串类型的图属性 */
    SETGAS(&graph, "name", "toy");
    /* 设置布尔类型的图属性 */
    SETGAB(&graph, "is_regular", false);

    /* 设置边的字符串属性 */
    SETEAS(&graph, "color", 1, "RED");

    /* 设置顶点属性,使用向量 */
    igraph_vector_init(&y, igraph_vcount(&graph)); // 初始化向量,大小为顶点数
    igraph_vector_fill(&y, 1.23);                  // 用1.23填充向量
    SETVANV(&graph, "y", &y);                     // 为所有顶点设置属性"y"的值
    igraph_vector_destroy(&y);                     // 销毁向量,释放内存

    /* 设置单个顶点的数值属性 */
    SETVAN(&graph, "y", 0, -1); // 为顶点0设置属性"y"的值为-1

    /* 删除图属性 */
    DELGA(&graph, "is_regular"); // 删除属性"is_regular"

    /* 打印最终结果 */
    print_attributes(&graph); // 调用之前定义的函数打印图的属性

    /* 删除所有剩余的属性 */
    DELALL(&graph); // 删除图的所有属性

    /* 销毁图 */
    igraph_destroy(&graph); // 释放图占用的内存

    return 0; // 程序正常退出
}

4 运行结果

下面是对这些输出结果的解释:

  1. id=10 name="toy": 这部分显示了图的属性。id 是一个数值属性,值为 10;name 是一个字符串属性,值为 "toy"。

  2. Vertex 0: y=-1: 这表示顶点 0 的属性 y 的值为 -1。这是通过 SETVAN 函数单独为顶点 0 设置的。

  3. Vertex 1: y=1.23: 这表示顶点 1 的属性 y 的值为 1.23。这是通过 SETVANV 函数使用向量 y 为所有顶点设置的属性值。

  4. Vertex 2: y=1.23: 这与顶点 1 相同,属性 y 的值也为 1.23。

  5. Edge 0 (0-1): color="": 这表示边 0(从顶点 0 到顶点 1)的属性 color 没有被设置,因此显示为空字符串。

  6. Edge 1 (1-2): color="RED": 这表示边 1(从顶点 1 到顶点 2)的属性 color 被设置为 "RED"。

请注意,程序中删除了图的布尔属性 is_regular,但是在输出中没有显示这部分,因为它已经被删除了。此外,边的 color 属性只设置了边 1,所以边 0 的 color 属性为空。

  • 14
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于您的问题,我会尽力回答。在Android中,JNI可以用来与C/C++代码进行交互,我们可以利用JNI来读写SD卡。下面是一个简单的例子: 1. 首先,在您的Java代码中定义native方法: ``` public class MainActivity extends Activity { static { System.loadLibrary("native-lib"); } public native String readFromSDCard(String filePath); public native boolean writeToSDCard(String filePath, String content); } ``` 2. 然后,在您的C/C++代码中实现这些方法: ``` #include <jni.h> #include <string.h> #include <stdio.h> #include <android/log.h> JNIEXPORT jstring JNICALL Java_com_example_myapplication_MainActivity_readFromSDCard(JNIEnv *env, jobject instance, jstring filePath) { const char *path = env->GetStringUTFChars(filePath, 0); FILE *file = fopen(path, "r"); if (file == NULL) { __android_log_print(ANDROID_LOG_ERROR, "JNI", "readFromSDCard: fopen failed"); return NULL; } fseek(file, 0, SEEK_END); long size = ftell(file); fseek(file, 0, SEEK_SET); char *buffer = new char[size + 1]; fread(buffer, 1, size, file); buffer[size] = '\0'; fclose(file); env->ReleaseStringUTFChars(filePath, path); return env->NewStringUTF(buffer); } JNIEXPORT jboolean JNICALL Java_com_example_myapplication_MainActivity_writeToSDCard(JNIEnv *env, jobject instance, jstring filePath, jstring content) { const char *path = env->GetStringUTFChars(filePath, 0); const char *str = env->GetStringUTFChars(content, 0); FILE *file = fopen(path, "w"); if (file == NULL) { __android_log_print(ANDROID_LOG_ERROR, "JNI", "writeToSDCard: fopen failed"); return false; } fwrite(str, 1, strlen(str), file); fclose(file); env->ReleaseStringUTFChars(filePath, path); env->ReleaseStringUTFChars(content, str); return true; } ``` 3. 最后,在您的AndroidManifest.xml文件中添加以下权限: ``` <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> ``` 这样,您就可以在Java代码中调用这些native方法来读写SD卡了。 至于Android NDK的使用实例——增量更新实战,这是一个比较复杂的话题,如果您有相关的需求,可以提出具体的问题,我会尽力为您解答。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值