用于使用 igraph C 库
本节列出的一些容器类型是为多种基本类型定义的。这类似于 C++ 中的模板和 Ada 中的泛型,但由于 C 语言无法处理,因此它是通过预处理器宏实现的。以下是模板类型及其当前支持的所有基本类型的列表
向量当前为 igraph_real_t、igraph_integer_t (int)、char (char)、igraph_bool_t (bool)、igraph_complex_t (complex) 和 void * (ptr) 定义。默认值为 igraph_real_t。
矩阵当前为 igraph_real_t、igraph_integer_t (int)、char (char)、igraph_bool_t (bool) 和 igraph_complex_t (complex) 定义。默认值为 igraph_real_t。
Array3 当前为 igraph_real_t、igraph_integer_t (int)、char (char) 和 igraph_bool_t (bool) 定义。默认值为 igraph_real_t。
栈当前为 igraph_real_t、igraph_integer_t (int)、char (char) 和 igraph_bool_t (bool) 定义。默认值为 igraph_real_t。
Dqueue 当前为 igraph_real_t、igraph_integer_t (int)、char (char) 和 igraph_bool_t (bool) 定义。默认值为 igraph_real_t。
堆当前为 igraph_real_t、igraph_integer_t (int)、char (char) 定义。此外,还提供最大堆和最小堆。默认值为 igraph_real_t 最大堆。
向量列表当前为保存 igraph_real_t 和 igraph_integer_t (int) 的向量定义。默认值为 igraph_real_t。
矩阵列表当前仅为保存 igraph_real_t 的矩阵定义。
基本元素的名称(在括号中)会添加到函数名称中,默认类型除外。
一些示例
igraph_vector_t 是 igraph_real_t 元素的向量。其函数为 igraph_vector_init
、igraph_vector_destroy
、igraph_vector_sort
等。
igraph_vector_bool_t 是 igraph_bool_t 元素的向量;使用 igraph_vector_bool_init
初始化,使用 igraph_vector_bool_destroy
销毁,等等。
igraph_heap_t 是一个带有 igraph_real_t 元素的最大堆。相应的函数为 igraph_heap_init
、igraph_heap_pop
等。
igraph_heap_min_t 是一个带有 igraph_real_t 元素的最小堆。相应的函数名为 igraph_heap_min_init
、igraph_heap_min_pop
等。
igraph_heap_int_t 是一个带有 igraph_integer_t 元素的最大堆。其函数具有 igraph_heap_int_
前缀。
igraph_heap_min_int_t 是一个包含 igraph_integer_t 元素的最小堆。其函数具有 igraph_heap_min_int_
前缀。
igraph_vector_list_t 是一个(浮点)向量列表;此数据结构中的每个元素都是 igraph_vector_t。类似地,igraph_matrix_list_t 是一个(浮点)矩阵列表;此数据结构中的每个元素都是 igraph_matrix_t。
igraph_vector_int_list_t 是一个整数向量列表;此数据结构中的每个元素都是 igraph_vector_int_t。
请注意,VECTOR 和 MATRIX 宏可以用于所有向量和矩阵类型。VECTOR 不能用于向量列表,只能用于列表中的单个向量。
igraph_vector_t 数据类型是一个简单而高效的接口,用于包含数字的数组。它类似于(但比)C++ 标准库中的 vector 模板。
存在多种 igraph_vector_t 变体;基本变体存储双精度数,但也存在用于整数(类型为 igraph_integer_t)、布尔值(类型为 igraph_bool_t)等的 igraph_vector_int_t 和 igraph_vector_bool_t
。向量在 igraph 中被广泛使用;所有期望或返回数字列表的函数都使用 igraph_vector_t 或 igraph_vector_int_t 来实现此目的。整数向量通常用于向量应该保存顶点或边标识符时,而 igraph_vector_t 用于向量应该保存小数或无穷大时。
igraph_vector_t 类型及其变体通常使用 O(n) 空间来存储 n 个元素。有时它们会使用更多空间,这是因为向量可以缩小,但即使它们缩小,当前的实现也不会释放任何内存。
igraph_vector_t 对象及其变体中的元素从零开始索引,我们在此遵循通常的 C 约定。
向量的元素始终占用一块内存,可以使用 VECTOR
宏查询此内存块的起始地址。这样,向量对象可以与标准数学库(如 GNU 科学库)一起使用。
下面针对 igraph_vector_t 描述的几乎所有函数也适用于所有其他向量类型变体。这些变体没有单独记录;如果您需要另一个变体的函数,只需将 vector
替换为 vector_int
、vector_bool
或类似的名称即可。例如,要初始化类型为 igraph_vector_int_t 的向量,您需要使用 igraph_vector_int_init()
,而不是 igraph_vector_init()
。
igraph_vector_t 对象在使用前必须初始化,这类似于对其调用构造函数。为了您的方便,存在许多 igraph_vector_t 构造函数。igraph_vector_init()
是基本构造函数,它创建一个给定长度的向量,并用零填充每个条目。igraph_vector_init_copy()
创建一个已经存在并初始化的向量的新的相同副本。igraph_vector_init_array()
通过复制一个普通的 C 数组来创建一个向量。igraph_vector_init_range()
创建一个包含增量为 1 的常规序列的向量。
igraph_vector_view()
是一个特殊的构造函数,它允许您将常规 C 数组作为 vector 处理,而无需复制其元素。
如果不再需要 igraph_vector_t 对象,则应通过调用 igraph_vector_t 析构函数 igraph_vector_destroy()
来销毁它以释放其分配的内存。
请注意,由 igraph_vector_view()
创建的向量是特殊的,您绝不能在这些向量上调用 igraph_vector_destroy()
。
igraph_error_t igraph_vector_init(igraph_vector_t *v, igraph_integer_t size);
每个向量在使用前都需要初始化,并且存在许多初始化函数或以其他方式调用的构造函数。此函数构造一个给定大小的向量,并将每个条目初始化为 0。请注意,igraph_vector_null()
可用于将向量的每个元素设置为零。但是,如果您想要一个零向量,则使用此函数比创建向量然后调用 igraph_vector_null()
快得多。
由该函数初始化的每个向量对象都应该在其不再需要时销毁(即,为其分配的内存应该释放),igraph_vector_destroy()
函数负责执行此操作。
参数:
|
指向尚未初始化的向量对象的指针。 |
|
向量的大小。 |
返回值:
错误代码:如果没有足够的内存,则为 |
时间复杂度:操作系统相关,分配 O(n) 个元素所需的“时间”量,n 是元素的数量。
igraph_error_t igraph_vector_init_array( igraph_vector_t *v, const igraph_real_t *data, igraph_integer_t length);
参数:
|
指向未初始化的向量对象的指针。 |
|
一个普通的 C 数组。 |
|
C 数组的长度。 |
返回值:
错误代码:如果没有足够的内存,则为 |
时间复杂度:操作系统特定,通常为 O(length
)。
igraph_error_t igraph_vector_init_copy( igraph_vector_t *to, const igraph_vector_t *from );
现有向量对象的内容将被复制到新对象。
参数:
|
指向尚未初始化的向量对象的指针。 |
|
要复制的原始向量对象。 |
返回值:
错误代码:如果没有足够的内存,则为 |
时间复杂度:操作系统相关,通常为 O(n),n 是向量的大小。
igraph_error_t igraph_vector_init_range(igraph_vector_t *v, igraph_real_t start, igraph_real_t end);
该向量将包含数字 start
、start
+1、...、end
-1。请注意,根据 C 约定,该范围从左侧闭合,从右侧打开。
参数:
|
指向未初始化的向量对象的指针。 |
|
范围内的下限(包括)。 |
|
范围内的上限(不包括)。 |
返回值:
错误代码: |
时间复杂度:O(n),向量中的元素数量。
void igraph_vector_destroy(igraph_vector_t *v);
由 igraph_vector_init()
初始化的所有向量都应由此函数正确销毁。销毁的向量需要通过 igraph_vector_init()
、igraph_vector_init_array()
或另一个构造函数重新初始化。
参数:
|
指向要销毁的(先前初始化的)向量对象的指针。 |
时间复杂度:操作系统相关。
void igraph_vector_null(igraph_vector_t *v);
请注意,igraph_vector_init()
也将元素设置为零,因此在刚刚初始化的向量上调用此函数没有意义。因此,如果您想要构造一个零向量,则应该使用 igraph_vector_init()
。
参数:
|
向量对象。 |
时间复杂度:O(n),向量的大小。
void igraph_vector_fill(igraph_vector_t *v, igraph_real_t e);
将向量的每个元素设置为提供的常量。
参数:
|
要处理的向量。 |
|
要填充的元素。 |
时间复杂度:O(n),向量的大小。
访问向量元素的最好和最有效的方法是使用 VECTOR
宏。此宏可以用于查询和设置 igraph_vector_t 元素。如果您需要一个函数,igraph_vector_get()
查询向量的元素,igraph_vector_set()
设置向量的元素。igraph_vector_get_ptr()
返回元素的地址。
igraph_vector_tail()
返回非空向量的最后一个元素。但是,没有 igraph_vector_head()
函数,因为很容易编写 VECTOR(v)[0]
来代替。
#define VECTOR(v)
用法
VECTOR(v)[0]
要访问向量的第一个元素,您也可以在赋值中使用它,例如
VECTOR(v)[10] = 5;
请注意,目前没有范围检查。
参数:
|
向量对象。 |
时间复杂度:O(1)。
igraph_real_t igraph_vector_get(const igraph_vector_t *v, igraph_integer_t pos);
除非您需要函数,否则请考虑使用 VECTOR
宏以获得更好的性能。
参数:
|
igraph_vector_t 对象。 |
|
元素的位置,第一个元素的索引为零。 |
返回值:
所需的元素。 |
另请参阅:
时间复杂度:O(1)。
igraph_real_t* igraph_vector_get_ptr(const igraph_vector_t *v, igraph_integer_t pos);
除非您需要函数,否则请考虑使用 VECTOR
宏以获得更好的性能。
参数:
|
igraph_vector_t 对象。 |
|
元素的位置,第一个元素的位置为零。 |
返回值:
指向所需元素的指针。 |
另请参阅:
时间复杂度:O(1)。
void igraph_vector_set(igraph_vector_t *v, igraph_integer_t pos, igraph_real_t value);
除非您需要函数,否则请考虑使用 VECTOR
宏以获得更好的性能。
参数:
|
igraph_vector_t 元素。 |
|
要设置的元素的位置。 |
|
元素的新值。 |
另请参阅:
const igraph_vector_t* igraph_vector_view(const igraph_vector_t *v, const igraph_real_t *data, igraph_integer_t length);
这是一个特殊的 igraph_vector_t 构造函数。它允许临时将常规 C 数组作为 igraph_vector_t 处理。请确保您不要在由此构造函数创建的对象上调用析构函数 (igraph_vector_destroy()
)。
参数:
|
指向未初始化的 igraph_vector_t 对象的指针。 |
|
指针,C 数组。它可能不是 |
|
C 数组的长度。 |
返回值:
指向向量对象的指针,与 |
时间复杂度:O(1)
void igraph_vector_copy_to(const igraph_vector_t *v, igraph_real_t *to);
C 数组应该有足够的长度。
参数:
|
向量对象。 |
|
C 数组。 |
时间复杂度:O(n),n 是向量的大小。
igraph_error_t igraph_vector_update(igraph_vector_t *to, const igraph_vector_t *from);
此操作后,to
的内容将与 from
的内容完全相同。如果向量 to
最初比 from
短或长,则会调整其大小。
参数:
|
要更新的向量。 |
|
要从中更新的向量。 |
返回值:
错误代码。 |
时间复杂度:O(n),from
中的元素数量。
igraph_error_t igraph_vector_swap_elements(igraph_vector_t *v, igraph_integer_t i, igraph_integer_t j);
请注意,目前不执行范围检查。
参数:
|
输入向量。 |
|
第一个元素的索引。 |
|
第二个元素的索引(可能与第一个元素相同)。 |
返回值:
错误代码,目前始终为 |
时间复杂度:O(1)。
igraph_error_t igraph_vector_reverse(igraph_vector_t *v);
第一个元素将是最后一个,最后一个元素将是第一个,依此类推。
参数:
|
输入向量。 |
返回值:
错误代码,目前始终为 |
另请参阅:
igraph_vector_reverse_section() 仅反转向量的某个部分。 |
时间复杂度:O(n),元素数量。
void igraph_vector_reverse_section(igraph_vector_t *v, igraph_integer_t from, igraph_integer_t to);
参数:
|
输入向量。 |
|
要包含在反转中的第一个元素的索引。 |
|
不包含在反转中的第一个元素的索引。 |
另请参阅:
igraph_vector_reverse() 反转整个向量。 |
时间复杂度:O(to - from),要反转的元素数量。
void igraph_vector_rotate_left(igraph_vector_t *v, igraph_integer_t n);
将向量的元素向左旋转给定的步数。旋转后,元素索引 n
的索引将为 0。例如,将 (0, 1, 2, 3, 4, 5)
旋转 2 将得到 (2, 3, 4, 5, 0, 1)
。
参数:
|
输入向量。 |
|
要旋转的步数。传递负值会向右旋转。 |
时间复杂度:O(n),元素数量。
igraph_error_t igraph_vector_shuffle(igraph_vector_t *v);
Fisher-Yates 洗牌确保在使用适当的随机源时,每个排列都是同样可能的。当然,这不适用于伪随机生成器,因为这些生成器的循环小于向量可能排列的数量(如果向量足够长)。
参数:
|
向量对象。 |
返回值:
错误代码,目前始终为 |
时间复杂度:O(n),向量中的元素数量。
参考
|
R. A. Fisher 和 F. Yates。《生物学、农业和医学研究的统计表。》 Oliver 和 Boyd,第 6 版,1963 年,第 37 页。 |
|
D. E. Knuth。《半数值算法,》卷 2,《计算机编程的艺术。》 Addison-Wesley,第 3 版,1998 年,第 145 页。 |
示例 7.1. 文件 examples/simple/igraph_fisher_yates_shuffle.c
#include <igraph.h> #define R_INTEGER(a,b) (igraph_rng_get_integer(igraph_rng_default(), (a), (b))) #define R_UNIF(a,b) (igraph_rng_get_unif(igraph_rng_default(), (a), (b))) int main(void) { igraph_real_t d; igraph_vector_t u, v; igraph_integer_t i, k, n; /******************************** * Example usage ********************************/ /* Sequences with one element. Such sequences are trivially permuted. * The result of any Fisher-Yates shuffle on a sequence with one element * must be the original sequence itself. */ n = 1; igraph_vector_init(&v, n); igraph_rng_seed(igraph_rng_default(), 42); /* make tests deterministic */ k = R_INTEGER(-1000, 1000); VECTOR(v)[0] = k; igraph_vector_shuffle(&v); if (VECTOR(v)[0] != k) { return 1; } d = R_UNIF(-1000.0, 1000.0); VECTOR(v)[0] = d; igraph_vector_shuffle(&v); if (VECTOR(v)[0] != d) { return 2; } igraph_vector_destroy(&v); /* Sequences with multiple elements. A Fisher-Yates shuffle of a sequence S * is a random permutation \pi(S) of S. Thus \pi(S) must have the same * length and elements as the original sequence S. A major difference between * S and its random permutation \pi(S) is that the order in which elements * appear in \pi(S) is probably different from how elements are ordered in S. * If S has length n = 1, then both \pi(S) and S are equivalent sequences in * that \pi(S) is merely S and no permutation has taken place. If S has * length n > 1, then there are n! possible permutations of S. Assume that * each such permutation is equally likely to appear as a result of the * Fisher-Yates shuffle. As n increases, the probability that S is different * from \pi(S) also increases. We have a probability of 1 / n! that S and * \pi(S) are equivalent sequences. */ n = 100; igraph_vector_init(&u, n); igraph_vector_init(&v, n); for (i = 0; i < n; i++) { k = R_INTEGER(-1000, 1000); VECTOR(u)[i] = k; VECTOR(v)[i] = k; } igraph_vector_shuffle(&v); /* must have same length */ if (igraph_vector_size(&v) != n) { return 3; } if (igraph_vector_size(&u) != igraph_vector_size(&v)) { return 4; } /* must have same elements */ igraph_vector_sort(&u); igraph_vector_sort(&v); if (!igraph_vector_all_e(&u, &v)) { return 5; } igraph_vector_destroy(&u); igraph_vector_destroy(&v); /* empty sequence */ igraph_vector_init(&v, 0); igraph_vector_shuffle(&v); igraph_vector_destroy(&v); return 0; }
igraph_error_t igraph_vector_permute(igraph_vector_t *v, const igraph_vector_int_t *index);
此函数采用向量 v
和相应的索引向量 ind
,并排列 v
的元素,使得在函数执行后,v
[ind[i]] 被移动为 v
[i]。
使用不表示有效排列的索引向量调用此函数是错误的。索引向量中的每个元素必须介于 0 和向量长度减一之间(包括),并且每个这样的元素必须只出现一次。该函数不会尝试验证索引向量。
此函数采用的索引向量与从 igraph_vector_sort_ind()
返回的索引向量兼容;传入来自 igraph_vector_sort_ind()
的索引向量将对原始向量进行排序。
作为一种特殊情况,此函数允许索引向量比要排列的向量短,在这种情况下,索引向量中未出现的索引的元素将从向量中删除。
参数:
|
要排列的向量 |
|
索引向量 |
返回值:
错误代码:如果没有足够的内存,则为 |
时间复杂度:O(n),向量的大小。
igraph_vector_add_constant
— 将一个常量加到向量上。igraph_vector_scale
— 将向量的所有元素乘以一个常量。igraph_vector_add
— 将两个向量相加。igraph_vector_sub
— 从一个向量中减去另一个向量。igraph_vector_mul
— 将两个向量相乘。igraph_vector_div
— 将一个向量除以另一个向量。igraph_vector_floor
— 通过对每个元素向下取整,将实数向量转换为整数向量。
void igraph_vector_add_constant(igraph_vector_t *v, igraph_real_t plus);
plus
被加到 v
的每个元素上。请注意,可能会发生溢出。
参数:
|
输入向量。 |
|
要添加的常量。 |
时间复杂度:O(n),元素数量。
void igraph_vector_scale(igraph_vector_t *v, igraph_real_t by);
参数:
|
向量。 |
|
常量。 |
返回值:
错误代码。当前实现始终返回成功。 |
在 0.2 版本中添加。
时间复杂度:O(n),向量中元素的数量。
igraph_error_t igraph_vector_add(igraph_vector_t *v1, const igraph_vector_t *v2);
将 v2
的元素添加到 v1
,结果存储在 v1
中。两个向量必须具有相同的长度。
参数:
|
第一个向量,结果将存储在这里。 |
|
第二个向量,其内容将保持不变。 |
返回值:
错误代码。 |
时间复杂度:O(n),元素数量。
igraph_error_t igraph_vector_sub(igraph_vector_t *v1, const igraph_vector_t *v2);
从 v1
中减去 v2
的元素,结果存储在 v1
中。两个向量必须具有相同的长度。
参数:
|
第一个向量,从中减去。结果存储在这里。 |
|
要减去的向量,它将保持不变。 |
返回值:
错误代码。 |
时间复杂度:O(n),向量的长度。
igraph_error_t igraph_vector_mul(igraph_vector_t *v1, const igraph_vector_t *v2);
v1
将逐元素乘以 v2
。两个向量必须具有相同的长度。
参数:
|
第一个向量,结果将存储在这里。 |
|
第二个向量,它保持不变。 |
返回值:
错误代码。 |
时间复杂度:O(n),元素数量。
igraph_vector_all_e
— 所有元素都相等吗?igraph_vector_all_almost_e
— 所有元素都几乎相等吗?igraph_vector_all_l
— 所有元素都小于吗?igraph_vector_all_g
— 所有元素都大于吗?igraph_vector_all_le
— 所有元素都小于或等于吗?igraph_vector_all_ge
— 所有元素都大于或等于吗?igraph_vector_is_equal
— 所有元素都相等吗?igraph_vector_zapsmall
— 将向量中的小元素替换为精确的零。igraph_vector_lex_cmp
— 两个向量的字典序比较(类型安全变体)。igraph_vector_lex_cmp_untyped
— 两个向量的字典序比较(非类型安全)。igraph_vector_colex_cmp
— 两个向量的逆字典序比较。igraph_vector_colex_cmp_untyped
— 两个向量的逆字典序比较。
igraph_bool_t igraph_vector_all_e(const igraph_vector_t *lhs, const igraph_vector_t *rhs);
检查两个向量的元素级相等性。对于包含浮点数值的向量,请考虑使用 igraph_matrix_all_almost_e()
。
参数:
|
第一个向量。 |
|
第二个向量。 |
返回值:
如果 |
时间复杂度:O(n),向量的长度。
igraph_bool_t igraph_vector_all_almost_e(const igraph_vector_t *lhs, const igraph_vector_t *rhs, igraph_real_t eps);
检查两个向量的元素是否在相对容差范围内相等。
参数:
|
第一个向量。 |
|
第二个向量。 |
|
相对容差,详见 |
返回值:
如果两个向量几乎相等则为真,如果至少有一个不同的元素或向量的大小不相同则为假。 |
igraph_bool_t igraph_vector_all_l(const igraph_vector_t *lhs, const igraph_vector_t *rhs);
参数:
|
第一个向量。 |
|
第二个向量。 |
返回值:
如果 |
时间复杂度:O(n),向量的长度。
igraph_bool_t igraph_vector_all_g(const igraph_vector_t *lhs, const igraph_vector_t *rhs);
参数:
|
第一个向量。 |
|
第二个向量。 |
返回值:
如果 |
时间复杂度:O(n),向量的长度。
igraph_bool_t igraph_vector_all_le(const igraph_vector_t *lhs, const igraph_vector_t *rhs);
参数:
|
第一个向量。 |
|
第二个向量。 |
返回值:
如果 |
时间复杂度:O(n),向量的长度。
igraph_bool_t igraph_vector_all_ge(const igraph_vector_t *lhs, const igraph_vector_t *rhs);
参数:
|
第一个向量。 |
|
第二个向量。 |
返回值:
如果 |
时间复杂度:O(n),向量的长度。
igraph_bool_t igraph_vector_is_equal(const igraph_vector_t *lhs, const igraph_vector_t *rhs);
这是 igraph_vector_all_e()
的别名,名称更直观。
参数:
|
第一个向量。 |
|
第二个向量。 |
返回值:
如果 |
时间复杂度:O(n),向量的长度。
igraph_error_t igraph_vector_zapsmall(igraph_vector_t *v, igraph_real_t tol);
幅度小于给定绝对容差的向量元素将被替换为精确的零。默认容差对应于 igraph_real_t 的可表示数字的三分之二,即 DBL_EPSILON^(2/3)
,大约为 10^-10
。
参数:
|
要处理的向量,它将被就地更改。 |
|
容差值。幅度小于此值的数字将被替换为零。传入零以使用默认容差。不能为负数。 |
返回值:
错误代码。 |
另请参阅:
|
int igraph_vector_lex_cmp( const igraph_vector_t *lhs, const igraph_vector_t *rhs );
如果两个向量的元素匹配但一个较短,则较短的向量排在前面。因此 {1, 3} 排在 {1, 2, 3} 之后,但在 {1, 3, 4} 之前。
此函数通常与 igraph_vector_list_sort()
一起使用。
参数:
|
指向第一个向量的指针。 |
|
指向第二个向量的指针。 |
返回值:
如果 |
另请参阅:
有关此函数的非类型化变体,请参阅 |
时间复杂度:O(n),较小向量中元素的数量。
示例 7.2. 文件 examples/simple/igraph_vector_int_list_sort.c
#include <igraph.h> #include <stdio.h> int main(void) { igraph_t graph; igraph_vector_int_list_t cliques; igraph_integer_t i, n; /* Set a random seed to make the program deterministic */ igraph_rng_seed(igraph_rng_default(), 31415); /* Create a random graph with a given number of vertices and edges */ igraph_erdos_renyi_game_gnm(&graph, 15, 80, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS); /* Find all maximal cliques in the graph */ igraph_vector_int_list_init(&cliques, 0); igraph_maximal_cliques(&graph, &cliques, -1, -1); /* Print the cliques in lexicographical order */ printf("Maximal cliques in lexicographical order:\n"); igraph_vector_int_list_sort(&cliques, igraph_vector_int_lex_cmp); n = igraph_vector_int_list_size(&cliques); for (i=0; i < n; ++i) { igraph_vector_int_print(igraph_vector_int_list_get_ptr(&cliques, i)); } /* Print the cliques in colexicographical order */ printf("\nMaximal cliques in colexicographical order:\n"); igraph_vector_int_list_sort(&cliques, igraph_vector_int_colex_cmp); n = igraph_vector_int_list_size(&cliques); for (i=0; i < n; ++i) { igraph_vector_int_print(igraph_vector_int_list_get_ptr(&cliques, i)); } /* Destroy data structures when we no longer need them */ igraph_vector_int_list_destroy(&cliques); igraph_destroy(&graph); return 0; }
int igraph_vector_lex_cmp_untyped(const void *lhs, const void *rhs);
如果两个向量的元素匹配但一个较短,则较短的向量排在前面。因此 {1, 3} 排在 {1, 2, 3} 之后,但在 {1, 3, 4} 之前。
此函数通常与 igraph_vector_ptr_sort()
一起使用。
参数:
|
指向指向第一个向量的指针的指针(解释为 |
|
指向指向第二个向量的指针的指针(解释为 |
返回值:
如果 |
另请参阅:
有关此函数的类型安全变体,请参阅 |
时间复杂度:O(n),较小向量中元素的数量。
int igraph_vector_colex_cmp( const igraph_vector_t *lhs, const igraph_vector_t *rhs );
此比较从两个向量的最后一个元素开始并向后移动。如果两个向量的元素匹配但一个较短,则较短的向量排在前面。因此 {1, 2} 排在 {3, 2, 1} 之后,但在 {0, 1, 2} 之前。
此函数通常与 igraph_vector_list_sort()
一起使用。
参数:
|
指向指向第一个向量的指针的指针。 |
|
指向指向第二个向量的指针的指针。 |
返回值:
如果 |
另请参阅:
有关此函数的非类型化变体,请参阅 |
时间复杂度:O(n),较小向量中元素的数量。
示例 7.3. 文件 examples/simple/igraph_vector_int_list_sort.c
#include <igraph.h> #include <stdio.h> int main(void) { igraph_t graph; igraph_vector_int_list_t cliques; igraph_integer_t i, n; /* Set a random seed to make the program deterministic */ igraph_rng_seed(igraph_rng_default(), 31415); /* Create a random graph with a given number of vertices and edges */ igraph_erdos_renyi_game_gnm(&graph, 15, 80, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS); /* Find all maximal cliques in the graph */ igraph_vector_int_list_init(&cliques, 0); igraph_maximal_cliques(&graph, &cliques, -1, -1); /* Print the cliques in lexicographical order */ printf("Maximal cliques in lexicographical order:\n"); igraph_vector_int_list_sort(&cliques, igraph_vector_int_lex_cmp); n = igraph_vector_int_list_size(&cliques); for (i=0; i < n; ++i) { igraph_vector_int_print(igraph_vector_int_list_get_ptr(&cliques, i)); } /* Print the cliques in colexicographical order */ printf("\nMaximal cliques in colexicographical order:\n"); igraph_vector_int_list_sort(&cliques, igraph_vector_int_colex_cmp); n = igraph_vector_int_list_size(&cliques); for (i=0; i < n; ++i) { igraph_vector_int_print(igraph_vector_int_list_get_ptr(&cliques, i)); } /* Destroy data structures when we no longer need them */ igraph_vector_int_list_destroy(&cliques); igraph_destroy(&graph); return 0; }
int igraph_vector_colex_cmp_untyped(const void *lhs, const void *rhs);
此比较从两个向量的最后一个元素开始并向后移动。如果两个向量的元素匹配但一个较短,则较短的向量排在前面。因此 {1, 2} 排在 {3, 2, 1} 之后,但在 {0, 1, 2} 之前。
此函数通常与 igraph_vector_ptr_sort()
一起使用。
参数:
|
指向指向第一个向量的指针的指针(解释为 |
|
指向指向第二个向量的指针的指针(解释为 |
返回值:
如果 |
另请参阅:
有关此函数的类型安全变体,请参阅 |
时间复杂度:O(n),较小向量中元素的数量。
igraph_real_t igraph_vector_min(const igraph_vector_t *v);
向量不能为空。
参数:
|
输入向量。 |
返回值:
|
时间复杂度:O(n),元素数量。
igraph_real_t igraph_vector_max(const igraph_vector_t *v);
向量不能为空。
参数:
|
向量对象。 |
返回值:
|
时间复杂度:O(n),元素数量。
igraph_integer_t igraph_vector_which_min(const igraph_vector_t* v);
向量不能为空。如果最小元素不是唯一的,则返回第一个的索引。如果向量包含 NaN 值,则返回第一个 NaN 值的索引。
参数:
|
输入向量。 |
返回值:
最小元素的索引。 |
时间复杂度:O(n),元素数量。
igraph_integer_t igraph_vector_which_max(const igraph_vector_t *v);
向量不能为空。如果最大元素不是唯一的,则返回第一个的索引。如果向量包含 NaN 值,则返回第一个 NaN 值的索引。
参数:
|
向量对象。 |
返回值:
第一个最大元素的索引。 |
时间复杂度:O(n),n 是向量的大小。
void igraph_vector_minmax(const igraph_vector_t *v, igraph_real_t *min, igraph_real_t *max);
如果您想要向量的最小和最大元素,则很方便。向量仅被遍历一次。向量必须非空。如果向量包含至少一个 NaN,则 min
和 max
都将是 NaN。
参数:
|
输入向量。它必须包含至少一个元素。 |
|
指向基本类型变量的指针,最小值存储在这里。 |
|
指向基本类型变量的指针,最大值存储在这里。 |
时间复杂度:O(n),元素数量。
void igraph_vector_which_minmax(const igraph_vector_t *v, igraph_integer_t *which_min, igraph_integer_t *which_max);
如果您需要最小和最大元素的索引,则很方便。向量仅被遍历一次。向量必须非空。如果最小值或最大值不是唯一的,则分别返回第一个最小值或第一个最大值的索引。如果向量包含至少一个 NaN,则 which_min
和 which_max
都将指向第一个 NaN 值。
参数:
|
输入向量。它必须包含至少一个元素。 |
|
最小元素的索引将存储在这里。 |
|
最大元素的索引将存储在这里。 |
时间复杂度:O(n),元素数量。
igraph_vector_empty
— 确定向量的大小是否为零。igraph_vector_size
— 向量的大小。igraph_vector_capacity
— 返回向量的已分配容量。igraph_vector_sum
— 计算向量中元素的总和。igraph_vector_prod
— 计算向量中元素的乘积。igraph_vector_isininterval
— 检查向量的所有元素是否都在给定的间隔内。igraph_vector_maxdifference
— m1
和 m2
的最大绝对差。igraph_vector_is_nan
— 检查每个元素是否为 NaN。igraph_vector_is_any_nan
— 检查是否有任何元素是 NaN。igraph_vector_is_all_finite
— 检查所有元素是否都是有限的。
igraph_bool_t igraph_vector_empty(const igraph_vector_t *v);
参数:
|
向量对象。 |
返回值:
如果向量的大小为零则为真,否则为假。 |
时间复杂度:O(1)。
igraph_integer_t igraph_vector_size(const igraph_vector_t *v);
返回向量中存储的元素数。
参数:
|
向量对象 |
返回值:
向量的大小。 |
时间复杂度:O(1)。
igraph_integer_t igraph_vector_capacity(const igraph_vector_t *v);
请注意,这可能与向量的大小(由 igraph_vector_size()
查询)不同,并且指定向量可以容纳多少个元素,而无需重新分配。
参数:
|
指向(先前初始化的)要查询的向量对象的指针。 |
返回值:
已分配容量。 |
另请参阅:
时间复杂度:O(1)。
igraph_real_t igraph_vector_sum(const igraph_vector_t *v);
对于空向量,返回 0。
参数:
|
向量对象。 |
返回值:
元素的总和。 |
时间复杂度:O(n),向量的大小。
igraph_real_t igraph_vector_prod(const igraph_vector_t *v);
对于空向量,返回 1。
参数:
|
向量对象。 |
返回值:
元素的乘积。 |
时间复杂度:O(n),向量的大小。
igraph_bool_t igraph_vector_isininterval(const igraph_vector_t *v, igraph_real_t low, igraph_real_t high);
参数:
|
向量对象。 |
|
间隔的下限(包括)。 |
|
间隔的上限(包括)。 |
返回值:
如果向量为空或所有向量元素都在间隔内,则为真,否则为假。如果有任何元素是 NaN,它将返回 false。 |
时间复杂度:O(n),向量中的元素数量。
igraph_real_t igraph_vector_maxdifference(const igraph_vector_t *m1, const igraph_vector_t *m2);
返回 m1
- m2
中具有最大绝对值的元素。两个向量必须非空,但它们不需要具有相同的长度,较长向量中的额外元素将被忽略。如果较短向量中有任何值是 NaN,则结果将是 NaN。
参数:
|
第一个向量。 |
|
第二个向量。 |
返回值:
|
时间复杂度:O(n),较短向量中元素的数量。
igraph_error_t igraph_vector_is_nan(const igraph_vector_t *v, igraph_vector_bool_t *is_nan);
参数:
|
要检查的 igraph_vector_t 对象。 |
|
结果布尔向量,指示每个元素是否为 NaN。 |
返回值:
错误代码, |
时间复杂度:O(n),元素数量。
igraph_bool_t igraph_vector_contains(const igraph_vector_t *v, igraph_real_t what);
通过线性搜索检查提供的元素是否包含在向量中。
参数:
|
输入向量。 |
|
要查找的元素。 |
返回值:
如果找到该元素则为 |
时间复杂度:O(n),向量的长度。
igraph_bool_t igraph_vector_search(const igraph_vector_t *v, igraph_integer_t from, igraph_real_t what, igraph_integer_t *pos);
提供的元素 what
在向量 v
中搜索,从元素索引 from
开始。如果找到,则第一个实例的索引(在 from
之后)存储在 pos
中。
参数:
|
输入向量。 |
|
开始搜索的索引。不执行范围检查。 |
|
要查找的元素。 |
|
如果不是 |
返回值:
布尔值,如果找到该元素则为 |
时间复杂度:O(m),要搜索的元素数,向量的长度减去 from
参数。
igraph_bool_t igraph_vector_binsearch(const igraph_vector_t *v, igraph_real_t what, igraph_integer_t *pos);
假设向量已排序。如果指定的元素 (what
) 不在向量中,则返回应插入该元素的位置(以保持向量排序)。如果向量包含任何 NaN 值,则返回的值是未定义的,并且 pos
可能指向任何位置。
参数:
|
igraph_vector_t 对象。 |
|
要搜索的元素。 |
|
指向 igraph_integer_t 的指针。如果向量中存在 |
返回值:
如果向量中找到 |
时间复杂度:O(log(n)),n 是 v
中的元素数。
igraph_bool_t igraph_vector_binsearch_slice(const igraph_vector_t *v, igraph_real_t what, igraph_integer_t *pos, igraph_integer_t start, igraph_integer_t end);
假设向量的指示切片(从 start
到 end
)已排序。如果指定的元素 (what
) 不在向量的切片中,则返回应插入该元素的位置(以保持 切片 排序)。请注意,这意味着返回的索引将指向切片的 内部(包括其端点),但不会计算切片外部的值。如果指示的切片包含任何 NaN 值,则返回的值是未定义的,并且 pos
可能指向切片中的任何位置。
参数:
|
igraph_vector_t 对象。 |
|
要搜索的元素。 |
|
指向 igraph_integer_t 的指针。如果向量的切片中存在 |
|
要搜索的切片的起始位置(包括)。 |
|
要搜索的切片的结束位置(不包括)。 |
返回值:
如果向量中找到 |
时间复杂度:O(log(n)),n 是 v
切片中的元素数,即 end
- start
。
igraph_vector_clear
— 从向量中删除所有元素。igraph_vector_reserve
— 为向量预留内存。igraph_vector_resize
— 调整向量大小。igraph_vector_resize_min
— 释放向量的未使用内存。igraph_vector_push_back
— 将一个元素追加到向量。igraph_vector_pop_back
— 删除并返回向量的最后一个元素。igraph_vector_insert
— 将单个元素插入向量。igraph_vector_remove
— 从向量中删除单个元素。igraph_vector_remove_section
— 从向量中删除一个部分。
void igraph_vector_clear(igraph_vector_t* v);
此函数只是将向量的大小设置为零,它不会释放任何已分配的内存。为此,您必须调用 igraph_vector_destroy()
。
参数:
|
向量对象。 |
时间复杂度:O(1)。
igraph_error_t igraph_vector_reserve(igraph_vector_t *v, igraph_integer_t capacity);
igraph 向量是灵活的,它们可以增长和收缩。但是,增长有时需要复制向量中的数据。为了避免这种情况,您可以调用此函数来为向量的未来增长预留空间。
请注意,此函数不更改向量的大小。让我们看一个小例子来澄清一下:如果您为 100 个元素预留空间,并且向量的大小是(并且仍然是)60,那么您肯定可以在复制向量之前向向量添加额外的 40 个元素。
参数:
|
向量对象。 |
|
向量的新已分配大小。 |
返回值:
错误代码:如果没有足够的内存,则为 |
时间复杂度:依赖于操作系统,应该在 O(n) 左右,n 是向量的新已分配大小。
igraph_error_t igraph_vector_resize(igraph_vector_t* v, igraph_integer_t new_size);
请注意,此函数不会释放任何内存,只是将向量的大小设置为给定的大小。另一方面,如果新大小大于先前的大小,它可以分配更多内存。在这种情况下,向量中新出现的元素不设置为零,它们是未初始化的。
参数:
|
向量对象 |
|
向量的新大小。 |
返回值:
错误代码, |
另请参阅:
有关为向量的未来扩展分配内存的信息,请参见 |
时间复杂度:如果新大小较小,则为 O(1),如果较大,则依赖于操作系统。在后一种情况下,通常约为 O(n),n 是向量的新大小。
void igraph_vector_resize_min(igraph_vector_t *v);
此函数尝试释放向量的未使用预留存储空间。如果成功,igraph_vector_size()
和 igraph_vector_capacity()
将相同。向量中的数据始终被保留,即使释放不成功。
参数:
|
指向已初始化向量的指针。 |
另请参阅:
时间复杂度:依赖于操作系统,最坏情况下为 O(n)。
igraph_error_t igraph_vector_push_back(igraph_vector_t *v, igraph_real_t e);
此函数将向量的大小调整为比原来长一个元素,并将向量中的最后一个元素设置为 e
。
参数:
|
向量对象。 |
|
要追加到向量的元素。 |
返回值:
错误代码: |
时间复杂度:依赖于操作系统。重要的是,对该函数的 n 次后续调用的时间复杂度为 O(n),即使 igraph_vector_reserve()
没有为新元素预留任何空间。这是通过类似于 C++ vector 类的技巧实现的:每次为向量分配更多内存时,额外分配的内存大小与向量的当前长度相同。(我们在这里假设内存分配的时间复杂度最多是线性的。)
igraph_real_t igraph_vector_pop_back(igraph_vector_t *v);
使用空向量调用此函数是一个错误。
参数:
|
向量对象。 |
返回值:
删除的最后一个元素。 |
时间复杂度:O(1)。
igraph_error_t igraph_vector_insert( igraph_vector_t *v, igraph_integer_t pos, igraph_real_t value);
请注意,此函数不进行范围检查。插入会将元素从给定位置到向量末尾向右移动一个位置,并将新元素插入到给定位置创建的空白空间中。向量的大小将增加 1。
参数:
|
向量对象。 |
|
要在其中插入新元素的位置。 |
|
要插入的新元素。 |
igraph_vector_complex_real
— 给出复数向量的实部。igraph_vector_complex_imag
— 返回复向量的虚部。igraph_vector_complex_realimag
— 返回复向量的实部和虚部。igraph_vector_complex_create
— 从实部和虚部创建一个复向量。igraph_vector_complex_create_polar
— 从幅值和角度创建一个复矩阵。igraph_vector_complex_all_almost_e
— 所有元素是否几乎相等?igraph_vector_complex_zapsmall
— 将复向量中的小元素替换为精确的零。
igraph_error_t igraph_vector_complex_real(const igraph_vector_complex_t *v, igraph_vector_t *real);
参数:
|
指向复向量的指针。 |
|
指向已初始化的向量的指针。结果将存储在此处。 |
返回值:
错误代码。 |
时间复杂度:O(n),向量中的元素数量。
igraph_error_t igraph_vector_complex_imag(const igraph_vector_complex_t *v, igraph_vector_t *imag);
参数:
|
指向复向量的指针。 |
|
指向已初始化的向量的指针。结果将存储在此处。 |
返回值:
错误代码。 |
时间复杂度:O(n),向量中的元素数量。
igraph_error_t igraph_vector_complex_realimag(const igraph_vector_complex_t *v, igraph_vector_t *real, igraph_vector_t *imag);
参数:
|
指向复向量的指针。 |
|
指向已初始化的向量的指针。实部将存储在此处。 |
|
指向已初始化的向量的指针。虚部将存储在此处。 |
返回值:
错误代码。 |
时间复杂度:O(n),向量中的元素数量。
igraph_error_t igraph_vector_complex_create(igraph_vector_complex_t *v, const igraph_vector_t *real, const igraph_vector_t *imag);
参数:
|
指向未初始化的复向量的指针。 |
|
指向复向量实部的指针。 |
|
指向复向量虚部的指针。 |
返回值:
错误代码。 |
时间复杂度:O(n),向量中的元素数量。
igraph_error_t igraph_vector_complex_create_polar(igraph_vector_complex_t *v, const igraph_vector_t *r, const igraph_vector_t *theta);
参数:
|
指向未初始化的复向量的指针。 |
|
指向包含幅值的实向量的指针。 |
|
指向包含辐角(相位角)的实向量的指针。 |
返回值:
错误代码。 |
时间复杂度:O(n),向量中的元素数量。
igraph_bool_t igraph_vector_complex_all_almost_e(const igraph_vector_complex_t *lhs, const igraph_vector_complex_t *rhs, igraph_real_t eps);
检查两个复向量的元素是否在相对容差范围内相等。
参数:
|
第一个向量。 |
|
第二个向量。 |
|
相对容差,有关详细信息,请参见 |
返回值:
如果两个向量几乎相等则为真,如果至少有一个不同的元素或向量的大小不相同则为假。 |
igraph_error_t igraph_vector_complex_zapsmall(igraph_vector_complex_t *v, igraph_real_t tol);
与 igraph_vector_zapsmall()
类似,小元素将被替换为零。该操作分别对数字的实部和虚部执行。这样,具有大实部和小虚部的复数将被有效地转换为实数。默认容差对应于 igraph_real_t 的可表示位数的⅔,即 DBL_EPSILON^(2/3)
,大约为 10^-10
。
参数:
|
要处理的向量,它将被就地更改。 |
|
容差值。实部和虚部小于此幅度的部分将被替换为零。传入零以使用默认容差。不能为负。 |
返回值:
错误代码。 |
另请参阅:
使用 |
void igraph_vector_sort(igraph_vector_t *v);
如果向量包含任何 NaN 值,则 NaN 值的最终排序是未定义的,并且可能出现在向量中的任何位置。
参数:
|
指向已初始化的向量对象的指针。 |
时间复杂度:对于 n 个元素为 O(n log n)。
void igraph_vector_reverse_sort(igraph_vector_t *v);
如果向量包含任何 NaN 值,则 NaN 值的最终排序是未定义的,并且可能出现在向量中的任何位置。
参数:
|
指向已初始化的向量对象的指针。 |
时间复杂度:对于 n 个元素为 O(n log n)。
igraph_error_t igraph_vector_sort_ind( const igraph_vector_t *v, igraph_vector_int_t *inds, igraph_order_t order);
接受一个未排序的数组 v
作为输入,并计算一个索引数组 inds
,使得 v[ inds[i] ]
,其中 i
从 0 开始递增,是一个有序数组(升序或降序,具体取决于 order
)。相同元素的索引顺序未定义。如果向量包含任何 NaN 值,则 NaN 值的排序是未定义的。
参数:
|
要排序的数组 |
|
索引的输出数组。必须初始化,但将调整大小 |
|
输出数组应按升序还是降序排序。使用 |
返回值:
错误代码。 |
此例程使用 igraph 的内置 qsort 例程。算法:1) 创建一个指向 v 元素的指针数组。2) 将此数组传递给 qsort。3) 排序后,指针值与第一个指针值之间的差异给出了其在数组中的原始位置。使用此来设置 inds 的值。
igraph_error_t igraph_vector_intersect_sorted(const igraph_vector_t *v1, const igraph_vector_t *v2, igraph_vector_t *result);
同时包含在两个向量中的元素存储在结果向量中。所有三个向量都必须初始化。
对于大小相似的向量,此函数使用简单的线性扫描。当向量大小差异很大时,它使用 Ricardo Baeza-Yates 的集合交集方法,该方法在较大向量的长度中花费对数时间。
该算法保留元素的重数:如果一个元素在第一个向量中出现 k1
次,在第二个向量中出现 k2
次,则结果将包括该元素 min(k1, k2)
次。
参考
Baeza-Yates R: A fast set intersection algorithm for sorted sequences. In: Lecture Notes in Computer Science, vol. 3109/2004, pp. 400--408, 2004. Springer Berlin/Heidelberg. https://doi.org/10.1007/978-3-540-27801-6_30
参数:
|
第一个向量 |
|
第二个向量 |
|
结果向量,也将被排序。 |
返回值:
错误代码。 |
时间复杂度:O(m log(n)),其中 m 是较小向量的大小,n 是较大向量的大小。
igraph_integer_t igraph_vector_intersection_size_sorted( const igraph_vector_t *v1, const igraph_vector_t *v2);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
计算两个向量中都存在的元素。这对于计算两个顶点的共同邻居特别有用。
对于大小相似的向量,此函数使用简单的线性扫描。当向量大小差异很大时,它使用 Ricardo Baeza-Yates 的集合交集方法,该方法在较大向量的长度中花费对数时间。
该算法保留元素的重数:如果一个元素在第一个向量中出现 k1
次,在第二个向量中出现 k2
次,则结果将包括该元素 min(k1, k2)
次。
参考
Baeza-Yates R: A fast set intersection algorithm for sorted sequences. In: Lecture Notes in Computer Science, vol. 3109/2004, pp. 400--408, 2004. Springer Berlin/Heidelberg. https://doi.org/10.1007/978-3-540-27801-6_30
参数:
|
第一个向量 |
|
第二个向量 |
返回值:
公共元素的数量。 |
时间复杂度:O(m log(n)),其中 m 是较小向量的大小,n 是较大向量的大小。
igraph_vector_ptr_init
— 初始化指针向量(构造函数)。igraph_vector_ptr_init_copy
— 从另一个指针向量初始化一个指针向量(构造函数)。igraph_vector_ptr_destroy
— 销毁指针向量。igraph_vector_ptr_free_all
— 释放指针向量的所有元素。igraph_vector_ptr_destroy_all
— 释放所有元素并销毁指针向量。igraph_vector_ptr_size
— 返回指针向量中的元素数量。igraph_vector_ptr_clear
— 从指针向量中删除所有元素。igraph_vector_ptr_push_back
— 将一个元素追加到指针向量的末尾。igraph_vector_ptr_pop_back
— 删除并返回指针向量的最后一个元素。igraph_vector_ptr_insert
— 将单个元素插入到指针向量中。igraph_vector_ptr_get
— 访问指针向量的元素。igraph_vector_ptr_set
— 分配给指针向量的元素。igraph_vector_ptr_resize
— 调整指针向量的大小。igraph_vector_ptr_sort
— 基于外部比较函数对指针向量进行排序。igraph_vector_ptr_sort_ind
— 返回对指针向量进行排序的索引置换。igraph_vector_ptr_permute
— 根据索引向量就地置换指针向量的元素。igraph_vector_ptr_get_item_destructor
— 获取此指针向量的当前项析构函数。igraph_vector_ptr_set_item_destructor
— 设置此指针向量的项析构函数。IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR
— 设置此指针向量的项析构函数(宏版本)。igraph_vector_ptr_t 数据类型与 igraph_vector_t
类型非常相似,但它存储的是通用指针而不是实数。
此类型具有与 igraph_vector_t
相同的空间复杂度,并且大多数已实现的操作的工作方式与 igraph_vector_t
相同。
用于普通向量的相同 VECTOR
宏也可以用于指针向量,请注意,此宏将提供无类型通用指针,并且您可能需要在开始使用它之前将其强制转换为特定指针。
指针向量可能具有关联的项析构函数,该函数接受一个指针并且不返回任何内容。当通过 igraph_vector_ptr_destroy()
或 igraph_vector_ptr_destroy_all()
销毁指针向量时,或者当 igraph_vector_ptr_free_all()
释放其元素时,将对指针向量中的每个项调用项析构函数。请注意,项析构函数的语义与 C++ 析构函数不一致;例如,当将指针向量调整为更小的大小时,额外的项将不会自动销毁!尽管如此,项析构函数在许多情况下可能会变得方便;例如,可以使用对 igraph_vector_ptr_destroy_all()
的单个调用来销毁由某些函数生成的图的向量(如果项析构函数设置为 igraph_destroy()
)。
igraph_error_t igraph_vector_ptr_init(igraph_vector_ptr_t* v, igraph_integer_t size);
这是指针向量数据类型的构造函数。以这种方式构造的所有指针向量都应通过调用 igraph_vector_ptr_destroy()
来销毁。
参数:
|
指向未初始化的 igraph_vector_ptr_t 对象的指针,要创建。 |
|
整数,指针向量的大小。 |
返回值:
错误代码:如果内存不足,则为 |
时间复杂度:操作系统依赖,分配 size
元素所需的“时间”量。
igraph_error_t igraph_vector_ptr_init_copy(igraph_vector_ptr_t *to, const igraph_vector_ptr_t *from);
此函数通过复制另一个指针向量来创建一个指针向量。这是一个浅拷贝,只会复制向量中的指针。
复制具有关联的项析构函数的指针向量可能存在潜在的危险。复制的向量将继承项析构函数,这可能会在两个向量都被销毁时导致问题,因为这些项可能会被销毁两次。请确保您知道在复制具有项析构函数的指针向量时您在做什么,或者稍后取消设置其中一个向量的项析构函数。
参数:
|
指向未初始化的指针向量对象的指针。 |
|
一个指针向量对象。 |
返回值:
错误代码:如果内存不足,则为 |
时间复杂度:如果为 n 个元素分配内存可以在 O(n) 时间内完成,则为 O(n)。
void igraph_vector_ptr_destroy(igraph_vector_ptr_t* v);
指针向量的析构函数。
参数:
|
指向要销毁的指针向量的指针。 |
时间复杂度:操作系统依赖,需要释放 O(n) 字节的“时间”,n 是为指针向量分配的元素数量(不一定是向量中的元素数量)。
void igraph_vector_ptr_free_all(igraph_vector_ptr_t* v);
如果为此指针向量设置了项析构函数,则此函数将首先对向量的所有元素调用析构函数,然后使用 igraph_free()
释放所有元素。如果未设置项析构函数,则只会释放元素。
参数:
|
指向要释放其元素的指针向量的指针。 |
时间复杂度:操作系统依赖,调用析构函数 n 次然后释放 O(n) 个指针所需的“时间”,每个指针都指向任意大小的内存区域。n 是指针向量中的元素数量。
void igraph_vector_ptr_destroy_all(igraph_vector_ptr_t* v);
此函数等效于 igraph_vector_ptr_free_all()
之后接 igraph_vector_ptr_destroy()
。
参数:
|
指向要销毁的指针向量的指针。 |
时间复杂度:操作系统依赖,释放 O(n) 个指针所需的“时间”,每个指针都指向任意大小的内存区域,再加上释放 O(n) 字节所需的“时间”,n 是为指针向量分配的元素数量(不一定是向量中的元素数量)。
igraph_integer_t igraph_vector_ptr_size(const igraph_vector_ptr_t* v);
参数:
|
指针向量对象。 |
返回值:
对象的大小,即存储的指针数量。 |
时间复杂度:O(1)。
void igraph_vector_ptr_clear(igraph_vector_ptr_t* v);
此函数将指针向量的大小调整为零长度。请注意,指向的对象不会被释放,您应该对它们调用 igraph_free()
,或者确保以某种其他方式释放它们的已分配内存,否则您会得到内存泄漏。如果您之前设置了项析构函数,则将对每个元素调用析构函数。
请注意,此函数的当前实现不会释放存储指针所需的内存,因此以这种方式缩小指针向量不会返回任何内存。此行为将来可能会更改。
参数:
|
要清除的指针向量。 |
时间复杂度:O(1)。
igraph_error_t igraph_vector_ptr_push_back(igraph_vector_ptr_t* v, void* e);
参数:
|
指针向量。 |
|
要包含在指针向量中的新元素。 |
返回值:
错误代码。 |
另请参阅:
|
时间复杂度:O(1) 或 O(n),n 是向量中的元素数量。指针向量实现确保 n 个后续 push_back 操作需要 O(n) 时间才能完成。
void *igraph_vector_ptr_pop_back(igraph_vector_ptr_t *v);
使用空向量调用此函数是一个错误。
参数:
|
指针向量。 |
返回值:
删除的最后一个元素。 |
时间复杂度:O(1)。
igraph_error_t igraph_vector_ptr_insert(igraph_vector_ptr_t* v, igraph_integer_t pos, void* e);
请注意,此函数不进行范围检查。插入会将元素从给定位置到向量末尾向右移动一个位置,并将新元素插入到给定位置创建的空白空间中。向量的大小将增加 1。
参数:
|
指针向量对象。 |
|
插入新元素的位置。 |
|
插入的元素 |
void *igraph_vector_ptr_get(const igraph_vector_ptr_t* v, igraph_integer_t pos);
参数:
|
指向指针向量的指针。 |
|
要返回的指针的索引。 |
返回值:
位于 |
时间复杂度:O(1)。
void igraph_vector_ptr_set(igraph_vector_ptr_t* v, igraph_integer_t pos, void* value);
参数:
|
指向指针向量的指针。 |
|
要更新的指针的索引。 |
|
要在向量中设置的新指针。 |
时间复杂度:O(1)。
igraph_error_t igraph_vector_ptr_resize(igraph_vector_ptr_t* v, igraph_integer_t newsize);
请注意,如果向量变小,则此函数不会释放指向的对象,也不会对额外的元素调用项析构函数。
参数:
|
一个指针向量。 |
|
指针向量的新大小。 |
返回值:
错误代码。 |
时间复杂度:如果向量变小则为 O(1)。否则操作系统依赖,分配向量元素的内存所需的“时间”量。
void igraph_vector_ptr_sort(igraph_vector_ptr_t *v, int (*compar)(const void*, const void*));
有时需要基于指针引用的元素的属性对向量中的指针进行排序。此函数允许我们基于任意外部比较函数对向量进行排序,该函数接受两个 void * 指针 p1
和 p2
,并且如果第一个参数分别被认为小于、等于或大于第二个参数,则返回一个小于、等于或大于零的整数。p1
和 p2
将指向向量中的指针,因此如果想要访问存储在 v
中的地址的基础对象,则必须对其进行双重解引用。
参数:
|
要排序的指针向量。 |
|
一个 qsort 兼容的比较函数。它必须采用指向指针向量的元素的指针。例如,如果指针向量包含 |
igraph_error_t igraph_vector_ptr_sort_ind(igraph_vector_ptr_t *v, igraph_vector_int_t *inds, cmp_t *cmp);
接受一个未排序的数组 v
作为输入,并计算一个索引数组 inds,使得 v[ inds[i] ],其中 i 从 0 开始递增,是一个有序数组(升序或降序,具体取决于 \v order)。相同元素的索引顺序未定义。
参数:
|
要排序的数组 |
|
索引的输出数组。必须初始化,但将调整大小 |
|
一个比较器函数,它接受要排序的指针向量的两个元素(这些元素本身是指针上的常量指针),并且如果第一个指针“指向”的项小于第二个指针“指向”的项,则返回一个负值;如果它更大,则返回一个正值;如果两项相等,则返回零 |
返回值:
错误代码。 |
此例程使用 C 库 qsort 例程。算法:1) 创建一个指向 v 元素的指针数组。2) 将此数组传递给 qsort。3) 排序后,指针值与第一个指针值之间的差异给出了其在数组中的原始位置。使用此来设置 inds 的值。
igraph_error_t igraph_vector_ptr_permute(igraph_vector_ptr_t* v, const igraph_vector_int_t* index);
此函数采用向量 v
和相应的索引向量 ind
,并排列 v
的元素,使得在函数执行后,v
[ind[i]] 被移动为 v
[i]。
使用不表示有效排列的索引向量调用此函数是错误的。索引向量中的每个元素必须介于 0 和向量长度减一之间(包括),并且每个这样的元素必须只出现一次。该函数不会尝试验证索引向量。
此函数采用的索引向量与从 igraph_vector_ptr_sort_ind()
返回的索引向量兼容;传入来自 igraph_vector_ptr_sort_ind()
的索引向量将对原始向量进行排序。
作为一种特殊情况,此函数允许索引向量比要排列的向量短,在这种情况下,索引向量中未出现的索引的元素将从向量中删除。
参数:
|
要排列的向量 |
|
索引向量 |
返回值:
错误代码:如果没有足够的内存,则为 |
时间复杂度:O(n),向量的大小。
igraph_finally_func_t* igraph_vector_ptr_get_item_destructor(const igraph_vector_ptr_t *v);
项析构函数是一个函数,当调用 igraph_vector_ptr_destroy()
、igraph_vector_ptr_destroy_all() 或 igraph_vector_ptr_free_all()
时,将对存储在此向量中的每个非空指针调用该函数。
返回值:
当前的项析构函数。 |
时间复杂度:O(1)。
igraph_finally_func_t* igraph_vector_ptr_set_item_destructor( igraph_vector_ptr_t *v, igraph_finally_func_t *func);
项析构函数是一个函数,当调用 igraph_vector_ptr_destroy()
、igraph_vector_ptr_destroy_all() 或 igraph_vector_ptr_free_all()
时,将对存储在此向量中的每个非空指针调用该函数。
返回值:
旧的项析构函数。 |
时间复杂度:O(1)。
#define IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(v, func)
此宏扩展为 igraph_vector_ptr_set_item_destructor()
,唯一的区别是第二个参数会自动强制转换为 igraph_finally_func_t
*。在大多数情况下都需要强制转换,因为我们使用的析构函数(例如 igraph_vector_destroy()
)采用指向某些具体的 igraph 数据类型的指针,而 igraph_finally_func_t
期望 void
*
igraph_vector_copy
— 从另一个向量对象初始化一个向量(已弃用的别名)。igraph_vector_e
— 访问向量的元素(已弃用的别名)。igraph_vector_e_ptr
— 获取向量元素的地址。igraph_vector_init_seq
— 使用序列初始化向量,包括端点(已弃用)。igraph_vector_ptr_copy
— 从另一个指针向量初始化一个指针向量(已弃用的别名)。igraph_vector_ptr_e
— 访问指针向量的元素(已弃用的别名)。igraph_vector_qsort_ind
— 返回对向量进行排序的索引置换(已弃用的别名)。igraph_vector_binsearch2
— 二分查找,不返回索引。
igraph_error_t igraph_vector_copy(igraph_vector_t *to, const igraph_vector_t *from);
自版本 0.10 起已弃用。请勿在新代码中使用此函数;请改用 igraph_vector_init_copy()
。
igraph_real_t igraph_vector_e(const igraph_vector_t *v, igraph_integer_t pos);
自版本 0.10.0 起已弃用。请勿在新代码中使用此函数;请改用 igraph_vector_get()
。
igraph_real_t* igraph_vector_e_ptr(const igraph_vector_t *v, igraph_integer_t pos);
参数:
|
igraph_vector_t 对象。 |
|
元素的位置,第一个元素的位置为零。 |
返回值:
指向所需元素的指针。 |
另请参阅:
时间复杂度:O(1)。
igraph_error_t igraph_vector_init_seq(igraph_vector_t *v, igraph_real_t from, igraph_real_t to);
该向量将包含数字 from
、from
+1、...、to
。请注意,与 C 中范围的典型用法相反,两个端点都包括在内。
自版本 0.10.0 起已弃用。请勿在新代码中使用此函数;请改用 igraph_vector_init_range()
。
参数:
|
指向未初始化的向量对象的指针。 |
|
序列中的下限(包括在内)。 |
|
序列中的上限(包括在内)。 |
返回值:
错误代码: |
时间复杂度:O(n),向量中的元素数量。
igraph_error_t igraph_vector_ptr_copy(igraph_vector_ptr_t *to, const igraph_vector_ptr_t *from);
自版本 0.10 起已弃用。请勿在新代码中使用此函数;请改用 igraph_vector_ptr_init_copy()
。
void *igraph_vector_ptr_e(const igraph_vector_ptr_t* v, igraph_integer_t pos);
自版本 0.10.0 起已弃用。请勿在新代码中使用此函数;请改用 igraph_vector_ptr_get()
。
igraph_error_t igraph_vector_qsort_ind(const igraph_vector_t *v, igraph_vector_int_t *inds, igraph_order_t order);
自版本 0.10.14 起已弃用。请勿在新代码中使用此函数;请改用 igraph_vector_sort_ind()
。
igraph_bool_t igraph_vector_binsearch2(const igraph_vector_t *v, igraph_real_t what);
自版本 0.10.14 起已弃用。请勿在新代码中使用此函数;请改用 igraph_vector_contains_sorted()
。
此类型只是 igraph_vector_t 的接口。
igraph_matrix_t 类型通常在 O(n) 空间中存储 n 个元素,但并非总是如此。请参阅向量类型的文档。
igraph_error_t igraph_matrix_init( igraph_matrix_t *m, igraph_integer_t nrow, igraph_integer_t ncol);
每个矩阵在使用之前都需要初始化。这通过调用此函数来完成。如果不再需要矩阵,则必须将其销毁;请参阅 igraph_matrix_destroy()
。
参数:
|
指向尚未初始化的矩阵对象的指针,要初始化。 |
|
矩阵中的行数。 |
|
矩阵中的列数。 |
返回值:
错误代码。 |
时间复杂度:通常为 O(n),n 是矩阵中的元素数量。
igraph_error_t igraph_matrix_init_array( igraph_matrix_t *m, const igraph_real_t *data, igraph_integer_t nrow, igraph_integer_t ncol, igraph_matrix_storage_t storage);
假定该数组以连续的方式存储矩阵数据,无论是列优先格式还是行优先格式。换句话说,data
可能会存储串联的矩阵列或串联的矩阵行。从列优先数据构造矩阵的速度更快,因为这是 igraph 的本机存储格式。
参数:
|
指向未初始化的矩阵对象的指针。 |
|
一个常规的 C 数组,以列优先顺序存储矩阵的元素,即首先存储第一列的元素,然后是第二列,依此类推。 |
|
矩阵中的行数。 |
|
矩阵中的列数。 |
|
如果数组采用行优先格式,则为 |
返回值:
错误代码:如果没有足够的内存,则为 |
时间复杂度:操作系统特定,通常为 O(nrow
ncol
)。
#define MATRIX(m,i,j)
请注意,目前没有范围检查。此功能稍后可能会被重新定义为一个合适的函数。
参数:
|
矩阵对象。 |
|
行的索引,从零开始。 |
|
列的索引,从零开始。 |
时间复杂度:O(1)。
igraph_real_t igraph_matrix_get(const igraph_matrix_t *m, igraph_integer_t row, igraph_integer_t col);
如果出于某种原因需要一个函数,并且无法使用 MATRIX
宏,请使用此函数。请注意,不执行范围检查。
参数:
|
输入矩阵。 |
|
行索引。 |
|
列索引。 |
返回值:
给定行和列中的元素。 |
时间复杂度:O(1)。
const igraph_matrix_t* igraph_matrix_view( const igraph_matrix_t *m, const igraph_real_t *data, igraph_integer_t nrow, igraph_integer_t ncol);
此函数允许您将现有 C 数组视为矩阵。矩阵的元素假定以列优先顺序存储在数组中,即首先存储第一列的元素,然后是第二列,依此类推。
由于此函数创建了一个到现有数组的视图,因此您在完成操作后不得销毁 igraph_matrix_t
对象。同样,您不得在其上调用任何可能尝试修改矩阵大小的函数。修改矩阵中的元素将修改底层数组,因为两者共享相同的内存块。
参数:
|
指向尚未初始化的矩阵对象的指针,将在其中创建视图。 |
|
矩阵提供视图的数组。 |
|
矩阵中的行数。 |
|
矩阵中的列数。 |
返回值:
指向矩阵对象的指针,与 |
时间复杂度:O(1)。
const igraph_matrix_t *igraph_matrix_view_from_vector( const igraph_matrix_t *m, const igraph_vector_t *v, igraph_integer_t nrow );
此函数允许您将现有的 igraph 向量视为矩阵。矩阵的元素假定以列优先顺序存储在向量中,即首先存储第一列的元素,然后是第二列,依此类推。
由于此函数创建了一个到现有向量的视图,因此您在完成操作后不得销毁 igraph_matrix_t
对象。同样,您不得在其上调用任何可能尝试修改向量大小的函数。修改矩阵中的元素将修改底层向量,因为两者共享相同的内存块。
此外,您不得尝试通过任何向量操作来增加底层向量,因为这可能会导致向量的后备内存块重新分配,并且矩阵视图不会收到有关重新分配的通知,因此它将在之后指向无效的内存区域。
参数:
|
指向尚未初始化的矩阵对象的指针,将在其中创建视图。 |
|
矩阵将提供视图的向量。 |
|
矩阵中的行数。列数将从向量的大小隐式导出。如果向量中的项目数不能被行数整除,则向量的最后几个元素将不会被视图覆盖。 |
返回值:
错误代码。 |
时间复杂度:O(1)。
void igraph_matrix_copy_to(const igraph_matrix_t *m, igraph_real_t *to);
矩阵按列复制,因为这是大多数程序和语言使用的格式。C 数组的大小应足够大;(当然)没有范围检查。
参数:
|
指向已初始化的矩阵对象的指针。 |
|
指向 C 数组的指针;复制数据的位置。 |
返回值:
错误代码。 |
时间复杂度:O(n),其中 n 是矩阵中元素的数量。
igraph_matrix_get_row
— 提取一行。igraph_matrix_get_col
— 选择一列。igraph_matrix_set_row
— 从向量设置一行。igraph_matrix_set_col
— 从向量设置一列。igraph_matrix_swap_rows
— 交换两行。igraph_matrix_swap_cols
— 交换两列。igraph_matrix_select_rows
— 选择矩阵的一些行。igraph_matrix_select_cols
— 选择矩阵的一些列。igraph_matrix_select_rows_cols
— 选择矩阵的一些行和列。
igraph_error_t igraph_matrix_get_row(const igraph_matrix_t *m, igraph_vector_t *res, igraph_integer_t index);
从矩阵中提取一行,并将其作为向量返回。
参数:
|
输入矩阵。 |
|
指向已初始化的向量的指针;如果需要,将调整其大小。 |
|
要选择的行的索引。 |
返回值:
错误代码。 |
时间复杂度:O(n),矩阵中的列数。
igraph_error_t igraph_matrix_get_col(const igraph_matrix_t *m, igraph_vector_t *res, igraph_integer_t index);
提取矩阵的一列,并将其作为向量返回。
参数:
|
输入矩阵。 |
|
结果将存储在此向量中。它应该被初始化,并且会根据需要调整大小。 |
|
要选择的列的索引。 |
返回值:
错误代码。 |
时间复杂度:O(n),矩阵中的行数。
igraph_error_t igraph_matrix_set_row(igraph_matrix_t *m, const igraph_vector_t *v, igraph_integer_t index);
用给定的向量设置一行的元素。其效果是将行 index
设置为具有向量 v
中的元素。向量的长度和矩阵中的列数必须匹配,否则会触发错误。
参数:
|
输入矩阵。 |
|
包含行的新元素的向量。 |
|
要设置的行的索引。 |
返回值:
错误代码。 |
时间复杂度:O(n),矩阵中的列数。
igraph_error_t igraph_matrix_set_col(igraph_matrix_t *m, const igraph_vector_t *v, igraph_integer_t index);
用给定的向量设置一列的元素。实际上,列 index
将被设置为向量 v
中的元素。向量的长度和矩阵中的行数必须匹配,否则会触发错误。
参数:
|
输入矩阵。 |
|
包含列的新元素的向量。 |
|
要设置的列的索引。 |
返回值:
错误代码。 |
时间复杂度:O(m),矩阵中的行数。
igraph_error_t igraph_matrix_swap_rows(igraph_matrix_t *m, igraph_integer_t i, igraph_integer_t j);
交换矩阵中的两行。
参数:
|
输入矩阵。 |
|
第一行的索引。 |
|
第二行的索引。 |
返回值:
错误代码。 |
时间复杂度:O(n),列数。
igraph_error_t igraph_matrix_swap_cols(igraph_matrix_t *m, igraph_integer_t i, igraph_integer_t j);
交换矩阵中的两列。
参数:
|
输入矩阵。 |
|
第一列的索引。 |
|
第二列的索引。 |
返回值:
错误代码。 |
时间复杂度:O(m),行数。
igraph_error_t igraph_matrix_select_rows(const igraph_matrix_t *m, igraph_matrix_t *res, const igraph_vector_int_t *rows);
此函数选择矩阵的一些行,并在新矩阵中返回它们。结果矩阵应该在调用函数之前被初始化。
参数:
|
输入矩阵。 |
|
结果矩阵。它应该被初始化,并且会根据需要调整大小。 |
|
向量;它包含要提取的行索引(从零开始)。请注意,不执行范围检查。 |
返回值:
错误代码。 |
时间复杂度:O(nm),n 是行数,m 是结果矩阵的列数。
igraph_error_t igraph_matrix_select_cols(const igraph_matrix_t *m, igraph_matrix_t *res, const igraph_vector_int_t *cols);
此函数选择矩阵的一些列,并在新矩阵中返回它们。结果矩阵应该在调用函数之前被初始化。
参数:
|
输入矩阵。 |
|
结果矩阵。它应该被初始化,并且会根据需要调整大小。 |
|
向量;它包含要提取的列索引(从零开始)。请注意,不执行范围检查。 |
返回值:
错误代码。 |
时间复杂度:O(nm),n 是行数,m 是结果矩阵的列数。
igraph_error_t igraph_matrix_select_rows_cols(const igraph_matrix_t *m, igraph_matrix_t *res, const igraph_vector_int_t *rows, const igraph_vector_int_t *cols);
此函数选择矩阵的一些行和列,并在新矩阵中返回它们。结果矩阵应该在调用函数之前被初始化。
参数:
|
输入矩阵。 |
|
结果矩阵。它应该被初始化,并且会根据需要调整大小。 |
|
向量;它包含要提取的行索引(从零开始)。请注意,不执行范围检查。 |
|
向量;它包含要提取的列索引(从零开始)。请注意,不执行范围检查。 |
返回值:
错误代码。 |
时间复杂度:O(nm),n 是行数,m 是结果矩阵的列数。
igraph_matrix_add_constant
— 将一个常数加到每个元素。igraph_matrix_scale
— 将矩阵的每个元素乘以一个常数。igraph_matrix_add
— 添加两个矩阵。igraph_matrix_sub
— 两个矩阵的差。igraph_matrix_mul_elements
— 元素矩阵乘法。igraph_matrix_div_elements
— 元素除法。igraph_matrix_sum
— 元素的和。igraph_matrix_prod
— 所有矩阵元素的乘积。igraph_matrix_rowsum
— 按行求和。igraph_matrix_colsum
— 按列求和。igraph_matrix_transpose
— 矩阵的转置。
void igraph_matrix_add_constant(igraph_matrix_t *m, igraph_real_t plus);
参数:
|
输入矩阵。 |
|
要添加的常量。 |
时间复杂度:O(mn),元素的数量。
void igraph_matrix_scale(igraph_matrix_t *m, igraph_real_t by);
参数:
|
矩阵。 |
|
常量。 |
在 0.2 版本中添加。
时间复杂度:O(n),矩阵中的元素数量。
igraph_error_t igraph_matrix_add(igraph_matrix_t *m1, const igraph_matrix_t *m2);
将 m2
加到 m1
,并将结果存储在 m1
中。矩阵的维度必须匹配。
参数:
|
第一个矩阵;结果将存储在这里。 |
|
第二个矩阵;它保持不变。 |
返回值:
错误代码。 |
时间复杂度:O(mn),元素的数量。
igraph_error_t igraph_matrix_sub(igraph_matrix_t *m1, const igraph_matrix_t *m2);
从 m1
中减去 m2
,并将结果存储在 m1
中。两个矩阵的维度必须匹配。
参数:
|
第一个矩阵;结果存储在这里。 |
|
第二个矩阵;它保持不变。 |
返回值:
错误代码。 |
时间复杂度:O(mn),元素的数量。
igraph_error_t igraph_matrix_mul_elements(igraph_matrix_t *m1, const igraph_matrix_t *m2);
将 m1
与 m2
逐元素相乘,并将结果存储在 m1
中。两个矩阵的维度必须匹配。
参数:
|
第一个矩阵;结果存储在这里。 |
|
第二个矩阵;它保持不变。 |
返回值:
错误代码。 |
时间复杂度:O(mn),元素的数量。
igraph_error_t igraph_matrix_div_elements(igraph_matrix_t *m1, const igraph_matrix_t *m2);
将 m1
除以 m2
逐元素相除,并将结果存储在 m1
中。两个矩阵的维度必须匹配。
参数:
|
被除数。结果存储在这里。 |
|
除数。它保持不变。 |
返回值:
错误代码。 |
时间复杂度:O(mn),元素的数量。
igraph_real_t igraph_matrix_sum(const igraph_matrix_t *m);
返回矩阵元素的和。
参数:
|
输入矩阵。 |
返回值:
元素的总和。 |
时间复杂度:O(mn),矩阵中元素的数量。
igraph_real_t igraph_matrix_prod(const igraph_matrix_t *m);
请注意,即使对于不太大的矩阵,此函数也容易导致溢出。不检查溢出。
参数:
|
输入矩阵。 |
返回值:
元素的乘积。 |
时间复杂度:O(mn),元素的数量。
igraph_error_t igraph_matrix_rowsum(const igraph_matrix_t *m, igraph_vector_t *res);
计算每行中元素的和。
参数:
|
输入矩阵。 |
|
指向已初始化的向量的指针;结果存储在这里。如果需要,将调整其大小。 |
返回值:
错误代码。 |
时间复杂度:O(mn),矩阵中元素的数量。
igraph_bool_t igraph_matrix_all_e(const igraph_matrix_t *lhs, const igraph_matrix_t *rhs);
检查两个矩阵的元素是否相等。对于包含浮点值的矩阵,请考虑使用 igraph_matrix_all_almost_e()
。
参数:
|
第一个矩阵。 |
|
第二个矩阵。 |
返回值:
如果 |
时间复杂度:O(nm),矩阵的大小。
igraph_bool_t igraph_matrix_all_almost_e(const igraph_matrix_t *lhs, const igraph_matrix_t *rhs, igraph_real_t eps);
检查两个矩阵的元素是否在相对容差范围内相等。
参数:
|
第一个矩阵。 |
|
第二个矩阵。 |
|
相对容差,详见 |
返回值:
如果两个矩阵几乎相等,则为 True;如果至少有一个不同的元素,或者矩阵的维度不同,则为 false。 |
igraph_bool_t igraph_matrix_all_l(const igraph_matrix_t *lhs, const igraph_matrix_t *rhs);
参数:
|
第一个矩阵。 |
|
第二个矩阵。 |
返回值:
如果 |
时间复杂度:O(nm),矩阵的大小。
igraph_bool_t igraph_matrix_all_g(const igraph_matrix_t *lhs, const igraph_matrix_t *rhs);
参数:
|
第一个矩阵。 |
|
第二个矩阵。 |
返回值:
如果 |
时间复杂度:O(nm),矩阵的大小。
igraph_bool_t igraph_matrix_all_le(const igraph_matrix_t *lhs, const igraph_matrix_t *rhs);
参数:
|
第一个矩阵。 |
|
第二个矩阵。 |
返回值:
如果 |
时间复杂度:O(nm),矩阵的大小。
igraph_bool_t igraph_matrix_all_ge(const igraph_matrix_t *lhs, const igraph_matrix_t *rhs);
参数:
|
第一个矩阵。 |
|
第二个矩阵。 |
返回值:
如果 |
时间复杂度:O(nm),矩阵的大小。
igraph_error_t igraph_matrix_zapsmall(igraph_matrix_t *m, igraph_real_t tol);
幅度小于给定绝对容差的矩阵元素将被替换为精确的零。默认容差对应于 igraph_real_t 的可表示数字的三分之二,即 DBL_EPSILON^(2/3)
,大约为 10^-10
。
参数:
|
要处理的矩阵,它将就地更改。 |
|
容差值。幅度小于此值的数字将被替换为零。传入零以使用默认容差。不能为负数。 |
返回值:
错误代码。 |
另请参阅:
|
igraph_real_t igraph_matrix_min(const igraph_matrix_t *m);
矩阵必须是非空的。
参数:
|
输入矩阵。 |
返回值:
|
时间复杂度:O(mn),矩阵中元素的数量。
igraph_real_t igraph_matrix_max(const igraph_matrix_t *m);
如果矩阵是空的,则返回一个任意数字。
参数:
|
矩阵对象。 |
返回值:
|
在 0.2 版本中添加。
时间复杂度:O(mn),矩阵中元素的数量。
void igraph_matrix_which_min( const igraph_matrix_t *m, igraph_integer_t *i, igraph_integer_t *j);
矩阵必须是非空的。如果最小元素不是唯一的,则返回第一个此类元素的索引。如果矩阵包含 NaN 值,则返回第一个 NaN 值的索引。
参数:
|
矩阵。 |
|
指向 igraph_integer_t 的指针。最小值的行索引存储在这里。 |
|
指向 igraph_integer_t 的指针。最小值的列索引存储在这里。 |
时间复杂度:O(mn),元素的数量。
void igraph_matrix_which_max( const igraph_matrix_t *m, igraph_integer_t *i, igraph_integer_t *j);
矩阵必须是非空的。如果最大元素不是唯一的,则返回第一个此类元素的索引。如果矩阵包含 NaN 值,则返回第一个 NaN 值的索引。
参数:
|
矩阵。 |
|
指向 igraph_integer_t 的指针。最大值的行索引存储在这里。 |
|
指向 igraph_integer_t 的指针。最大值的列索引存储在这里。 |
时间复杂度:O(mn),元素的数量。
void igraph_matrix_minmax(const igraph_matrix_t *m, igraph_real_t *min, igraph_real_t *max);
如果您想要矩阵的最小和最大元素,则很方便。矩阵只会被遍历一次。矩阵必须是非空的。如果一个矩阵包含至少一个 NaN,则 min
和 max
都将是 NaN。
参数:
|
输入矩阵。它必须包含至少一个元素。 |
|
指向基本类型变量的指针。最小值存储在这里。 |
|
指向基本类型变量的指针。最大值存储在这里。 |
时间复杂度:O(mn),元素的数量。
void igraph_matrix_which_minmax(const igraph_matrix_t *m, igraph_integer_t *imin, igraph_integer_t *jmin, igraph_integer_t *imax, igraph_integer_t *jmax);
如果您需要最小和最大元素的索引,则很方便。矩阵只会被遍历一次。矩阵必须是非空的。如果最小值或最大值不是唯一的,则分别返回第一个最小值或第一个最大值的索引。如果一个矩阵包含至少一个 NaN,则 which_min
和 which_max
都将指向第一个 NaN 值。
参数:
|
输入矩阵。 |
|
指向 igraph_integer_t 的指针,最小值的行索引存储在这里。 |
|
指向 igraph_integer_t 的指针,最小值的列索引存储在这里。 |
|
指向 igraph_integer_t 的指针,最大值的行索引存储在这里。 |
|
指向 igraph_integer_t 的指针,最大值的列索引存储在这里。 |
时间复杂度:O(mn),元素的数量。
igraph_matrix_empty
— 矩阵为空吗?igraph_matrix_isnull
— 检查是否为空矩阵。igraph_matrix_size
— 矩阵中的元素数。igraph_matrix_capacity
— 返回为矩阵分配的元素数。igraph_matrix_nrow
— 矩阵中的行数。igraph_matrix_ncol
— 矩阵中的列数。igraph_matrix_is_symmetric
— 矩阵是对称的吗?igraph_matrix_maxdifference
— 两个矩阵之间的最大绝对差。
igraph_bool_t igraph_matrix_empty(const igraph_matrix_t *m);
矩阵可能有零行或零列,甚至两者都有。此函数检查这些。
参数:
|
输入矩阵。 |
返回值:
布尔值,如果矩阵包含零元素,则为 |
时间复杂度:O(1)。
igraph_bool_t igraph_matrix_isnull(const igraph_matrix_t *m);
检查所有元素是否为零。
参数:
|
输入矩阵。 |
返回值:
布尔值,如果 |
时间复杂度:O(mn),元素的数量。
igraph_integer_t igraph_matrix_size(const igraph_matrix_t *m);
参数:
|
指向已初始化的矩阵对象的指针。 |
返回值:
矩阵的大小。 |
时间复杂度:O(1)。
igraph_integer_t igraph_matrix_capacity(const igraph_matrix_t *m);
请注意,这可能与矩阵的大小不同(如 igraph_matrix_size()
查询),并指定矩阵可以容纳多少个元素,而无需重新分配。
参数:
|
指向要查询的(先前初始化的)矩阵对象的指针。 |
返回值:
已分配容量。 |
另请参阅:
时间复杂度:O(1)。
igraph_integer_t igraph_matrix_nrow(const igraph_matrix_t *m);
参数:
|
指向已初始化的矩阵对象的指针。 |
返回值:
矩阵中的行数。 |
时间复杂度:O(1)。
igraph_integer_t igraph_matrix_ncol(const igraph_matrix_t *m);
参数:
|
指向已初始化的矩阵对象的指针。 |
返回值:
矩阵中的列数。 |
时间复杂度:O(1)。
igraph_bool_t igraph_matrix_is_symmetric(const igraph_matrix_t *m);
根据定义,非正方形矩阵不是对称的。
参数:
|
输入矩阵。 |
返回值:
布尔值,如果矩阵是正方形且对称的,则为 |
时间复杂度:O(mn),元素的数量。对于非正方形矩阵,为 O(1)。
igraph_bool_t igraph_matrix_contains(const igraph_matrix_t *m, igraph_real_t e);
在矩阵中搜索给定的元素。
参数:
|
输入矩阵。 |
|
要搜索的元素。 |
返回值:
布尔值,如果矩阵包含 |
时间复杂度:O(mn),元素的数量。
igraph_bool_t igraph_matrix_search(const igraph_matrix_t *m, igraph_integer_t from, igraph_real_t what, igraph_integer_t *pos, igraph_integer_t *row, igraph_integer_t *col);
在矩阵中搜索元素,并从给定位置开始搜索。搜索按列执行。
参数:
|
输入矩阵。 |
|
要从中搜索的位置,位置按列枚举。 |
|
要搜索的元素。 |
|
指向 igraph_integer_t 的指针。如果找到该元素,则将其设置为其首次出现的位置。 |
|
指向 igraph_integer_t 的指针。如果找到该元素,则将其设置为其行索引。 |
|
指向 igraph_integer_t 的指针。如果找到该元素,则将其设置为其列索引。 |
返回值:
布尔值,如果找到该元素,则为 |
时间复杂度:O(mn),元素的数量。
igraph_error_t igraph_matrix_resize(igraph_matrix_t *m, igraph_integer_t nrow, igraph_integer_t ncol);
此函数通过添加更多元素来调整矩阵大小。调整大小后,矩阵包含任意数据。也就是说,调用此函数后,您不能期望矩阵中的元素 (i,j) 与之前保持相同。
参数:
|
指向已初始化的矩阵对象的指针。 |
|
调整大小后的矩阵中的行数。 |
|
调整大小后的矩阵中的列数。 |
返回值:
错误代码。 |
时间复杂度:如果矩阵变小,则为 O(1);如果变大,通常为 O(n),其中 n 是调整大小后的矩阵中的元素数量。
void igraph_matrix_resize_min(igraph_matrix_t *m);
此函数尝试释放矩阵未使用的保留存储空间。
参数:
|
指向已初始化矩阵的指针。 |
另请参阅:
时间复杂度:依赖于操作系统,最坏情况下为 O(n)。
igraph_error_t igraph_matrix_add_rows(igraph_matrix_t *m, igraph_integer_t n);
参数:
|
矩阵对象。 |
|
要添加的行数。 |
返回值:
错误代码,如果操作没有足够的内存,则为 |
时间复杂度:与新的调整大小后的矩阵的元素数量呈线性关系。
igraph_error_t igraph_matrix_add_cols(igraph_matrix_t *m, igraph_integer_t n);
参数:
|
矩阵对象。 |
|
要添加的列数。 |
返回值:
错误代码,如果没有足够的内存来执行操作,则为 |
时间复杂度:与新的调整大小后的矩阵的元素数量呈线性关系。
igraph_matrix_complex_real
— 给出复矩阵的实部。igraph_matrix_complex_imag
— 给出复矩阵的虚部。igraph_matrix_complex_realimag
— 给出复矩阵的实部和虚部。igraph_matrix_complex_create
— 从实部和虚部创建复矩阵。igraph_matrix_complex_create_polar
— 从幅度和角度创建复矩阵。igraph_matrix_complex_all_almost_e
— 所有元素是否几乎相等?igraph_matrix_complex_zapsmall
— 将复矩阵的小元素替换为精确的零。
igraph_error_t igraph_matrix_complex_real(const igraph_matrix_complex_t *m, igraph_matrix_t *real);
参数:
|
指向复矩阵的指针。 |
|
指向已初始化矩阵的指针。结果将存储在此处。 |
返回值:
错误代码。 |
时间复杂度:O(n),其中 n 是矩阵中元素的数量。
igraph_error_t igraph_matrix_complex_imag(const igraph_matrix_complex_t *m, igraph_matrix_t *imag);
参数:
|
指向复矩阵的指针。 |
|
指向已初始化矩阵的指针。结果将存储在此处。 |
返回值:
错误代码。 |
时间复杂度:O(n),其中 n 是矩阵中元素的数量。
igraph_error_t igraph_matrix_complex_realimag(const igraph_matrix_complex_t *m, igraph_matrix_t *real, igraph_matrix_t *imag);
参数:
|
指向复矩阵的指针。 |
|
指向已初始化矩阵的指针。实部将存储在此处。 |
|
指向已初始化矩阵的指针。虚部将存储在此处。 |
返回值:
错误代码。 |
时间复杂度:O(n),其中 n 是矩阵中元素的数量。
igraph_error_t igraph_matrix_complex_create(igraph_matrix_complex_t *m, const igraph_matrix_t *real, const igraph_matrix_t *imag);
参数:
|
指向未初始化的复矩阵的指针。 |
|
指向复矩阵实部的指针。 |
|
指向复矩阵虚部的指针。 |
返回值:
错误代码。 |
时间复杂度:O(n),其中 n 是矩阵中元素的数量。
igraph_error_t igraph_matrix_complex_create_polar(igraph_matrix_complex_t *m, const igraph_matrix_t *r, const igraph_matrix_t *theta);
参数:
|
指向未初始化的复矩阵的指针。 |
|
指向包含幅度的实矩阵的指针。 |
|
指向包含参数(相位角)的实矩阵的指针。 |
返回值:
错误代码。 |
时间复杂度:O(n),其中 n 是矩阵中元素的数量。
igraph_bool_t igraph_matrix_complex_all_almost_e(igraph_matrix_complex_t *lhs, igraph_matrix_complex_t *rhs, igraph_real_t eps);
检查两个复矩阵的元素是否在相对容差范围内相等。
参数:
|
第一个矩阵。 |
|
第二个矩阵。 |
|
相对容差,有关详细信息,请参见 |
返回值:
如果两个矩阵几乎相等,则为 True;如果至少有一个不同的元素,或者矩阵的维度不同,则为 false。 |
igraph_error_t igraph_matrix_complex_zapsmall(igraph_matrix_complex_t *m, igraph_real_t tol);
与 igraph_matrix_zapsmall()
类似,小元素将被零替换。该操作分别在数字的实部和虚部上执行。这样,具有较大实部和微小虚部的复数将有效地转换为实数。默认容差对应于 igraph_real_t 的可表示数字的三分之二,即 DBL_EPSILON^(2/3)
,大约为 10^-10
。
参数:
|
要处理的矩阵,它将就地更改。 |
|
容差值。实部和虚部小于此幅度的部分将被替换为零。传入零以使用默认容差。不能为负。 |
返回值:
错误代码。 |
另请参阅:
igraph_error_t igraph_matrix_copy(igraph_matrix_t *to, const igraph_matrix_t *from);
自 0.10 版本起已弃用。请勿在新代码中使用此函数;请改用 igraph_matrix_init_copy()
。
igraph_real_t igraph_matrix_e(const igraph_matrix_t *m, igraph_integer_t row, igraph_integer_t col);
自 0.10.0 版本起已弃用。请勿在新代码中使用此函数;请改用 igraph_matrix_get()
。
igraph_real_t* igraph_matrix_e_ptr(const igraph_matrix_t *m, igraph_integer_t row, igraph_integer_t col);
自 0.10.0 版本起已弃用。请勿在新代码中使用此函数;请改用 igraph_matrix_get_ptr()
。
igraph_sparsemat_t
数据类型存储稀疏矩阵,即大多数元素为零的矩阵。
该数据类型本质上是对 Tim Davis 的 CXSparse 库中的某些函数的包装,请参阅 http://faculty.cse.tamu.edu/davis/suitesparse.html
矩阵可以两种格式存储:三元组和列压缩。三元组格式适用于稀疏矩阵初始化,因为很容易向其中添加新的(非零)元素。大多数计算都在列压缩格式的稀疏矩阵上完成,用户通过 igraph_sparsemat_compress()
将三元组矩阵转换为列压缩格式之后。
两种格式都是动态的,因为可以向其中添加新元素,这可能会导致分配更多内存。
行和列索引遵循 C 约定,并且从零开始。
示例 7.4. 文件 examples/simple/igraph_sparsemat.c
#include <igraph.h> int main(void) { igraph_sparsemat_t A, B, C, D; igraph_t G, H; igraph_vector_t vect; igraph_integer_t i; /* Create, compress, destroy */ igraph_sparsemat_init(&A, 100, 20, 50); igraph_sparsemat_compress(&A, &B); igraph_sparsemat_destroy(&B); igraph_sparsemat_destroy(&A); /* Convert a ring graph to a matrix, print it, compress, print again */ #define VC 10 igraph_sparsemat_init(&A, 1, 1, 0); igraph_ring(&G, VC, /*directed=*/ 0, /*mutual=*/ 0, /*circular=*/ 1); igraph_get_adjacency_sparse(&G, &A, IGRAPH_GET_ADJACENCY_BOTH, NULL, IGRAPH_LOOPS_ONCE); igraph_destroy(&G); igraph_sparsemat_compress(&A, &B); igraph_sparsemat_print(&A, stdout); igraph_sparsemat_print(&B, stdout); /* Basic query, nrow, ncol, type, is_triplet, is_cc */ if (igraph_sparsemat_nrow(&A) != VC || igraph_sparsemat_ncol(&A) != VC || igraph_sparsemat_nrow(&B) != VC || igraph_sparsemat_ncol(&B) != VC) { return 1; } if (!igraph_sparsemat_is_triplet(&A)) { return 2; } if (!igraph_sparsemat_is_cc(&B)) { return 3; } if (igraph_sparsemat_type(&A) != IGRAPH_SPARSEMAT_TRIPLET) { return 4; } if (igraph_sparsemat_type(&B) != IGRAPH_SPARSEMAT_CC) { return 5; } igraph_sparsemat_destroy(&A); igraph_sparsemat_destroy(&B); #undef VC printf("------------------------\n"); /* Create unit matrices */ igraph_sparsemat_init_eye(&A, /*n=*/ 5, /*nzmax=*/ 5, /*value=*/ 1.0, /*compress=*/ 0); igraph_sparsemat_init_eye(&B, /*n=*/ 5, /*nzmax=*/ 5, /*value=*/ 1.0, /*compress=*/ 1); igraph_sparsemat_print(&A, stdout); igraph_sparsemat_print(&B, stdout); igraph_sparsemat_destroy(&A); igraph_sparsemat_destroy(&B); printf("------------------------\n"); /* Create diagonal matrices */ igraph_vector_init(&vect, 5); for (i = 0; i < 5; i++) { VECTOR(vect)[i] = i; } igraph_sparsemat_init_diag(&A, /*nzmax=*/ 5, /*values=*/ &vect, /*compress=*/ 0); igraph_sparsemat_init_diag(&B, /*nzmax=*/ 5, /*values=*/ &vect, /*compress=*/ 1); igraph_vector_destroy(&vect); igraph_sparsemat_print(&A, stdout); igraph_sparsemat_print(&B, stdout); igraph_sparsemat_destroy(&A); igraph_sparsemat_destroy(&B); printf("------------------------\n"); /* Transpose matrices */ igraph_sparsemat_init(&A, 1, 1, 0); igraph_kary_tree(&G, 10, /*children=*/ 2, IGRAPH_TREE_OUT); igraph_get_adjacency_sparse(&G, &A, IGRAPH_GET_ADJACENCY_BOTH, NULL, IGRAPH_LOOPS_ONCE); igraph_destroy(&G); igraph_sparsemat_compress(&A, &B); igraph_sparsemat_print(&B, stdout); igraph_sparsemat_transpose(&B, &C); igraph_sparsemat_print(&C, stdout); igraph_sparsemat_destroy(&A); igraph_sparsemat_destroy(&B); igraph_sparsemat_destroy(&C); printf("------------------------\n"); /* Add duplicate elements */ igraph_sparsemat_init(&A, 10, 10, /*nzmax=*/ 20); for (i = 1; i < 10; i++) { igraph_sparsemat_entry(&A, 0, i, 1.0); } for (i = 1; i < 10; i++) { igraph_sparsemat_entry(&A, 0, i, 1.0); } igraph_sparsemat_print(&A, stdout); igraph_sparsemat_compress(&A, &B); igraph_sparsemat_print(&B, stdout); igraph_sparsemat_dupl(&B); igraph_sparsemat_print(&B, stdout); igraph_sparsemat_destroy(&A); igraph_sparsemat_destroy(&B); printf("------------------------\n"); /* Drop zero elements */ igraph_sparsemat_init(&A, 10, 10, /*nzmax=*/ 20); igraph_sparsemat_entry(&A, 7, 3, 0.0); for (i = 1; i < 10; i++) { igraph_sparsemat_entry(&A, 0, i, 1.0); igraph_sparsemat_entry(&A, 0, i, 0.0); } igraph_sparsemat_entry(&A, 0, 0, 0.0); igraph_sparsemat_print(&A, stdout); igraph_sparsemat_compress(&A, &B); igraph_sparsemat_print(&B, stdout); igraph_sparsemat_dropzeros(&B); igraph_sparsemat_print(&B, stdout); igraph_sparsemat_destroy(&A); igraph_sparsemat_destroy(&B); printf("------------------------\n"); /* Add two matrices */ igraph_sparsemat_init(&A, 1, 1, 0); igraph_sparsemat_init(&B, 1, 1, 0); igraph_star(&G, 10, IGRAPH_STAR_OUT, /*center=*/ 0); igraph_ring(&H, 10, /*directed=*/ 0, /*mutual=*/ 0, /*circular=*/ 1); igraph_get_adjacency_sparse(&G, &A, IGRAPH_GET_ADJACENCY_BOTH, NULL, IGRAPH_LOOPS_ONCE); igraph_get_adjacency_sparse(&H, &B, IGRAPH_GET_ADJACENCY_BOTH, NULL, IGRAPH_LOOPS_ONCE); igraph_destroy(&G); igraph_destroy(&H); igraph_sparsemat_compress(&A, &C); igraph_sparsemat_compress(&B, &D); igraph_sparsemat_destroy(&A); igraph_sparsemat_destroy(&B); igraph_sparsemat_add(&C, &D, /*alpha=*/ 1.0, /*beta=*/ 2.0, &A); igraph_sparsemat_destroy(&C); igraph_sparsemat_destroy(&D); igraph_sparsemat_print(&A, stdout); igraph_sparsemat_destroy(&A); return 0; }
示例 7.5. 文件 examples/simple/igraph_sparsemat3.c
#include <igraph.h> void permute(const igraph_matrix_t *M, const igraph_vector_int_t *p, const igraph_vector_int_t *q, igraph_matrix_t *res) { igraph_integer_t nrow = igraph_vector_int_size(p); igraph_integer_t ncol = igraph_vector_int_size(q); igraph_integer_t i, j; igraph_matrix_resize(res, nrow, ncol); for (i = 0; i < nrow; i++) { for (j = 0; j < ncol; j++) { igraph_integer_t ii = VECTOR(*p)[i]; igraph_integer_t jj = VECTOR(*q)[j]; MATRIX(*res, i, j) = MATRIX(*M, ii, jj); } } } void permute_rows(const igraph_matrix_t *M, const igraph_vector_int_t *p, igraph_matrix_t *res) { igraph_integer_t nrow = igraph_vector_int_size(p); igraph_integer_t ncol = igraph_matrix_ncol(M); igraph_integer_t i, j; igraph_matrix_resize(res, nrow, ncol); for (i = 0; i < nrow; i++) { for (j = 0; j < ncol; j++) { igraph_integer_t ii = VECTOR(*p)[i]; MATRIX(*res, i, j) = MATRIX(*M, ii, j); } } } void permute_cols(const igraph_matrix_t *M, const igraph_vector_int_t *q, igraph_matrix_t *res) { igraph_integer_t nrow = igraph_matrix_nrow(M); igraph_integer_t ncol = igraph_vector_int_size(q); igraph_integer_t i, j; igraph_matrix_resize(res, nrow, ncol); for (i = 0; i < nrow; i++) { for (j = 0; j < ncol; j++) { igraph_integer_t jj = VECTOR(*q)[j]; MATRIX(*res, i, j) = MATRIX(*M, i, jj); } } } void random_permutation(igraph_vector_int_t *vec) { /* We just do size(vec) * 2 swaps */ igraph_integer_t one, two, i, n = igraph_vector_int_size(vec); igraph_integer_t tmp; for (i = 0; i < 2 * n; i++) { one = RNG_INTEGER(0, n - 1); two = RNG_INTEGER(0, n - 1); tmp = VECTOR(*vec)[one]; VECTOR(*vec)[one] = VECTOR(*vec)[two]; VECTOR(*vec)[two] = tmp; } } igraph_bool_t check_same(const igraph_sparsemat_t *A, const igraph_matrix_t *M) { igraph_matrix_t A_dense; igraph_bool_t result; igraph_matrix_init(&A_dense, 1, 1); igraph_sparsemat_as_matrix(&A_dense, A); result = igraph_matrix_all_e(&A_dense, M); igraph_matrix_destroy(&A_dense); return result; } int main(void) { igraph_sparsemat_t A, B; igraph_matrix_t M, N; igraph_vector_int_t p, q; igraph_integer_t i; RNG_BEGIN(); /* Permutation of a matrix */ #define NROW 10 #define NCOL 5 #define EDGES NROW*NCOL/3 igraph_matrix_init(&M, NROW, NCOL); igraph_sparsemat_init(&A, NROW, NCOL, EDGES); for (i = 0; i < EDGES; i++) { igraph_integer_t r = RNG_INTEGER(0, NROW - 1); igraph_integer_t c = RNG_INTEGER(0, NCOL - 1); igraph_real_t value = RNG_INTEGER(1, 5); MATRIX(M, r, c) = MATRIX(M, r, c) + value; igraph_sparsemat_entry(&A, r, c, value); } igraph_sparsemat_compress(&A, &B); igraph_sparsemat_destroy(&A); igraph_vector_int_init_range(&p, 0, NROW); igraph_vector_int_init_range(&q, 0, NCOL); /* Identity */ igraph_matrix_init(&N, 0, 0); permute(&M, &p, &q, &N); igraph_sparsemat_permute(&B, &p, &q, &A); igraph_sparsemat_dupl(&A); if (! check_same(&A, &N)) { return 1; } /* Random permutation */ random_permutation(&p); random_permutation(&q); permute(&M, &p, &q, &N); igraph_sparsemat_destroy(&A); igraph_sparsemat_permute(&B, &p, &q, &A); igraph_sparsemat_dupl(&A); if (! check_same(&A, &N)) { return 2; } igraph_vector_int_destroy(&p); igraph_vector_int_destroy(&q); igraph_sparsemat_destroy(&A); igraph_sparsemat_destroy(&B); igraph_matrix_destroy(&M); igraph_matrix_destroy(&N); #undef NROW #undef NCOL #undef EDGES /* Indexing */ #define NROW 10 #define NCOL 5 #define EDGES NROW*NCOL/3 #define I_NROW 6 #define I_NCOL 3 igraph_matrix_init(&M, NROW, NCOL); igraph_sparsemat_init(&A, NROW, NCOL, EDGES); for (i = 0; i < EDGES; i++) { igraph_integer_t r = RNG_INTEGER(0, NROW - 1); igraph_integer_t c = RNG_INTEGER(0, NCOL - 1); igraph_real_t value = RNG_INTEGER(1, 5); MATRIX(M, r, c) = MATRIX(M, r, c) + value; igraph_sparsemat_entry(&A, r, c, value); } igraph_sparsemat_compress(&A, &B); igraph_sparsemat_destroy(&A); igraph_vector_int_init(&p, I_NROW); igraph_vector_int_init(&q, I_NCOL); for (i = 0; i < I_NROW; i++) { VECTOR(p)[i] = RNG_INTEGER(0, I_NROW - 1); } for (i = 0; i < I_NCOL; i++) { VECTOR(p)[i] = RNG_INTEGER(0, I_NCOL - 1); } igraph_matrix_init(&N, 0, 0); permute(&M, &p, &q, &N); igraph_sparsemat_index(&B, &p, &q, &A, 0); if (! check_same(&A, &N)) { return 3; } igraph_sparsemat_destroy(&A); /* Getting single elements with index() */ igraph_vector_int_resize(&p, 1); igraph_vector_int_resize(&q, 1); for (i = 0; i < 100; i++) { igraph_real_t value; VECTOR(p)[0] = RNG_INTEGER(0, NROW - 1); VECTOR(q)[0] = RNG_INTEGER(0, NCOL - 1); igraph_sparsemat_index(&B, &p, &q, /*res=*/ 0, &value); if (value != MATRIX(M, VECTOR(p)[0], VECTOR(q)[0])) { return 4; } } /* Getting single elements with get() */ igraph_vector_int_resize(&p, 1); igraph_vector_int_resize(&q, 1); for (i = 0; i < 100; i++) { igraph_integer_t row = RNG_INTEGER(0, NROW - 1); igraph_integer_t col = RNG_INTEGER(0, NCOL - 1); if (igraph_sparsemat_get(&B, row, col) != MATRIX(M, row, col)) { return 4; } } /* Getting submatrices with index() */ for (i = 0; i < 100; i++) { igraph_real_t value; VECTOR(p)[0] = RNG_INTEGER(0, NROW - 1); VECTOR(q)[0] = RNG_INTEGER(0, NCOL - 1); igraph_sparsemat_index(&B, &p, &q, /*res=*/ &A, &value); igraph_sparsemat_destroy(&A); if (value != MATRIX(M, VECTOR(p)[0], VECTOR(q)[0])) { return 4; } } igraph_vector_int_destroy(&p); igraph_vector_int_destroy(&q); igraph_sparsemat_destroy(&B); igraph_matrix_destroy(&M); igraph_matrix_destroy(&N); /* Indexing only the rows or the columns */ igraph_matrix_init(&M, NROW, NCOL); igraph_sparsemat_init(&A, NROW, NCOL, EDGES); for (i = 0; i < EDGES; i++) { igraph_integer_t r = RNG_INTEGER(0, NROW - 1); igraph_integer_t c = RNG_INTEGER(0, NCOL - 1); igraph_real_t value = RNG_INTEGER(1, 5); MATRIX(M, r, c) = MATRIX(M, r, c) + value; igraph_sparsemat_entry(&A, r, c, value); } igraph_sparsemat_compress(&A, &B); igraph_sparsemat_destroy(&A); igraph_vector_int_init(&p, I_NROW); igraph_vector_int_init(&q, I_NCOL); for (i = 0; i < I_NROW; i++) { VECTOR(p)[i] = RNG_INTEGER(0, I_NROW - 1); } for (i = 0; i < I_NCOL; i++) { VECTOR(p)[i] = RNG_INTEGER(0, I_NCOL - 1); } igraph_matrix_init(&N, 0, 0); permute_rows(&M, &p, &N); igraph_sparsemat_index(&B, &p, 0, &A, 0); if (! check_same(&A, &N)) { return 5; } permute_cols(&M, &q, &N); igraph_sparsemat_destroy(&A); igraph_sparsemat_index(&B, 0, &q, &A, 0); if (! check_same(&A, &N)) { return 6; } igraph_sparsemat_destroy(&A); igraph_sparsemat_destroy(&B); igraph_vector_int_destroy(&p); igraph_vector_int_destroy(&q); igraph_matrix_destroy(&M); igraph_matrix_destroy(&N); RNG_END(); return 0; }
示例 7.6. 文件 examples/simple/igraph_sparsemat4.c
#include <igraph.h> igraph_bool_t check_solution(const igraph_sparsemat_t *A, const igraph_vector_t *x, const igraph_vector_t *b) { igraph_vector_t res; igraph_real_t min, max; igraph_bool_t success; igraph_sparsemat_iterator_t it; igraph_vector_init_copy(&res, b); igraph_sparsemat_iterator_init(&it, (igraph_sparsemat_t*) A); while (!igraph_sparsemat_iterator_end(&it)) { igraph_integer_t row = igraph_sparsemat_iterator_row(&it); igraph_integer_t col = igraph_sparsemat_iterator_col(&it); igraph_real_t value = igraph_sparsemat_iterator_get(&it); VECTOR(res)[row] -= VECTOR(*x)[col] * value; igraph_sparsemat_iterator_next(&it); } igraph_vector_minmax(&res, &min, &max); igraph_vector_destroy(&res); success = fabs(min) < 1e-12 && fabs(max) < 1e-12; if (!success) { printf("Incorrect solution.\n\n"); printf("A =\n"); igraph_sparsemat_print(A, stdout); printf("\n"); printf("x =\n"); igraph_vector_print(x); printf("\n"); printf("b =\n"); igraph_vector_print(b); printf("\n"); printf("difference between A*x and b =\n"); igraph_vector_print(&res); printf("\n\n"); } return success; } int main(void) { igraph_sparsemat_t A, B, C; igraph_vector_t b, x; igraph_integer_t i; RNG_BEGIN(); /* lsolve */ #define DIM 10 #define EDGES (DIM*DIM/6) igraph_sparsemat_init(&A, DIM, DIM, EDGES + DIM); for (i = 0; i < DIM; i++) { igraph_sparsemat_entry(&A, i, i, RNG_INTEGER(1, 3)); } for (i = 0; i < EDGES; i++) { igraph_integer_t r = RNG_INTEGER(0, DIM - 1); igraph_integer_t c = RNG_INTEGER(0, r); igraph_real_t value = RNG_INTEGER(1, 5); igraph_sparsemat_entry(&A, r, c, value); } igraph_sparsemat_compress(&A, &B); igraph_sparsemat_destroy(&A); igraph_sparsemat_dupl(&B); igraph_vector_init(&b, DIM); for (i = 0; i < DIM; i++) { VECTOR(b)[i] = RNG_INTEGER(1, 10); } igraph_vector_init(&x, DIM); igraph_sparsemat_lsolve(&B, &b, &x); if (! check_solution(&B, &x, &b)) { return 1; } igraph_vector_destroy(&b); igraph_vector_destroy(&x); igraph_sparsemat_destroy(&B); #undef DIM #undef EDGES /* ltsolve */ #define DIM 10 #define EDGES (DIM*DIM/6) igraph_sparsemat_init(&A, DIM, DIM, EDGES + DIM); for (i = 0; i < DIM; i++) { igraph_sparsemat_entry(&A, i, i, RNG_INTEGER(1, 3)); } for (i = 0; i < EDGES; i++) { igraph_integer_t r = RNG_INTEGER(0, DIM - 1); igraph_integer_t c = RNG_INTEGER(0, r); igraph_real_t value = RNG_INTEGER(1, 5); igraph_sparsemat_entry(&A, r, c, value); } igraph_sparsemat_compress(&A, &B); igraph_sparsemat_destroy(&A); igraph_sparsemat_dupl(&B); igraph_vector_init(&b, DIM); for (i = 0; i < DIM; i++) { VECTOR(b)[i] = RNG_INTEGER(1, 10); } igraph_vector_init(&x, DIM); igraph_sparsemat_ltsolve(&B, &b, &x); igraph_sparsemat_transpose(&B, &A); if (! check_solution(&A, &x, &b)) { return 2; } igraph_vector_destroy(&b); igraph_vector_destroy(&x); igraph_sparsemat_destroy(&B); igraph_sparsemat_destroy(&A); #undef DIM #undef EDGES /* usolve */ #define DIM 10 #define EDGES (DIM*DIM/6) igraph_sparsemat_init(&A, DIM, DIM, EDGES + DIM); for (i = 0; i < DIM; i++) { igraph_sparsemat_entry(&A, i, i, RNG_INTEGER(1, 3)); } for (i = 0; i < EDGES; i++) { igraph_integer_t r = RNG_INTEGER(0, DIM - 1); igraph_integer_t c = RNG_INTEGER(0, r); igraph_real_t value = RNG_INTEGER(1, 5); igraph_sparsemat_entry(&A, r, c, value); } igraph_sparsemat_compress(&A, &B); igraph_sparsemat_destroy(&A); igraph_sparsemat_dupl(&B); igraph_sparsemat_transpose(&B, &A); igraph_vector_init(&b, DIM); for (i = 0; i < DIM; i++) { VECTOR(b)[i] = RNG_INTEGER(1, 10); } igraph_vector_init(&x, DIM); igraph_sparsemat_usolve(&A, &b, &x); if (! check_solution(&A, &x, &b)) { return 3; } igraph_vector_destroy(&b); igraph_vector_destroy(&x); igraph_sparsemat_destroy(&B); igraph_sparsemat_destroy(&A); #undef DIM #undef EDGES /* utsolve */ #define DIM 10 #define EDGES (DIM*DIM/6) igraph_sparsemat_init(&A, DIM, DIM, EDGES + DIM); for (i = 0; i < DIM; i++) { igraph_sparsemat_entry(&A, i, i, RNG_INTEGER(1, 3)); } for (i = 0; i < EDGES; i++) { igraph_integer_t r = RNG_INTEGER(0, DIM - 1); igraph_integer_t c = RNG_INTEGER(0, r); igraph_real_t value = RNG_INTEGER(1, 5); igraph_sparsemat_entry(&A, r, c, value); } igraph_sparsemat_compress(&A, &B); igraph_sparsemat_destroy(&A); igraph_sparsemat_dupl(&B); igraph_sparsemat_transpose(&B, &A); igraph_sparsemat_destroy(&B); igraph_vector_init(&b, DIM); for (i = 0; i < DIM; i++) { VECTOR(b)[i] = RNG_INTEGER(1, 10); } igraph_vector_init(&x, DIM); igraph_sparsemat_utsolve(&A, &b, &x); igraph_sparsemat_transpose(&A, &B); if (! check_solution(&B, &x, &b)) { return 4; } igraph_vector_destroy(&b); igraph_vector_destroy(&x); igraph_sparsemat_destroy(&B); igraph_sparsemat_destroy(&A); #undef DIM #undef EDGES /* cholsol */ /* We need a positive definite matrix, so we create a full-rank matrix first and then calculate A'A, which will be positive definite. */ #define DIM 10 #define EDGES (DIM*DIM/6) igraph_sparsemat_init(&A, DIM, DIM, EDGES + DIM); for (i = 0; i < DIM; i++) { igraph_sparsemat_entry(&A, i, i, RNG_INTEGER(1, 3)); } for (i = 0; i < EDGES; i++) { igraph_integer_t from = RNG_INTEGER(0, DIM - 1); igraph_integer_t to = RNG_INTEGER(0, DIM - 1); igraph_real_t value = RNG_INTEGER(1, 5); igraph_sparsemat_entry(&A, from, to, value); } igraph_sparsemat_compress(&A, &B); igraph_sparsemat_destroy(&A); igraph_sparsemat_dupl(&B); igraph_sparsemat_transpose(&B, &A); igraph_sparsemat_multiply(&A, &B, &C); igraph_sparsemat_destroy(&A); igraph_sparsemat_destroy(&B); igraph_vector_init(&b, DIM); for (i = 0; i < DIM; i++) { VECTOR(b)[i] = RNG_INTEGER(1, 10); } igraph_vector_init(&x, DIM); igraph_sparsemat_cholsol(&C, &b, &x, /*order=*/ 0); if (! check_solution(&C, &x, &b)) { return 5; } igraph_vector_destroy(&b); igraph_vector_destroy(&x); igraph_sparsemat_destroy(&C); #undef DIM #undef EDGES /* lusol */ #define DIM 10 #define EDGES (DIM*DIM/4) igraph_sparsemat_init(&A, DIM, DIM, EDGES + DIM); for (i = 0; i < DIM; i++) { igraph_sparsemat_entry(&A, i, i, RNG_INTEGER(1, 3)); } for (i = 0; i < EDGES; i++) { igraph_integer_t from = RNG_INTEGER(0, DIM - 1); igraph_integer_t to = RNG_INTEGER(0, DIM - 1); igraph_real_t value = RNG_INTEGER(1, 5); igraph_sparsemat_entry(&A, from, to, value); } igraph_sparsemat_compress(&A, &B); igraph_sparsemat_destroy(&A); igraph_sparsemat_dupl(&B); igraph_vector_init(&b, DIM); for (i = 0; i < DIM; i++) { VECTOR(b)[i] = RNG_INTEGER(1, 10); } igraph_vector_init(&x, DIM); igraph_sparsemat_lusol(&B, &b, &x, /*order=*/ 0, /*tol=*/ 1e-10); if (! check_solution(&B, &x, &b)) { return 6; } igraph_vector_destroy(&b); igraph_vector_destroy(&x); igraph_sparsemat_destroy(&B); #undef DIM #undef EDGES RNG_END(); return 0; }
示例 7.7. 文件 examples/simple/igraph_sparsemat6.c
#include <igraph.h> int main(void) { igraph_matrix_t mat, mat2, mat3; igraph_sparsemat_t spmat, spmat2; igraph_rng_seed(igraph_rng_default(), 42); #define NROW 10 #define NCOL 7 #define NUM_NONZEROS 15 igraph_matrix_init(&mat, NROW, NCOL); for (igraph_integer_t i = 0; i < NUM_NONZEROS; i++) { igraph_integer_t r = igraph_rng_get_integer(igraph_rng_default(), 0, NROW - 1); igraph_integer_t c = igraph_rng_get_integer(igraph_rng_default(), 0, NCOL - 1); igraph_real_t val = igraph_rng_get_integer(igraph_rng_default(), 1, 10); MATRIX(mat, r, c) = val; } igraph_matrix_as_sparsemat(&spmat, &mat, /*tol=*/ 1e-14); igraph_matrix_init(&mat2, 0, 0); igraph_sparsemat_as_matrix(&mat2, &spmat); if (!igraph_matrix_all_e(&mat, &mat2)) { return 1; } igraph_sparsemat_compress(&spmat, &spmat2); igraph_matrix_init(&mat3, 0, 0); igraph_sparsemat_as_matrix(&mat3, &spmat2); if (!igraph_matrix_all_e(&mat, &mat3)) { return 2; } igraph_matrix_destroy(&mat); igraph_matrix_destroy(&mat2); igraph_matrix_destroy(&mat3); igraph_sparsemat_destroy(&spmat); igraph_sparsemat_destroy(&spmat2); return 0; }
示例 7.8. 文件 examples/simple/igraph_sparsemat7.c
#include <igraph.h> #define DIM1 10 #define DIM2 5 #define RANDINT(a) (igraph_rng_get_integer(igraph_rng_default(), 0, (a))) int main(void) { igraph_matrix_t mat; igraph_sparsemat_t spmat, spmat2; igraph_real_t m1, m2; igraph_rng_seed(igraph_rng_default(), 42); igraph_sparsemat_init(&spmat, DIM1, DIM2, 20); igraph_sparsemat_entry(&spmat, 1, 2, -1.0); igraph_sparsemat_entry(&spmat, 3, 2, 10.0); for (int i = 0; i < 10; i++) { igraph_sparsemat_entry(&spmat, RANDINT(DIM1 - 1), RANDINT(DIM2 - 1), 1.0); } igraph_sparsemat_entry(&spmat, 1, 2, -1.0); igraph_sparsemat_entry(&spmat, 3, 2, 10.0); igraph_sparsemat_compress(&spmat, &spmat2); igraph_matrix_init(&mat, 0, 0); igraph_sparsemat_as_matrix(&mat, &spmat2); m1 = igraph_sparsemat_min(&spmat2); m2 = igraph_matrix_min(&mat); if (m1 != m2) { printf("%f %f\n", m1, m2); return 1; } m1 = igraph_sparsemat_max(&spmat2); m2 = igraph_matrix_max(&mat); if (m1 != m2) { printf("%f %f\n", m1, m2); return 2; } igraph_sparsemat_minmax(&spmat2, &m1, &m2); if (m1 != igraph_matrix_min(&mat)) { return 3; } if (m2 != igraph_matrix_max(&mat)) { return 4; } igraph_matrix_destroy(&mat); igraph_sparsemat_destroy(&spmat); igraph_sparsemat_destroy(&spmat2); return 0; }
示例 7.9. 文件 examples/simple/igraph_sparsemat8.c
#include <igraph.h> #define DIM1 10 #define DIM2 5 #define INT(a) (igraph_rng_get_integer(igraph_rng_default(), 0, (a))) int main(void) { igraph_matrix_t mat, mat2; igraph_sparsemat_t spmat, spmat2; igraph_integer_t i, j, nz1, nz2; igraph_vector_t sums1, sums2; igraph_rng_seed(igraph_rng_default(), 42); /* COPY */ igraph_sparsemat_init(&spmat, DIM1, DIM2, 20); for (i = 0; i < 10; i++) { igraph_sparsemat_entry(&spmat, INT(DIM1 - 1), INT(DIM2 - 1), 1.0); } igraph_sparsemat_init_copy(&spmat2, &spmat); igraph_matrix_init(&mat, 0, 0); igraph_sparsemat_as_matrix(&mat, &spmat); igraph_matrix_init(&mat2, 0, 0); igraph_sparsemat_as_matrix(&mat2, &spmat2); if (!igraph_matrix_all_e(&mat, &mat2)) { return 1; } igraph_matrix_destroy(&mat2); igraph_sparsemat_destroy(&spmat2); igraph_sparsemat_compress(&spmat, &spmat2); igraph_sparsemat_destroy(&spmat); igraph_sparsemat_init_copy(&spmat, &spmat2); igraph_matrix_init(&mat2, 0, 0); igraph_sparsemat_as_matrix(&mat2, &spmat); if (!igraph_matrix_all_e(&mat, &mat2)) { return 2; } igraph_sparsemat_destroy(&spmat); igraph_sparsemat_destroy(&spmat2); igraph_matrix_destroy(&mat); igraph_matrix_destroy(&mat2); /* COLSUMS, ROWSUMS */ igraph_sparsemat_init(&spmat, DIM1, DIM2, 20); for (i = 0; i < 10; i++) { igraph_sparsemat_entry(&spmat, INT(DIM1 - 1), INT(DIM2 - 1), 1.0); } igraph_sparsemat_compress(&spmat, &spmat2); igraph_matrix_init(&mat, 0, 0); igraph_sparsemat_as_matrix(&mat, &spmat); igraph_vector_init(&sums1, 0); igraph_vector_init(&sums2, 0); igraph_sparsemat_colsums(&spmat, &sums1); igraph_matrix_colsum(&mat, &sums2); if (!igraph_vector_all_e(&sums1, &sums2)) { return 3; } igraph_sparsemat_colsums(&spmat2, &sums1); if (!igraph_vector_all_e(&sums1, &sums2)) { return 4; } igraph_sparsemat_rowsums(&spmat, &sums1); igraph_matrix_rowsum(&mat, &sums2); if (!igraph_vector_all_e(&sums1, &sums2)) { return 5; } igraph_sparsemat_rowsums(&spmat2, &sums1); if (!igraph_vector_all_e(&sums1, &sums2)) { return 6; } igraph_matrix_destroy(&mat); igraph_sparsemat_destroy(&spmat); igraph_sparsemat_destroy(&spmat2); igraph_vector_destroy(&sums1); igraph_vector_destroy(&sums2); /* COUNT_NONZERO, COUNT_NONZEROTOL */ igraph_sparsemat_init(&spmat, DIM1, DIM2, 20); igraph_sparsemat_entry(&spmat, 1, 2, 1.0); igraph_sparsemat_entry(&spmat, 1, 2, 1.0); igraph_sparsemat_entry(&spmat, 1, 3, 1e-12); for (i = 0; i < 10; i++) { igraph_sparsemat_entry(&spmat, INT(DIM1 - 1), INT(DIM2 - 1), 1.0); } igraph_sparsemat_compress(&spmat, &spmat2); igraph_matrix_init(&mat, 0, 0); igraph_sparsemat_as_matrix(&mat, &spmat2); nz1 = igraph_sparsemat_count_nonzero(&spmat2); for (nz2 = 0, i = 0; i < igraph_matrix_nrow(&mat); i++) { for (j = 0; j < igraph_matrix_ncol(&mat); j++) { if (MATRIX(mat, i, j) != 0) { nz2++; } } } if (nz1 != nz2) { printf("%" IGRAPH_PRId " %" IGRAPH_PRId "\n", nz1, nz2); return 7; } nz1 = igraph_sparsemat_count_nonzerotol(&spmat2, 1e-10); for (nz2 = 0, i = 0; i < igraph_matrix_nrow(&mat); i++) { for (j = 0; j < igraph_matrix_ncol(&mat); j++) { if (fabs(MATRIX(mat, i, j)) >= 1e-10) { nz2++; } } } if (nz1 != nz2) { printf("%" IGRAPH_PRId " %" IGRAPH_PRId "\n", nz1, nz2); return 8; } igraph_matrix_destroy(&mat); igraph_sparsemat_destroy(&spmat); igraph_sparsemat_destroy(&spmat2); /* SCALE */ igraph_sparsemat_init(&spmat, DIM1, DIM2, 20); for (i = 0; i < 10; i++) { igraph_sparsemat_entry(&spmat, INT(DIM1 - 1), INT(DIM2 - 1), 1.0); } igraph_sparsemat_compress(&spmat, &spmat2); igraph_sparsemat_scale(&spmat, 2.0); igraph_sparsemat_scale(&spmat2, 2.0); igraph_matrix_init(&mat, 0, 0); igraph_sparsemat_as_matrix(&mat, &spmat); igraph_matrix_init(&mat2, 0, 0); igraph_sparsemat_as_matrix(&mat2, &spmat2); igraph_matrix_scale(&mat, 1.0 / 2.0); igraph_matrix_scale(&mat2, 1.0 / 2.0); if (!igraph_matrix_all_e(&mat, &mat2)) { return 9; } igraph_matrix_destroy(&mat); igraph_matrix_destroy(&mat2); igraph_sparsemat_destroy(&spmat); igraph_sparsemat_destroy(&spmat2); /* ADDROWS, ADDCOLS */ igraph_sparsemat_init(&spmat, DIM1, DIM2, 20); for (i = 0; i < 10; i++) { igraph_sparsemat_entry(&spmat, INT(DIM1 - 1), INT(DIM2 - 1), 1.0); } igraph_sparsemat_compress(&spmat, &spmat2); igraph_sparsemat_add_rows(&spmat, 3); igraph_sparsemat_add_cols(&spmat, 2); igraph_sparsemat_add_rows(&spmat2, 3); igraph_sparsemat_add_cols(&spmat2, 2); igraph_matrix_init(&mat, 0, 0); igraph_sparsemat_as_matrix(&mat, &spmat); igraph_matrix_init(&mat2, 0, 0); igraph_sparsemat_as_matrix(&mat2, &spmat2); if (!igraph_matrix_all_e(&mat, &mat2)) { return 10; } igraph_matrix_destroy(&mat); igraph_matrix_destroy(&mat2); igraph_sparsemat_destroy(&spmat); igraph_sparsemat_destroy(&spmat2); return 0; }
igraph_sparsemat_init
— 初始化三元组格式的稀疏矩阵。igraph_sparsemat_init_copy
— 复制稀疏矩阵。igraph_sparsemat_init_diag
— 创建稀疏对角矩阵。igraph_sparsemat_init_eye
— 创建稀疏单位矩阵。igraph_sparsemat_realloc
— 为稀疏矩阵分配更多(或更少)内存。igraph_sparsemat_destroy
— 释放稀疏矩阵使用的内存。igraph_sparsemat_view
— 初始化稀疏矩阵并设置所有参数。
igraph_error_t igraph_sparsemat_init(igraph_sparsemat_t *A, igraph_integer_t rows, igraph_integer_t cols, igraph_integer_t nzmax);
这是创建稀疏矩阵的最常见方法,以及 igraph_sparsemat_entry()
函数,该函数可用于逐个添加非零元素。完成后,用户可以调用 igraph_sparsemat_compress()
将矩阵转换为列压缩格式,以便对其进行计算。
用户必须在矩阵上调用 igraph_sparsemat_destroy()
以释放内存,一旦不再需要该矩阵。
参数:
|
指向尚未初始化的稀疏矩阵的指针。 |
|
矩阵中的行数。 |
|
列数。 |
|
矩阵中非零元素的最大数量。正确获得此值不是强制性的,但对于分配适当数量的内存很有用。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_init_copy( igraph_sparsemat_t *to, const igraph_sparsemat_t *from );
通过复制另一个稀疏矩阵来创建稀疏矩阵对象。源矩阵可以是三元组格式或列压缩格式。
将为复制矩阵分配与原始矩阵当前完全相同的内存量。
参数:
|
指向未初始化的稀疏矩阵的指针,副本将在此处创建。 |
|
要复制的稀疏矩阵。 |
返回值:
错误代码。 |
时间复杂度:O(n+nzmax),列数加上非零元素的最大数量。
igraph_error_t igraph_sparsemat_init_diag( igraph_sparsemat_t *A, igraph_integer_t nzmax, const igraph_vector_t *values, igraph_bool_t compress );
参数:
|
一个未初始化的稀疏矩阵,结果存储在此处。 |
|
非零元素的最大数量,这实质上给出了将为矩阵元素分配的内存量。 |
|
要在对角线上存储的值,矩阵的大小由该向量的长度定义。 |
|
是否创建列压缩矩阵。如果为 false,则创建三元组矩阵。 |
返回值:
错误代码。 |
时间复杂度:O(n),对角向量的长度。
igraph_error_t igraph_sparsemat_init_eye( igraph_sparsemat_t *A, igraph_integer_t n, igraph_integer_t nzmax, igraph_real_t value, igraph_bool_t compress );
参数:
|
一个未初始化的稀疏矩阵,结果存储在此处。 |
|
矩阵中的行数和列数。 |
|
非零元素的最大数量,这实质上给出了将为矩阵元素分配的内存量。 |
|
要在对角线上存储的值。 |
|
是否创建列压缩矩阵。如果为 false,则创建三元组矩阵。 |
返回值:
错误代码。 |
时间复杂度:O(n)。
igraph_error_t igraph_sparsemat_realloc(igraph_sparsemat_t *A, igraph_integer_t nzmax);
稀疏矩阵会自动分配更多内存,根据需要。要控制内存分配,用户可以调用此函数,为给定数量的非零元素分配内存。
参数:
|
稀疏矩阵,可以是三元组格式或列压缩格式。 |
|
非零元素的新最大数量。 |
返回值:
错误代码。 |
时间复杂度:待定。
void igraph_sparsemat_destroy(igraph_sparsemat_t *A);
一旦销毁,必须再次初始化稀疏矩阵,然后才能对其调用任何其他操作。
参数:
|
要销毁的稀疏矩阵。 |
时间复杂度:O(1)。
igraph_error_t igraph_sparsemat_view(igraph_sparsemat_t *A, igraph_integer_t nzmax, igraph_integer_t m, igraph_integer_t n, igraph_integer_t *p, igraph_integer_t *i, igraph_real_t *x, igraph_integer_t nz);
此函数可用于临时处理现有的稀疏矩阵数据,通常由另一个软件库创建,作为 igraph_sparsemat_t
对象,从而避免不必要的复制。它支持以压缩稀疏列格式或 (i, j, x)
三元组格式存储的数据,其中 i
和 j
是非零元素的矩阵索引,x
是其值。
压缩稀疏列(或行)格式通常用于表示稀疏矩阵数据。它由三个向量组成,p
列指针,i
行索引和 x
值。p[k]
是矩阵列 k-1
和更低列中非零元素的数量。p[0]
始终为零,p[n]
始终为矩阵中非零元素的总数。i[l]
是第 l
个存储元素的行索引,而 x[l]
是其值。如果显式存储索引为 (j, k)
的矩阵元素,则它必须位于 i
和 x
向量中的位置 p[k]
和 p[k+1] - 1
(包括)之间。
不要对使用此函数创建的稀疏矩阵调用 igraph_sparsemat_destroy()
。相反,必须在 A
的 cs
字段上调用 igraph_free()
以释放此函数分配的存储空间。
警告:使用此函数创建的矩阵不得与可能重新分配底层存储的函数一起使用,例如 igraph_sparsemat_entry()
。
参数:
|
未初始化的稀疏矩阵。 |
|
条目的最大数量,通常是条目的实际数量。 |
|
矩阵行数。 |
|
矩阵列数。 |
|
对于压缩矩阵,这是列指针向量,并且大小必须为 |
|
行向量。这应包含 |
|
稀疏矩阵的非零元素的值。它的大小必须为 |
|
对于压缩矩阵,它必须为 -1。对于三元组格式矩阵,它必须包含条目的数量。 |
返回值:
错误代码。 |
时间复杂度:O(1)。
igraph_sparsemat_index
— 提取子矩阵或单个元素。igraph_sparsemat_nrow
— 行数。igraph_sparsemat_ncol
— 列数。igraph_sparsemat_type
— 稀疏矩阵的类型(三元组或列压缩)。igraph_sparsemat_is_triplet
— 此稀疏矩阵是否为三元组格式?igraph_sparsemat_is_cc
— 此稀疏矩阵是否为列压缩格式?igraph_sparsemat_is_symmetric
— 返回稀疏矩阵是否对称。igraph_sparsemat_get
— 从稀疏矩阵返回单个元素的值。igraph_sparsemat_getelements
— 返回稀疏矩阵的所有元素。igraph_sparsemat_getelements_sorted
— 返回稀疏矩阵的所有元素,按行和列索引排序。igraph_sparsemat_min
— 稀疏矩阵的最小值。igraph_sparsemat_max
— 稀疏矩阵的最大值。igraph_sparsemat_minmax
— 稀疏矩阵的最小值和最大值。igraph_sparsemat_count_nonzero
— 计数稀疏矩阵的非零元素。igraph_sparsemat_count_nonzerotol
— 计数稀疏矩阵的非零元素,忽略接近零的元素。igraph_sparsemat_rowsums
— 按行求和。igraph_sparsemat_colsums
— 按列求和。igraph_sparsemat_nonzero_storage
— 返回稀疏矩阵的存储条目数。
igraph_error_t igraph_sparsemat_index(const igraph_sparsemat_t *A, const igraph_vector_int_t *p, const igraph_vector_int_t *q, igraph_sparsemat_t *res, igraph_real_t *constres);
此函数索引到稀疏矩阵中。它有两个目的。首先,它可以从稀疏矩阵中提取子矩阵。其次,作为一种特殊情况,它可以从稀疏矩阵中提取单个元素。
参数:
|
输入矩阵,它必须是列压缩格式。 |
|
一个整数向量或一个空指针。选定的行索引或索引。空指针选择所有行。 |
|
一个整数向量或一个空指针。选定的列索引或索引。空指针选择所有列。 |
|
指向未初始化的稀疏矩阵的指针,或一个空指针。如果不是空指针,则选定的子矩阵将存储在此处。 |
|
指向实变量的指针或一个空指针。如果不是空指针,则选定子矩阵中的第一个非零元素将存储在此处(如果存在)。否则,将在此处存储零。如果有人想从矩阵中选择单个条目,则此行为很方便。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_integer_t igraph_sparsemat_nrow(const igraph_sparsemat_t *A);
参数:
|
输入矩阵,三元组格式或列压缩格式。 |
返回值:
|
时间复杂度:O(1)。
igraph_integer_t igraph_sparsemat_ncol(const igraph_sparsemat_t *A);
参数:
|
输入矩阵,三元组格式或列压缩格式。 |
返回值:
|
时间复杂度:O(1)。
igraph_sparsemat_type_t igraph_sparsemat_type(const igraph_sparsemat_t *A);
指示稀疏矩阵是以三元组格式还是以列压缩格式存储。
参数:
|
输入矩阵。 |
返回值:
要么是 |
时间复杂度:O(1)。
igraph_bool_t igraph_sparsemat_is_triplet(const igraph_sparsemat_t *A);
确定稀疏矩阵是否为三元组格式。
参数:
|
输入矩阵。 |
返回值:
如果输入矩阵为三元组格式,则为 1,否则为零。 |
时间复杂度:O(1)。
igraph_bool_t igraph_sparsemat_is_cc(const igraph_sparsemat_t *A);
确定稀疏矩阵是否为列压缩格式。
参数:
|
输入矩阵。 |
返回值:
如果输入矩阵为列压缩格式,则为 1,否则为零。 |
时间复杂度:O(1)。
igraph_error_t igraph_sparsemat_is_symmetric(const igraph_sparsemat_t *A, igraph_bool_t *result);
参数:
|
输入矩阵 |
|
指向 |
返回值:
错误代码。 |
igraph_real_t igraph_sparsemat_get( const igraph_sparsemat_t *A, igraph_integer_t row, igraph_integer_t col );
参数:
|
输入矩阵,三元组格式或列压缩格式。 |
|
行索引 |
|
列索引 |
返回值:
矩阵中具有给定行和列索引的单元格的值;如果索引超出范围,则为零。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_getelements(const igraph_sparsemat_t *A, igraph_vector_int_t *i, igraph_vector_int_t *j, igraph_vector_t *x);
此函数将以三个向量返回稀疏矩阵的元素。两个向量将指示元素的位置,一个向量将指定元素本身。
参数:
|
三元组或压缩形式的稀疏矩阵。 |
|
一个初始化的整数向量。这将存储返回元素的行。 |
|
一个初始化的整数向量。对于三元组矩阵,这将存储返回元素的列。对于压缩矩阵,如果列索引为 |
|
一个初始化的向量。元素将放置在此处。 |
返回值:
错误代码。 |
时间复杂度:O(n),稀疏矩阵中存储元素的数量。
igraph_error_t igraph_sparsemat_getelements_sorted(const igraph_sparsemat_t *A, igraph_vector_int_t *i, igraph_vector_int_t *j, igraph_vector_t *x);
此函数将对稀疏矩阵进行排序,并在三个向量中返回元素。两个向量将指示元素的位置,一个向量将指定元素本身。
排序是基于元素的 索引 而不是它们的数值完成的。返回的条目将按列索引排序;然后,同一列中的条目按行索引排序。
参数:
|
三元组或压缩形式的稀疏矩阵。 |
|
一个初始化的整数向量。这将存储返回元素的行。 |
|
一个初始化的整数向量。对于三元组矩阵,这将存储返回元素的列。对于压缩矩阵,如果列索引为 |
|
一个初始化的向量。元素将放置在此处。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_real_t igraph_sparsemat_min(igraph_sparsemat_t *A);
参数:
|
输入矩阵,列压缩。 |
返回值:
输入矩阵中的最小值,如果矩阵具有零元素,则为 |
时间复杂度:待定。
igraph_real_t igraph_sparsemat_max(igraph_sparsemat_t *A);
参数:
|
输入矩阵,列压缩。 |
返回值:
输入矩阵中的最大值,如果矩阵具有零元素,则为 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_minmax(igraph_sparsemat_t *A, igraph_real_t *min, igraph_real_t *max);
参数:
|
输入矩阵,列压缩。 |
|
输入矩阵中的最小值存储在此处,如果矩阵具有零元素,则为 |
|
输入矩阵中的最大值存储在此处,如果矩阵具有零元素,则为 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_integer_t igraph_sparsemat_count_nonzero(igraph_sparsemat_t *A);
参数:
|
输入矩阵,列压缩。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_integer_t igraph_sparsemat_count_nonzerotol(igraph_sparsemat_t *A, igraph_real_t tol);
计算比 tol
更接近零的矩阵条目的数量。
参数:
|
输入矩阵,列压缩。 |
|
零比较的容差。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_rowsums(const igraph_sparsemat_t *A, igraph_vector_t *res);
参数:
|
输入矩阵,三元组格式或列压缩格式。 |
|
一个初始化的向量,结果存储在此处。它将根据需要调整大小。 |
返回值:
错误代码。 |
时间复杂度:O(nz),非零元素的数量。
igraph_error_t igraph_sparsemat_colsums(const igraph_sparsemat_t *A, igraph_vector_t *res);
参数:
|
输入矩阵,三元组格式或列压缩格式。 |
|
一个初始化的向量,结果存储在此处。它将根据需要调整大小。 |
返回值:
错误代码。 |
时间复杂度:对于三元组矩阵为 O(nz),对于列压缩矩阵为 O(nz+n),nz 是非零元素的数量,n 是列数。
igraph_integer_t igraph_sparsemat_nonzero_storage(const igraph_sparsemat_t *A);
此函数将返回稀疏矩阵的存储条目数。这些条目可能为零,并且多个条目可能位于同一位置。使用 igraph_sparsemat_dupl()
对重复条目求和,并使用 igraph_sparsemat_dropzeros()
删除零。
参数:
|
三元组或压缩形式的稀疏矩阵。 |
返回值:
存储条目的数量。 |
时间复杂度:O(1)。
igraph_sparsemat_entry
— 向稀疏矩阵添加元素。igraph_sparsemat_fkeep
— 过滤稀疏矩阵的元素。igraph_sparsemat_dropzeros
— 从稀疏矩阵中删除零元素。igraph_sparsemat_droptol
— 从稀疏矩阵中删除几乎为零的元素。igraph_sparsemat_scale
— 缩放稀疏矩阵。igraph_sparsemat_permute
— 排列稀疏矩阵的行和列。igraph_sparsemat_transpose
— 转置稀疏矩阵。igraph_sparsemat_add
— 两个稀疏矩阵的和。igraph_sparsemat_multiply
— 矩阵乘法。igraph_sparsemat_gaxpy
— 矩阵-向量乘积,添加到另一个向量。igraph_sparsemat_add_rows
— 向稀疏矩阵添加行。igraph_sparsemat_add_cols
— 向稀疏矩阵添加列。igraph_sparsemat_resize
— 调整稀疏矩阵的大小并清除所有元素。igraph_sparsemat_sort
— 按行和列索引对稀疏矩阵的所有元素进行排序。
igraph_error_t igraph_sparsemat_entry(igraph_sparsemat_t *A, igraph_integer_t row, igraph_integer_t col, igraph_real_t elem);
在用 igraph_sparsemat_init()
初始化稀疏矩阵后,可以使用此函数将条目添加到稀疏矩阵中。如果在同一位置添加多个条目,则将保存所有条目,并且结果值是该位置中所有条目的总和。
参数:
|
输入矩阵,它必须是三元组格式。 |
|
要添加的条目的行索引。 |
|
要添加的条目的列索引。 |
|
条目的值。 |
返回值:
错误代码。 |
时间复杂度:平均 O(1)。
igraph_error_t igraph_sparsemat_fkeep( igraph_sparsemat_t *A, igraph_integer_t (*fkeep)(igraph_integer_t, igraph_integer_t, igraph_real_t, void*), void *other );
此函数可用于过滤稀疏矩阵的(非零)元素。对于所有条目,它都会调用提供的函数,并根据返回值保留或删除矩阵中的元素。
参数:
|
输入矩阵,列压缩格式。 |
|
筛选函数。它必须接受四个参数:第一个是 |
|
一个 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_dropzeros(igraph_sparsemat_t *A);
由于矩阵运算,稀疏矩阵中的某些条目可能为零。此函数删除这些条目。
参数:
|
输入矩阵,它必须是列压缩格式。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_droptol(igraph_sparsemat_t *A, igraph_real_t tol);
此函数类似于 igraph_sparsemat_dropzeros()
,但它也会删除比给定的容差阈值更接近零的条目。
参数:
|
输入矩阵,它必须是列压缩格式。 |
|
实数,给出容差阈值。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_scale(igraph_sparsemat_t *A, igraph_real_t by);
将稀疏矩阵的所有元素乘以给定的因子。
参数:
|
输入矩阵。 |
|
比例因子。 |
返回值:
错误代码。 |
时间复杂度:O(nz),矩阵中非零元素的数量。
igraph_error_t igraph_sparsemat_permute(const igraph_sparsemat_t *A, const igraph_vector_int_t *p, const igraph_vector_int_t *q, igraph_sparsemat_t *res);
参数:
|
输入矩阵,它必须是列压缩格式。 |
|
整数向量,给出行的排列。 |
|
整数向量,列的排列。 |
|
指向未初始化的稀疏矩阵的指针,结果存储在此处。 |
返回值:
错误代码。 |
时间复杂度:O(m+n+nz),行数加上列数加上矩阵中非零元素的数量。
igraph_error_t igraph_sparsemat_transpose( const igraph_sparsemat_t *A, igraph_sparsemat_t *res );
参数:
|
输入矩阵,列压缩格式或三元组格式。 |
|
指向未初始化的稀疏矩阵的指针,结果存储在此处。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_add(const igraph_sparsemat_t *A, const igraph_sparsemat_t *B, igraph_real_t alpha, igraph_real_t beta, igraph_sparsemat_t *res);
参数:
|
第一个输入矩阵,列压缩格式。 |
|
第二个输入矩阵,列压缩格式。 |
|
实数值, |
|
实数值, |
|
指向未初始化的稀疏矩阵的指针,结果存储在此处。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_multiply(const igraph_sparsemat_t *A, const igraph_sparsemat_t *B, igraph_sparsemat_t *res);
乘以两个稀疏矩阵。
参数:
|
第一个输入矩阵(左侧),列压缩格式。 |
|
第二个输入矩阵(右侧),列压缩格式。 |
|
指向未初始化的稀疏矩阵的指针,结果存储在此处。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_gaxpy(const igraph_sparsemat_t *A, const igraph_vector_t *x, igraph_vector_t *res);
参数:
|
输入矩阵,列压缩格式。 |
|
输入向量,其大小必须与 |
|
此向量将添加到矩阵-向量乘积中,并被结果覆盖。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_add_rows(igraph_sparsemat_t *A, igraph_integer_t n);
当前矩阵元素将被保留,并且新行中的所有元素都为零。
参数:
|
输入矩阵,三元组格式或列压缩格式。 |
|
要添加的行数。 |
返回值:
错误代码。 |
时间复杂度:O(1)。
igraph_error_t igraph_sparsemat_add_cols(igraph_sparsemat_t *A, igraph_integer_t n);
当前矩阵元素将被保留,并且新列中的所有元素都为零。
参数:
|
输入矩阵,三元组格式或列压缩格式。 |
|
要添加的列数。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_resize(igraph_sparsemat_t *A, igraph_integer_t nrow, igraph_integer_t ncol, igraph_integer_t nzmax);
此函数会调整稀疏矩阵的大小。调整大小后的稀疏矩阵将变为空,即使其中包含非零条目。
参数:
|
要调整大小的已初始化稀疏矩阵。 |
|
新的行数。 |
|
新的列数。 |
|
元素的新最大数量。 |
返回值:
错误代码。 |
时间复杂度:O(nzmax),非零元素的最大数量。
igraph_sparsemat_iterator_init
— 初始化稀疏矩阵迭代器。igraph_sparsemat_iterator_reset
— 将稀疏矩阵迭代器重置为第一个元素。igraph_sparsemat_iterator_end
— 查询迭代器是否已超过最后一个元素。igraph_sparsemat_iterator_row
— 返回迭代器所在的行。igraph_sparsemat_iterator_col
— 返回迭代器所在的列。igraph_sparsemat_iterator_get
— 返回当前迭代器位置的元素。igraph_sparsemat_iterator_next
— 将稀疏矩阵迭代器移动到下一个元素。igraph_sparsemat_iterator_idx
— 返回稀疏矩阵迭代器的元素向量索引。
igraph_error_t igraph_sparsemat_iterator_init( igraph_sparsemat_iterator_t *it, const igraph_sparsemat_t *sparsemat );
参数:
|
指向未初始化的稀疏矩阵迭代器的指针。 |
|
指向稀疏矩阵的指针。 |
返回值:
错误代码。始终返回 |
时间复杂度:O(n),稀疏矩阵的列数。
igraph_error_t igraph_sparsemat_iterator_reset(igraph_sparsemat_iterator_t *it);
参数:
|
指向稀疏矩阵迭代器的指针。 |
返回值:
错误代码。始终返回 |
时间复杂度:O(n),稀疏矩阵的列数。
igraph_bool_t igraph_sparsemat_iterator_end(const igraph_sparsemat_iterator_t *it);
参数:
|
指向稀疏矩阵迭代器的指针。 |
返回值:
如果迭代器已超过最后一个元素,则为 true;如果它指向稀疏矩阵中的一个元素,则为 false。 |
时间复杂度:O(1)。
igraph_integer_t igraph_sparsemat_iterator_row(const igraph_sparsemat_iterator_t *it);
参数:
|
指向稀疏矩阵迭代器的指针。 |
返回值:
当前迭代器位置的元素的行。 |
时间复杂度:O(1)。
igraph_integer_t igraph_sparsemat_iterator_col(const igraph_sparsemat_iterator_t *it);
参数:
|
指向稀疏矩阵迭代器的指针。 |
返回值:
当前迭代器位置的元素的列。 |
时间复杂度:O(1)。
igraph_real_t igraph_sparsemat_iterator_get(const igraph_sparsemat_iterator_t *it);
参数:
|
指向稀疏矩阵迭代器的指针。 |
返回值:
当前迭代器位置的元素的值。 |
时间复杂度:O(1)。
igraph_sparsemat_symblu
— 符号 LU 分解。igraph_sparsemat_symbqr
— 符号 QR 分解。igraph_sparsemat_lsolve
— 求解下三角线性系统。igraph_sparsemat_ltsolve
— 求解上三角线性系统。igraph_sparsemat_usolve
— 求解上三角线性系统。igraph_sparsemat_utsolve
— 求解下三角线性系统。igraph_sparsemat_cholsol
— 通过 Cholesky 分解求解对称线性系统。igraph_sparsemat_lusol
— 通过 LU 分解求解线性系统。igraph_sparsemat_lu
— 稀疏矩阵的 LU 分解。igraph_sparsemat_qr
— 稀疏矩阵的 QR 分解。igraph_sparsemat_luresol
— 使用预计算的 LU 分解求解线性系统。igraph_sparsemat_qrresol
— 使用预计算的 QR 分解求解线性系统。igraph_sparsemat_symbolic_destroy
— 在符号分解后释放内存。igraph_sparsemat_numeric_destroy
— 在数值分解后释放内存。
igraph_error_t igraph_sparsemat_symblu(igraph_integer_t order, const igraph_sparsemat_t *A, igraph_sparsemat_symbolic_t *dis);
稀疏矩阵的 LU 分解涉及两个步骤,首先调用此函数,然后调用 igraph_sparsemat_lu()
。
参数:
|
要使用的排序:0 表示自然排序,1 表示 A+A' 的最小度排序,2 表示从 A 中删除密集行后 A'A 的最小度排序,3 表示 A'A 的最小度排序。 |
|
输入矩阵,列压缩格式。 |
|
符号分析的结果存储在此处。一旦不再需要,必须通过调用 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_symbqr(igraph_integer_t order, const igraph_sparsemat_t *A, igraph_sparsemat_symbolic_t *dis);
稀疏矩阵的 QR 分解涉及两个步骤,首先调用此函数,然后调用 igraph_sparsemat_qr()
。
参数:
|
要使用的排序:0 表示自然排序,1 表示 A+A' 的最小度排序,2 表示从 A 中删除密集行后 A'A 的最小度排序,3 表示 A'A 的最小度排序。 |
|
输入矩阵,列压缩格式。 |
|
符号分析的结果存储在此处。一旦不再需要,必须通过调用 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_lsolve(const igraph_sparsemat_t *L, const igraph_vector_t *b, igraph_vector_t *res);
求解 Lx=b 线性方程组,其中 L 系数矩阵是具有无零对角线的方阵且下三角。
参数:
|
输入矩阵,列压缩格式。 |
|
线性系统的右侧。 |
|
初始化的向量,结果存储在此处。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_ltsolve(const igraph_sparsemat_t *L, const igraph_vector_t *b, igraph_vector_t *res);
求解 L'x=b 线性方程组,其中 L 矩阵是具有无零对角线的方阵且下三角。
参数:
|
输入矩阵,列压缩格式。 |
|
线性系统的右侧。 |
|
初始化的向量,结果存储在此处。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_usolve(const igraph_sparsemat_t *U, const igraph_vector_t *b, igraph_vector_t *res);
求解 Ux=b 上三角系统。
参数:
|
输入矩阵,列压缩格式。 |
|
线性系统的右侧。 |
|
初始化的向量,结果存储在此处。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_utsolve(const igraph_sparsemat_t *U, const igraph_vector_t *b, igraph_vector_t *res);
这与 igraph_sparsemat_usolve()
相同,但求解的是 U'x=b,其中撇号表示转置。
参数:
|
输入矩阵,列压缩格式。 |
|
线性系统的右侧。 |
|
初始化的向量,结果存储在此处。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_cholsol(const igraph_sparsemat_t *A, const igraph_vector_t *b, igraph_vector_t *res, igraph_integer_t order);
求解 Ax=b,其中 A 是对称正定矩阵。
参数:
|
输入矩阵,列压缩格式。 |
|
右手边。 |
|
初始化的向量,结果存储在此处。 |
|
一个整数,给出用于分解的排序方法。零是自然排序;如果它是一,则使用 A+A' 的填充减少最小度排序。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_lusol(const igraph_sparsemat_t *A, const igraph_vector_t *b, igraph_vector_t *res, igraph_integer_t order, igraph_real_t tol);
通过 A 的 LU 分解求解 Ax=b。
参数:
|
输入矩阵,列压缩格式。 |
|
方程的右手边。 |
|
初始化的向量,结果存储在此处。 |
|
要使用的排序方法,零表示自然排序,一表示 A+A' 的填充减少最小度排序,二表示 A'*A 的排序,从 A 中删除密集行后。三表示 A'*A 的排序。 |
|
实数,用于数值 LU 分解的容差限制。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_lu(const igraph_sparsemat_t *A, const igraph_sparsemat_symbolic_t *dis, igraph_sparsemat_numeric_t *din, double tol);
执行矩阵的数值稀疏 LU 分解。
参数:
|
输入矩阵,列压缩格式。 |
|
LU 分解的符号分析,来自对 |
|
数值分解,结果存储在此处。通过调用 |
|
数值 LU 分解的容差。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_qr(const igraph_sparsemat_t *A, const igraph_sparsemat_symbolic_t *dis, igraph_sparsemat_numeric_t *din);
稀疏矩阵的数值 QR 分解。
参数:
|
输入矩阵,列压缩格式。 |
|
符号 QR 分析的结果,来自函数 |
|
分解的结果存储在此处,通过使用 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_luresol(const igraph_sparsemat_symbolic_t *dis, const igraph_sparsemat_numeric_t *din, const igraph_vector_t *b, igraph_vector_t *res);
使用矩阵的 LU 分解来求解线性系统。
参数:
|
系数矩阵的符号分析, |
|
LU 分解,调用 |
|
一个向量,定义线性方程组的右手边。 |
|
一个初始化的向量,线性系统的解存储在此处。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_qrresol(const igraph_sparsemat_symbolic_t *dis, const igraph_sparsemat_numeric_t *din, const igraph_vector_t *b, igraph_vector_t *res);
使用其系数矩阵的 QR 分解求解线性系统。
参数:
|
系数矩阵的符号分析, |
|
系数矩阵的 QR 分解, |
|
向量,给出线性方程组的右手边。 |
|
一个初始化的向量,解存储在此处。它会根据需要调整大小。 |
返回值:
错误代码。 |
时间复杂度:待定。
void igraph_sparsemat_symbolic_destroy(igraph_sparsemat_symbolic_t *dis);
释放由 igraph_sparsemat_symbqr()
或 igraph_sparsemat_symblu()
分配的内存。
参数:
|
符号分析。 |
时间复杂度:O(1)。
void igraph_sparsemat_numeric_destroy(igraph_sparsemat_numeric_t *din);
释放由 igraph_sparsemat_qr()
或 igraph_sparsemat_lu()
分配的内存。
参数:
|
LU 或 QR 分解。 |
时间复杂度:O(1)。
igraph_error_t igraph_sparsemat_arpack_rssolve(const igraph_sparsemat_t *A, igraph_arpack_options_t *options, igraph_arpack_storage_t *storage, igraph_vector_t *values, igraph_matrix_t *vectors, igraph_sparsemat_solve_t solvemethod);
参数:
|
输入矩阵,必须是列压缩的。 |
||||
|
它传递给 |
||||
|
ARPACK 的存储。有关详细信息,请参阅 |
||||
|
一个初始化的向量或一个空指针,特征值存储在此处。 |
||||
|
一个初始化的矩阵或一个空指针,特征向量存储在此处的列中。 |
||||
|
求解线性系统的方法,如果
|
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat_arpack_rnsolve(const igraph_sparsemat_t *A, igraph_arpack_options_t *options, igraph_arpack_storage_t *storage, igraph_matrix_t *values, igraph_matrix_t *vectors);
非对称稀疏矩阵的特征值和/或特征向量。
参数:
|
输入矩阵,采用列压缩模式。 |
|
ARPACK 选项,它传递给 |
|
ARPACK 的存储,这传递给 |
|
一个初始化的矩阵或一个空指针。如果不是空指针,则特征值存储在此处,第一列是实部,第二列是虚部。 |
|
一个初始化的矩阵或一个空指针。如果不是空指针,则特征向量存储在此处,请参阅 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_sparsemat(igraph_t *graph, const igraph_sparsemat_t *A, igraph_bool_t directed);
为矩阵中的每个非零条目创建一个边。如果您有一个对称矩阵,并且想要创建一个无向图,请首先删除上对角线中的条目,或者在结果图上调用 igraph_simplify()
以消除多重边。
参数:
|
指向未初始化的 igraph_t 对象的指针,图存储在此处。 |
|
输入矩阵,三元组格式或列压缩格式。 |
|
是否创建有向图。 |
返回值:
错误代码。 |
时间复杂度:待定。
igraph_error_t igraph_matrix_as_sparsemat(igraph_sparsemat_t *res, const igraph_matrix_t *mat, igraph_real_t tol);
参数:
|
一个未初始化的稀疏矩阵,结果存储在此处。 |
|
密集输入矩阵。 |
|
零比较的容差。值比 |
返回值:
错误代码。 |
另请参阅:
|
时间复杂度:O(mn),密集矩阵中元素的数量。
igraph_error_t igraph_sparsemat_as_matrix(igraph_matrix_t *res, const igraph_sparsemat_t *spmat);
参数:
|
指向初始化的矩阵的指针,结果存储在此处。它将调整为所需的大小。 |
|
输入稀疏矩阵,采用三元组或列压缩格式。 |
返回值:
错误代码。 |
另请参阅:
|
时间复杂度:O(mn),密集矩阵中元素的数量。
igraph_error_t igraph_sparsemat_copy( igraph_sparsemat_t *to, const igraph_sparsemat_t *from );
自 0.10 版本起已弃用。请勿在新代码中使用此函数;请改用 igraph_sparsemat_init_copy()
。
igraph_error_t igraph_sparsemat_diag( igraph_sparsemat_t *A, igraph_integer_t nzmax, const igraph_vector_t *values, igraph_bool_t compress );
自 0.10 版本起已弃用。请勿在新代码中使用此函数;请改用 igraph_sparsemat_init_diag()
。
igraph_error_t igraph_sparsemat_eye( igraph_sparsemat_t *A, igraph_integer_t n, igraph_integer_t nzmax, igraph_real_t value, igraph_bool_t compress );
自 0.10 版本起已弃用。请勿在新代码中使用此函数;请改用 igraph_sparsemat_init_eye()
。
igraph_stack_init
— 初始化堆栈。igraph_stack_destroy
— 销毁堆栈对象。igraph_stack_reserve
— 预留内存。igraph_stack_empty
— 判断堆栈对象是否为空。igraph_stack_size
— 返回堆栈中的元素数量。igraph_stack_clear
— 从堆栈中删除所有元素。igraph_stack_push
— 将元素放置在堆栈顶部。igraph_stack_pop
— 从堆栈顶部删除并返回一个元素。igraph_stack_top
— 查询顶部元素。
igraph_error_t igraph_stack_init(igraph_stack_t* s, igraph_integer_t capacity);
初始化的堆栈始终为空。
参数:
|
指向未初始化的堆栈的指针。 |
|
要为其分配内存的元素的数量。 |
返回值:
错误代码。 |
时间复杂度:O(size
)。
void igraph_stack_destroy(igraph_stack_t* s);
释放用于堆栈的内存。可以通过 igraph_stack_init()
再次重新初始化已销毁的堆栈。
参数:
|
要销毁的堆栈。 |
时间复杂度:O(1)。
igraph_error_t igraph_stack_reserve(igraph_stack_t* s, igraph_integer_t capacity);
为将来使用预留内存。堆栈的实际大小不变。
参数:
|
堆栈对象。 |
|
要为其预留内存的元素的数量。如果它不大于当前大小,则不会发生任何事情。 |
返回值:
错误代码。 |
时间复杂度:应该在 O(n) 左右,堆栈的新分配大小。
igraph_bool_t igraph_stack_empty(igraph_stack_t* s);
参数:
|
堆栈对象。 |
返回值:
布尔值,如果堆栈为空,则为 |
时间复杂度:O(1)。
igraph_integer_t igraph_stack_size(const igraph_stack_t* s);
参数:
|
堆栈对象。 |
返回值:
堆栈中的元素数量。 |
时间复杂度:O(1)。
igraph_error_t igraph_stack_push(igraph_stack_t* s, igraph_real_t elem);
如果需要,堆栈的容量会增加。
参数:
|
堆栈对象。 |
|
要推送的元素。 |
返回值:
错误代码。 |
时间复杂度:如果不需要重新分配,则为 O(1),否则为 O(n),但可以确保在 O(n) 时间内执行 n 次推送操作。
igraph_real_t igraph_stack_pop(igraph_stack_t* s);
堆栈必须包含至少一个元素,请调用 igraph_stack_empty()
以确保这一点。
参数:
|
堆栈对象。 |
返回值:
已删除的顶部元素。 |
时间复杂度:O(1)。
igraph_dqueue_init
— 初始化双端队列 (deque)。igraph_dqueue_destroy
— 销毁双端队列。igraph_dqueue_empty
— 判断队列是否为空。igraph_dqueue_full
— 检查队列是否已满。igraph_dqueue_clear
— 从队列中删除所有元素。igraph_dqueue_size
— 队列中的元素数量。igraph_dqueue_head
— 队列的头部。igraph_dqueue_back
— 队列的尾部。igraph_dqueue_get
— 访问队列中的元素。igraph_dqueue_pop
— 删除头部。igraph_dqueue_pop_back
— 删除尾部。igraph_dqueue_push
— 追加一个元素。这是双端队列的经典数据类型。如果需要先进先出 (FIFO) 行为,则大多数时候会使用它。请参阅以下操作。
示例 7.10. 文件 examples/simple/dqueue.c
#include <igraph.h> int main(void) { igraph_dqueue_t q; /* igraph_dqueue_init, igraph_dqueue_destroy, igraph_dqueue_empty */ igraph_dqueue_init(&q, 5); if (!igraph_dqueue_empty(&q)) { return 1; } igraph_dqueue_destroy(&q); /* igraph_dqueue_push, igraph_dqueue_pop */ igraph_dqueue_init(&q, 4); igraph_dqueue_push(&q, 1); igraph_dqueue_push(&q, 2); igraph_dqueue_push(&q, 3); igraph_dqueue_push(&q, 4); if (igraph_dqueue_pop(&q) != 1) { return 2; } if (igraph_dqueue_pop(&q) != 2) { return 3; } if (igraph_dqueue_pop(&q) != 3) { return 4; } if (igraph_dqueue_pop(&q) != 4) { return 5; } igraph_dqueue_destroy(&q); /* igraph_dqueue_clear, igraph_dqueue_size */ igraph_dqueue_init(&q, 0); if (igraph_dqueue_size(&q) != 0) { return 6; } igraph_dqueue_clear(&q); if (igraph_dqueue_size(&q) != 0) { return 7; } for (int i = 0; i < 10; i++) { igraph_dqueue_push(&q, i); } igraph_dqueue_clear(&q); if (igraph_dqueue_size(&q) != 0) { return 8; } igraph_dqueue_destroy(&q); /* TODO: igraph_dqueue_full */ /* igraph_dqueue_head, igraph_dqueue_back, igraph_dqueue_pop_back */ igraph_dqueue_init(&q, 0); for (int i = 0; i < 10; i++) { igraph_dqueue_push(&q, i); } for (int i = 0; i < 10; i++) { if (igraph_dqueue_head(&q) != 0) { return 9; } if (igraph_dqueue_back(&q) != 9 - i) { return 10; } if (igraph_dqueue_pop_back(&q) != 9 - i) { return 11; } } igraph_dqueue_destroy(&q); /* print */ igraph_dqueue_init(&q, 4); igraph_dqueue_push(&q, 1); igraph_dqueue_push(&q, 2); igraph_dqueue_push(&q, 3); igraph_dqueue_push(&q, 4); igraph_dqueue_pop(&q); igraph_dqueue_pop(&q); igraph_dqueue_push(&q, 5); igraph_dqueue_push(&q, 6); igraph_dqueue_print(&q); igraph_dqueue_clear(&q); igraph_dqueue_print(&q); igraph_dqueue_destroy(&q); if (IGRAPH_FINALLY_STACK_SIZE() != 0) { return 12; } return 0; }
igraph_error_t igraph_dqueue_init(igraph_dqueue_t* q, igraph_integer_t capacity);
队列将始终为空。
参数:
|
指向未初始化的 deque 的指针。 |
|
要为其分配内存的元素数量。 |
返回值:
错误代码。 |
时间复杂度:O(capacity
)。
igraph_bool_t igraph_dqueue_empty(const igraph_dqueue_t* q);
参数:
|
队列。 |
返回值:
布尔值,如果 |
时间复杂度:O(1)。
igraph_bool_t igraph_dqueue_full(igraph_dqueue_t* q);
如果队列已满,则下一个 igraph_dqueue_push()
操作将分配更多内存。
参数:
|
队列。 |
返回值:
如果 |
时间复杂度:O(1)。
igraph_integer_t igraph_dqueue_size(const igraph_dqueue_t* q);
参数:
|
队列。 |
返回值:
整数,队列中当前的元素数量。 |
时间复杂度:O(1)。
igraph_real_t igraph_dqueue_head(const igraph_dqueue_t* q);
队列必须包含至少一个元素。
参数:
|
队列。 |
返回值:
队列中的第一个元素。 |
时间复杂度:O(1)。
igraph_real_t igraph_dqueue_back(const igraph_dqueue_t* q);
队列必须包含至少一个元素。
参数:
|
队列。 |
返回值:
队列中的最后一个元素。 |
时间复杂度:O(1)。
igraph_real_t igraph_dqueue_get(const igraph_dqueue_t *q, igraph_integer_t idx);
参数:
|
队列。 |
|
队列中元素的索引。 |
返回值:
所需的元素。 |
时间复杂度:O(1)。
igraph_real_t igraph_dqueue_pop(igraph_dqueue_t* q);
删除并返回队列中的第一个元素。队列必须为非空。
参数:
|
输入队列。 |
返回值:
队列中的第一个元素。 |
时间复杂度:O(1)。
igraph_heap_init
— 初始化一个空堆对象。igraph_heap_init_array
— 从数组构建一个堆。igraph_heap_destroy
— 销毁一个初始化的堆对象。igraph_heap_clear
— 从堆中删除所有元素。igraph_heap_empty
— 判断堆对象是否为空。igraph_heap_push
— 添加一个元素。igraph_heap_top
— 顶部元素。igraph_heap_delete_top
— 删除并返回顶部元素。igraph_heap_size
— 堆中的元素数量。igraph_heap_reserve
— 为堆预留内存。
igraph_error_t igraph_heap_init(igraph_heap_t* h, igraph_integer_t capacity);
创建一个空堆,并为某些元素分配内存。
参数:
|
指向未初始化的堆对象的指针。 |
|
要为其分配内存的元素的数量。 |
返回值:
错误代码。 |
时间复杂度:O(alloc_size
),假设内存分配是线性操作。
igraph_error_t igraph_heap_init_array(igraph_heap_t *h, const igraph_real_t *data, igraph_integer_t len);
从数组初始化一个堆对象。当然,堆也已构建(构造函数)。
参数:
|
指向未初始化的堆对象的指针。 |
|
指向基本数据类型数组的指针。 |
|
|
返回值:
错误代码。 |
时间复杂度:O(n),堆中的元素数量。
void igraph_heap_clear(igraph_heap_t* h);
此函数仅将堆的大小设置为零,它不会释放任何已分配的内存。为此,您必须调用 igraph_heap_destroy()
。
参数:
|
堆对象。 |
时间复杂度:O(1)。
igraph_bool_t igraph_heap_empty(const igraph_heap_t* h);
参数:
|
堆对象。 |
返回值:
如果堆为空,则为 |
时间复杂度:O(1)。
igraph_error_t igraph_heap_push(igraph_heap_t* h, igraph_real_t elem);
将一个元素添加到堆中。
参数:
|
堆对象。 |
|
要添加的元素。 |
返回值:
错误代码。 |
时间复杂度:如果不需要重新分配,则 n 是堆中元素的数量,为 O(log n),否则为 O(n)。可以确保在 O(n log n) 时间内执行 n 次推送操作。
igraph_real_t igraph_heap_top(const igraph_heap_t* h);
对于最大堆,这是堆中最大的元素,对于最小堆,这是堆中最小的元素。
参数:
|
堆对象。 |
返回值:
顶部元素。 |
时间复杂度:O(1)。
igraph_real_t igraph_heap_delete_top(igraph_heap_t* h);
删除并返回堆的顶部元素。对于最大堆,这是最大的元素,对于最小堆,这是最小的元素。
参数:
|
堆对象。 |
返回值:
顶部元素。 |
时间复杂度:O(log n),n 是堆中元素的数量。
igraph_strvector_init
— 初始化字符串向量。igraph_strvector_init_copy
— 通过复制初始化。igraph_strvector_destroy
— 释放为字符串向量分配的内存。STR
— 索引字符串向量。igraph_strvector_get
— 检索字符串向量的元素。igraph_strvector_set
— 从字符串设置字符串向量的元素。igraph_strvector_set_len
— 给定缓冲区及其大小,设置字符串向量的元素。igraph_strvector_push_back
— 将元素添加到字符串向量的末尾。igraph_strvector_push_back_len
— 将给定长度的字符串添加到字符串向量的末尾。igraph_strvector_swap_elements
— 交换字符串向量中的两个元素。igraph_strvector_remove
— 从字符串向量中删除单个元素。igraph_strvector_remove_section
— 从字符串向量中删除一个部分。igraph_strvector_append
— 连接两个字符串向量。igraph_strvector_merge
— 将一个字符串向量的内容移动到另一个字符串向量的末尾。igraph_strvector_clear
— 从字符串向量中删除所有元素。igraph_strvector_resize
— 调整字符串向量的大小。igraph_strvector_reserve
— 为字符串向量保留内存。igraph_strvector_resize_min
— 释放字符串向量中未使用的内存。igraph_strvector_size
— 返回字符串向量的大小。igraph_strvector_capacity
— 返回字符串向量的容量。igraph_strvector_t 类型是空终止字符串的向量。它在内部用于存储图属性名称以及 C 属性处理程序中的字符串属性。
此容器自动管理其元素的内存。igraph_strvector_t 中的字符串应被视为常量,并且不应直接修改。添加新元素的函数总是复制传递给它们的字符串。
示例 7.11. 文件 examples/simple/igraph_strvector.c
#include <igraph.h> void strvector_print(const igraph_strvector_t sv) { igraph_integer_t i, s = igraph_strvector_size(&sv); for (i = 0; i < s; i++) { printf("---%s---\n", igraph_strvector_get(&sv, i)); } printf("\n"); } int main(void) { igraph_strvector_t sv1, sv2; printf("Initializing and setting elements:\n"); igraph_strvector_init(&sv1, 5); igraph_strvector_set(&sv1, 0, "zero"); igraph_strvector_set(&sv1, 1, "one"); igraph_strvector_set(&sv1, 2, "two"); igraph_strvector_set(&sv1, 3, "three"); igraph_strvector_set(&sv1, 4, "four"); strvector_print(sv1); printf("strvector size after first removing one element, and then the rest:\n"); igraph_strvector_remove(&sv1, 4); igraph_strvector_remove_section(&sv1, 0, 4); printf("%" IGRAPH_PRId "\n\n", igraph_strvector_size(&sv1)); printf("Resize to three elements, and set them:\n"); igraph_strvector_resize(&sv1, 3); igraph_strvector_set(&sv1, 0, "zero"); igraph_strvector_set(&sv1, 1, "one"); igraph_strvector_set(&sv1, 2, "two"); strvector_print(sv1); printf("Then copy the first element over the third element:\n"); igraph_strvector_set(&sv1, 2, igraph_strvector_get(&sv1, 0)); strvector_print(sv1); printf("Make a copy of the strvector and set the last element of the copy:\n"); igraph_strvector_init_copy(&sv2, &sv1); igraph_strvector_set(&sv2, 2, "copy two"); strvector_print(sv2); printf("Append the copy to the strvector:\n"); igraph_strvector_append(&sv1, &sv2); strvector_print(sv1); printf("Add two strings at the end:\n"); igraph_strvector_push_back(&sv1, "zeroth"); igraph_strvector_push_back(&sv1, "first"); strvector_print(sv1); igraph_strvector_destroy(&sv1); printf("strvector size after clearing it:\n"); igraph_strvector_clear(&sv2); printf("%" IGRAPH_PRId "\n", igraph_strvector_size(&sv2)); igraph_strvector_destroy(&sv2); return 0; }
igraph_error_t igraph_strvector_init(igraph_strvector_t *sv, igraph_integer_t size);
为字符串向量保留内存,必须先初始化字符串向量,然后才能在其上调用其他函数。字符串向量的所有元素都设置为空字符串。
参数:
|
指向已初始化字符串向量的指针。 |
|
字符串向量的(初始)长度。 |
返回值:
错误代码。 |
时间复杂度:O(len
)。
igraph_error_t igraph_strvector_init_copy(igraph_strvector_t *to, const igraph_strvector_t *from);
通过复制另一个字符串向量来初始化字符串向量。
参数:
|
指向未初始化字符串向量的指针。 |
|
要复制的另一个字符串向量。 |
返回值:
错误代码。 |
时间复杂度:O(l),from
中字符串的总长度。
void igraph_strvector_destroy(igraph_strvector_t *sv);
销毁字符串向量。稍后可以使用 igraph_strvector_init()
重新初始化它。
参数:
|
字符串向量。 |
时间复杂度:O(l),字符串的总长度,可能取决于内存管理器。
#define STR(sv,i)
这是一个宏,允许查询字符串向量的元素,就像 igraph_strvector_get()
一样。请注意,此宏不能用于设置元素。请使用 igraph_strvector_set()
来设置元素。
参数:
|
字符串向量 |
|
元素的索引。 |
返回值:
位置 |
时间复杂度:O(1)。
自 0.10.9 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_strvector_get()
。
const char *igraph_strvector_get(const igraph_strvector_t *sv, igraph_integer_t idx);
查询字符串向量的元素。返回的字符串不得修改。
参数:
|
输入字符串向量。 |
|
要查询的元素的索引。 |
时间复杂度:O(1)。
igraph_error_t igraph_strvector_set(igraph_strvector_t *sv, igraph_integer_t idx, const char *value);
提供的 value
被复制到字符串向量中的 idx
位置。
参数:
|
字符串向量。 |
|
要设置的位置。 |
|
新值。 |
返回值:
错误代码。 |
时间复杂度:O(l),新字符串的长度。如果需要重新分配,则可能会更多,具体取决于内存管理。
igraph_error_t igraph_strvector_set_len(igraph_strvector_t *sv, igraph_integer_t idx, const char *value, size_t len);
这几乎与 igraph_strvector_set
相同,但新值不是以零结尾的字符串,而是给出了它的长度。
参数:
|
字符串向量。 |
|
要设置的位置。 |
|
新值。 |
|
新值的长度。 |
返回值:
错误代码。 |
时间复杂度:O(l),新字符串的长度。如果需要重新分配,则可能会更多,具体取决于内存管理。
igraph_error_t igraph_strvector_push_back(igraph_strvector_t *sv, const char *value);
参数:
|
字符串向量。 |
|
要添加的字符串;它将被复制。 |
返回值:
错误代码。 |
时间复杂度:O(n+l),n 是字符串的总数,l 是新字符串的长度。
igraph_error_t igraph_strvector_push_back_len( igraph_strvector_t *sv, const char *value, igraph_integer_t len);
参数:
|
字符串向量。 |
|
要添加的字符串的开头。最多复制 |
|
字符串的长度。 |
返回值:
错误代码。 |
时间复杂度:O(n+l),n 是字符串的总数,l 是新字符串的长度。
void igraph_strvector_swap_elements(igraph_strvector_t *sv, igraph_integer_t i, igraph_integer_t j);
请注意,目前不执行范围检查。
参数:
|
字符串向量。 |
|
第一个元素的索引。 |
|
第二个元素的索引(可能与第一个元素相同)。 |
时间复杂度:O(1)。
void igraph_strvector_remove(igraph_strvector_t *sv, igraph_integer_t elem);
字符串将短一个。
参数:
|
字符串向量。 |
|
要删除的元素的索引。 |
时间复杂度:O(n),字符串的长度。
void igraph_strvector_remove_section( igraph_strvector_t *sv, igraph_integer_t from, igraph_integer_t to);
此函数从字符串向量中删除范围 [from, to)
。
参数:
|
字符串向量。 |
|
要删除的第一个元素的位置。 |
|
第一个不要删除的元素的位置。 |
igraph_error_t igraph_strvector_append(igraph_strvector_t *to, const igraph_strvector_t *from);
将 from
向量的内容附加到 to
向量。如果在此操作后不再需要 from
向量,请使用 igraph_strvector_merge()
以获得更好的性能。
参数:
|
第一个字符串向量,结果存储在此处。 |
|
第二个字符串向量,它保持不变。 |
返回值:
错误代码。 |
另请参阅:
时间复杂度:O(n+l2),n 是新字符串向量中字符串的数量,l2 是 from
字符串向量中字符串的总长度。
igraph_error_t igraph_strvector_merge(igraph_strvector_t *to, igraph_strvector_t *from);
将 from
向量的内容传输到 to
的末尾,同时清除 from
。如果此操作失败,则两个向量都保持不变。此函数不复制或重新分配单个字符串,因此它比 igraph_strvector_append()
性能更好。
参数:
|
目标向量。 |
|
源向量。它将被清除。 |
返回值:
错误代码。 |
另请参阅:
时间复杂度:如果 to
有足够的容量,则为 O(l2),否则为 O(2*l1+l2),其中 l1 和 l2 分别是 to
和 \from 的长度。
void igraph_strvector_clear(igraph_strvector_t *sv);
在此操作之后,字符串向量将为空。
参数:
|
字符串向量。 |
时间复杂度:O(l),字符串的总长度,可能更少,具体取决于内存管理器。
igraph_error_t igraph_strvector_resize(igraph_strvector_t *sv, igraph_integer_t newsize);
如果新大小大于当前大小,则添加空字符串;如果小于当前大小,则删除不需要的元素。
参数:
|
字符串向量。 |
|
新大小。 |
返回值:
错误代码。 |
时间复杂度:O(n),如果向量变大,则为字符串的数量;O(l),如果向量变小,则为已删除字符串的总长度,可能更少,具体取决于内存管理。
igraph_error_t igraph_strvector_reserve(igraph_strvector_t *sv, igraph_integer_t capacity);
igraph 字符串向量是灵活的,它们可以增长和缩小。但是,增长偶尔需要复制向量中的数据。为了避免这种情况,您可以调用此函数来为向量的未来增长保留空间。
请注意,此函数不会更改字符串向量的大小。让我们看一个小例子来阐明这一点:如果您为 100 个字符串保留空间,并且您的向量的大小为(并且仍然是)60,那么您肯定可以在复制之前向向量添加额外的 40 个字符串。
参数:
|
字符串向量对象。 |
|
字符串向量的新的已分配大小。 |
返回值:
错误代码:如果没有足够的内存,则为 |
时间复杂度:依赖于操作系统,应该在 O(n) 左右,n 是向量的新已分配大小。
void igraph_strvector_resize_min(igraph_strvector_t *sv);
此函数尝试释放字符串向量中未使用的保留存储空间。如果成功,igraph_strvector_size()
和 igraph_strvector_capacity()
将相同。字符串向量中的数据始终被保留,即使释放不成功。
参数:
|
字符串向量。 |
时间复杂度:取决于操作系统,最多 O(n)。
igraph_integer_t igraph_strvector_size(const igraph_strvector_t *sv);
参数:
|
字符串向量。 |
返回值:
字符串向量的长度。 |
时间复杂度:O(1)。
igraph_integer_t igraph_strvector_capacity(const igraph_strvector_t *sv);
参数:
|
字符串向量。 |
返回值:
字符串向量的容量。 |
时间复杂度:O(1)。
igraph_error_t igraph_strvector_copy(igraph_strvector_t *to, const igraph_strvector_t *from);
自 0.10.0 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_strvector_init_copy()
。
igraph_error_t igraph_strvector_add(igraph_strvector_t *sv, const char *value);
自 0.10.0 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_strvector_push_back()
。
igraph_error_t igraph_strvector_set2( igraph_strvector_t *sv, igraph_integer_t idx, const char *value, size_t len );
自 0.10.0 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_strvector_set_len()
。
igraph_vector_list_t 数据类型本质上是一个 igraph_vector_t 对象的列表,具有自动内存管理。它类似于 C++ 标准库中的 vector 模板(但比它简单得多),其中元素本身就是向量。
存在 igraph_vector_list_t 的多个变体;基本变体存储双精度向量(即,每个项都是一个 igraph_vector_t
),但也有整数的 igraph_vector_int_list_t(其中每个项都是一个 igraph_vector_int_t),双精度矩阵的 igraph_matrix_list_t 等。以下列表总结了当前库中可用的变体
igraph_vector_list_t 用于浮点数向量的列表 (igraph_vector_t)
igraph_vector_int_list_t 用于整数向量的列表 (igraph_vector_int_t)
igraph_matrix_list_t 用于浮点数矩阵的列表 (igraph_matrix_t)
igraph_graph_list_t 用于图的列表 (igraph_t)
在许多情况下,igraph 中使用向量列表,例如,返回路径、集团或顶点集合的列表时。期望或返回数字向量列表的函数通常使用 igraph_vector_list_t 或 igraph_vector_int_list_t 来实现此目的。当列表中的向量应该保存顶点或边标识符时,使用整数向量列表;而当向量应该保存小数值或无穷大时,使用浮点向量列表。
igraph_vector_list_t 对象及其变体中的元素从零开始索引,我们遵循通常的 C 约定。
以下针对 igraph_vector_list_t 描述的几乎所有函数也存在于所有其他向量列表变体中。这些变体没有单独记录;如果您需要另一个变体的函数,您可以简单地将 vector_list
替换为 vector_int_list
。例如,要初始化整数向量列表,您需要使用 igraph_vector_int_list_init
(),而不是 igraph_vector_list_init()
。
在深入了解与向量列表相关的函数的详细描述之前,我们还必须讨论这些对象的所有权规则。最重要的规则是列表中的向量归列表本身所有,这意味着用户不负责为向量分配内存或释放与向量关联的内存。列表负责在列表中创建新项时分配和初始化向量,并且列表还负责在从列表中删除项而不将所有权传递给用户时销毁这些项。因此,列表可能不包含“未初始化”或“空”项;每个项在存在时都会被初始化。如果您创建一个包含一百万个向量的列表,您不仅为一百万个 igraph_vector_t
对象分配内存,而且还初始化了一百万个向量。此外,如果您有一个包含一百万个向量的列表,并且您通过调用 igraph_vector_list_clear()
清除该列表,则该列表将隐式销毁这些列表,并且您可能持有的任何指向项的指针都会立即失效。
说到指针,使用列表中向量的典型方法是通过 igraph_vector_list_get_ptr()
方法获取指向其中一个项的指针,然后将此指针传递给可以操作 igraph_vector_t
对象的函数。但是,请注意,指针是临时的,因为当列表被修改时,它们可能会失效,因为如果需要更多空间,修改可能涉及重新分配列表的内部存储,并且您获得的指针不会跟随重新分配。这种限制在 igraph_vector_list_t
的实际使用中并不经常出现,总的来说,自动内存管理的优势超过了这种限制。
igraph_vector_list_t 对象在使用前必须初始化,这类似于在它们上面调用构造函数。igraph_vector_list_init()
是基本构造函数;它创建给定长度的列表,并将新创建列表中的每个向量初始化为零长度。
如果不再需要 igraph_vector_list_t 对象,则应通过调用 igraph_vector_list_t 析构函数 igraph_vector_list_destroy()
来销毁它以释放其已分配的内存。由于所有权规则,调用析构函数还会销毁向量列表中的所有向量。如果您想保留向量列表中的一些向量,您需要使用 igraph_vector_init_copy()
或 igraph_vector_update()
复制它们,或者您需要通过调用 igraph_vector_list_pop_back()
、igraph_vector_list_remove()
或 igraph_vector_list_remove_fast()
将它们从列表中删除并取得所有权。
igraph_error_t igraph_vector_list_init(igraph_vector_list_t *v, igraph_integer_t size);
此函数构造给定大小的向量列表,并将新创建列表中的每个向量初始化为空向量。
由此函数初始化的向量对象由列表拥有,并且当列表被 igraph_vector_list_destroy()
销毁时,它们将被自动销毁。
参数:
|
指向尚未初始化的向量列表的指针。 |
|
列表的大小。 |
返回值:
错误代码:如果没有足够的内存,则为 |
时间复杂度:取决于操作系统,分配 O(n) 个元素并初始化相应向量所需的“时间”量;n 是元素的数量。
void igraph_vector_list_destroy(igraph_vector_list_t *v);
通过 igraph_vector_list_init()
初始化的所有列表都应由此函数正确销毁。如果您想再次使用销毁的向量列表,则需要通过 igraph_vector_list_init()
重新初始化它。
当列表被销毁时,列表中的向量也会被隐式销毁。
参数:
|
指向要销毁的(先前已初始化的)列表对象的指针。 |
时间复杂度:操作系统相关。
可以使用 igraph_vector_list_get_ptr()
函数访问向量列表的元素。该函数返回指向列表中给定索引处的向量的指针,然后您可以将此指针传递给其他可以查询或操作向量的函数。只要列表本身没有被修改,指针本身就可以保证保持有效;但是,对列表的任何修改都会使指针失效,即使是与指针指向的向量看似无关的修改(例如,在列表末尾添加新向量)。这是因为如果新元素不适合已分配的空间,则列表数据结构可能被迫重新分配其内部存储,并且不能保证重新分配的块保留在同一内存位置(通常它会被移动到其他地方)。
请注意,适用于普通向量的标准 VECTOR
宏不适用于向量列表来访问第 i 个元素(但当然您可以使用它来索引您从向量列表中使用 igraph_vector_list_get_ptr()
检索到的现有向量)。这是因为宏表示法将允许一个人用另一个向量覆盖列表中的向量,而列表对此一无所知,因此列表将无法销毁被新向量覆盖的向量。
igraph_vector_list_tail_ptr()
返回指向列表中最后一个向量的指针,如果列表为空,则返回 NULL
。没有 igraph_vector_list_head_ptr()
,但是,很容易编写 igraph_vector_list_get_ptr(v, 0)
代替。
igraph_vector_t *igraph_vector_list_get_ptr(const igraph_vector_list_t *v, igraph_integer_t pos);
参数:
|
列表对象。 |
|
向量在列表中的位置。第一个向量的位置为零。 |
返回值:
指向向量的指针。只要底层向量列表未被修改,它就保持有效。 |
时间复杂度:O(1)。
igraph_vector_t *igraph_vector_list_tail_ptr(const igraph_vector_list_t *v);
参数:
|
列表对象。 |
返回值:
指向列表中最后一个向量的指针,如果列表为空,则为 |
时间复杂度:O(1)。
void igraph_vector_list_set(igraph_vector_list_t *v, igraph_integer_t pos, igraph_vector_t *e);
此函数销毁列表中给定索引 pos
处已有的向量,并将其替换为 e
指向的向量。 e
指向的向量的所有权由列表获取,因此用户不再负责销毁 e
;当列表本身被销毁或如果 e
从列表中删除而没有将所有权传递给其他地方时,它将被销毁。
参数:
|
列表对象。 |
|
要修改的列表中的索引。 |
|
要在列表中设置的向量。 |
时间复杂度:O(1)。
igraph_bool_t igraph_vector_list_empty(const igraph_vector_list_t *v);
参数:
|
列表对象。 |
返回值:
如果列表的大小为零,则为 True,否则为 false。 |
时间复杂度:O(1)。
igraph_integer_t igraph_vector_list_size(const igraph_vector_list_t *v);
返回列表中存储的向量数量。
参数:
|
列表对象 |
返回值:
列表的大小。 |
时间复杂度:O(1)。
igraph_integer_t igraph_vector_list_capacity(const igraph_vector_list_t *v);
请注意,这可能与列表的大小不同(通过 igraph_vector_list_size()
查询),并且指定列表可以容纳多少向量,而无需重新分配。
参数:
|
指向要查询的(先前已初始化的)列表对象的指针。 |
返回值:
已分配容量。 |
另请参阅:
时间复杂度:O(1)。
igraph_vector_list_clear
— 从向量列表中删除所有元素。igraph_vector_list_reserve
— 为列表保留内存。igraph_vector_list_resize
— 调整向量列表的大小。igraph_vector_list_push_back
— 将现有向量附加到列表,转移所有权。igraph_vector_list_push_back_copy
— 将向量的副本附加到列表。igraph_vector_list_push_back_new
— 将新向量附加到列表。igraph_vector_list_pop_back
— 从向量列表中删除最后一项并将所有权转移给调用方。igraph_vector_list_insert
— 将现有向量插入到列表,转移所有权。igraph_vector_list_insert_copy
— 将向量的副本插入到列表。igraph_vector_list_insert_new
— 将新向量插入到列表。igraph_vector_list_remove
— 从向量列表中删除给定索引处的项并将所有权转移给调用方。igraph_vector_list_remove_fast
— 删除向量列表中给定索引处的项,将最后一项移动到其位置并将所有权转移给调用方。igraph_vector_list_discard
— 丢弃向量列表中给定索引处的项。igraph_vector_list_discard_back
— 丢弃向量列表中的最后一项。igraph_vector_list_discard_fast
— 丢弃向量列表中给定索引处的项并将最后一项移动到其位置。
void igraph_vector_list_clear(igraph_vector_list_t *v);
此函数将列表的大小设置为零,并且还会销毁在清除列表之前放置在列表中的所有向量。
参数:
|
列表对象。 |
时间复杂度:O(n),n 是要删除的项的数量。
igraph_error_t igraph_vector_list_reserve(igraph_vector_list_t *v, igraph_integer_t capacity);
igraph 列表是灵活的,它们可以增长和缩小。但是,增长偶尔需要复制列表中的数据。为了避免这种情况,您可以调用此函数来为列表的未来增长保留空间。
请注意,此函数不会更改列表的大小,也不会初始化任何新向量。让我们看一个小例子来阐明这一点:如果您为 100 个元素保留空间,并且您的列表的大小为(并且仍然是)60,那么您肯定可以在复制之前向列表中添加额外的 40 个新向量。
参数:
|
列表对象。 |
|
列表的新的已分配大小。 |
返回值:
错误代码:如果没有足够的内存,则为 |
时间复杂度:取决于操作系统,应该大约为 O(n),n 是列表的新已分配大小。
igraph_error_t igraph_vector_list_resize(igraph_vector_list_t *v, igraph_integer_t new_size);
请注意,此函数不会释放任何内存,只是将列表的大小设置为给定的大小。另一方面,如果新大小大于以前的大小,它可以分配更多内存。
当新大小大于当前大小时,列表中新添加的向量将被初始化为空向量。当新大小小于当前大小时,从列表末尾删除的向量将被自动销毁。
参数:
|
列表对象 |
|
列表的新大小。 |
返回值:
错误代码,如果没有足够的内存,则为 |
另请参阅:
|
时间复杂度:如果新尺寸较小,则为 O(m)(m 是从列表中删除的项数);如果新尺寸较大,则取决于操作系统。 在后一种情况下,通常约为 O(n),其中 n 是向量的新尺寸。
igraph_error_t igraph_vector_list_push_back(igraph_vector_list_t *v, igraph_vector_t *e);
此函数将列表大小调整为一个元素更长,并将列表中最后一个元素设置为指定的向量 e
。 列表获得向量的所有权,因此用户不再负责释放 e
;向量将在列表本身被销毁时或如果 e
从列表中移除而没有将所有权传递给其他地方时被销毁。
参数:
|
列表对象。 |
|
要追加到列表的向量的指针。 |
返回值:
错误代码: |
时间复杂度:取决于操作系统。 重要的是,对该函数的 n 个后续调用的时间复杂度为 O(n),即使 igraph_vector_list_reserve()
没有为新元素预留任何空间。 这是通过类似于 C++ vector 类的技巧实现的:每次为向量分配更多内存时,额外分配的内存大小与向量的当前长度相同。(我们在此假设内存分配的时间复杂度最多是线性的)。
igraph_error_t igraph_vector_list_push_back_copy(igraph_vector_list_t *v, const igraph_vector_t *e);
此函数将列表大小调整为一个元素更长,并将作为参数指定的向量复制到最后一个元素。 新添加的元素归列表所有,但原始向量的所有权由调用者保留。
参数:
|
列表对象。 |
|
要复制到列表末尾的向量的指针。 |
返回值:
错误代码: |
时间复杂度:与 igraph_vector_list_push_back()
相同,加上复制向量所需的时间(对于向量中的 n 个元素,时间复杂度为 O(n))。
igraph_error_t igraph_vector_list_push_back_new(igraph_vector_list_t *v, igraph_vector_t** e);
此函数将列表大小调整为一个元素更长。 新添加的元素将是一个空向量,归列表所有。 如果最后一个参数不是 NULL
,则会在最后一个参数中返回指向新添加元素的指针。
参数:
|
列表对象。 |
|
指向向量指针的指针;这将更新为指向新添加的向量。 如果您不需要指向新添加的向量的指针,则可能为 |
返回值:
错误代码: |
时间复杂度:与 igraph_vector_list_push_back()
相同。
igraph_vector_t igraph_vector_list_pop_back(igraph_vector_list_t *v);
此函数从列表中删除最后一个向量。 从列表中删除的向量将被返回,其所有权将被传递回调用者;换句话说,调用者有责任在不再需要该向量时销毁该向量。
使用空向量调用此函数是一个错误。
参数:
|
列表对象。 |
|
指向 |
时间复杂度:O(1)。
igraph_error_t igraph_vector_list_insert(igraph_vector_list_t *v, igraph_integer_t pos, igraph_vector_t *e);
此函数将 e
插入到列表中给定的索引处,并根据需要将其他项目移向列表的末尾。 列表获得向量的所有权,因此用户不再负责释放 e
;向量将在列表本身被销毁时或如果 e
从列表中移除而没有将所有权传递给其他地方时被销毁。
参数:
|
列表对象。 |
|
要在其中插入新元素的位置。 |
|
要插入列表中的向量的指针。 |
返回值:
错误代码: |
时间复杂度:O(n)。
igraph_error_t igraph_vector_list_insert_copy(igraph_vector_list_t *v, igraph_integer_t pos, const igraph_vector_t *e);
此函数将 e
的副本插入到列表中给定的索引处,并根据需要将其他项目移向列表的末尾。 新添加的元素归列表所有,但原始向量的所有权由调用者保留。
参数:
|
列表对象。 |
|
要在其中插入新元素的位置。 |
|
要复制到列表末尾的向量的指针。 |
返回值:
错误代码: |
时间复杂度:与 igraph_vector_list_insert()
相同,加上复制向量所需的时间(对于向量中的 n 个元素,时间复杂度为 O(n))。
igraph_error_t igraph_vector_list_insert_new(igraph_vector_list_t *v, igraph_integer_t pos, igraph_vector_t** e);
此函数将新创建的空向量插入到列表中给定的索引处,并根据需要将其他项目移向列表的末尾。 新添加的向量归列表所有。 如果最后一个参数不是 NULL
,则会在最后一个参数中返回指向新元素的指针。
参数:
|
列表对象。 |
|
要在其中插入新元素的位置。 |
|
指向向量指针的指针;这将更新为指向新添加的向量。 如果您不需要指向新添加的向量的指针,则可能为 |
返回值:
错误代码: |
时间复杂度:与 igraph_vector_list_push_back()
相同。
igraph_error_t igraph_vector_list_remove(igraph_vector_list_t *v, igraph_integer_t index, igraph_vector_t *result);
此函数从列表中删除给定索引处的向量,并将列表中所有后续项目向左移动一个槽以填充空白。 从列表中删除的向量将在 e
中返回,其所有权将传递回调用者;换句话说,调用者有责任在不再需要该向量时销毁该向量。
参数:
|
列表对象。 |
|
要删除的项目的索引。 |
|
指向 |
另请参阅:
如果您对删除的项目不感兴趣,请使用 |
时间复杂度:O(n),其中 n 是列表中的项目数。
igraph_error_t igraph_vector_list_remove_fast(igraph_vector_list_t *v, igraph_integer_t index, igraph_vector_t *result);
此函数从列表中删除给定索引处的向量,将列表中的最后一个项目移动到 index
以填充空白,然后将删除的向量的所有权传递回调用者;换句话说,调用者有责任在不再需要该向量时销毁该向量。
参数:
|
列表对象。 |
|
要删除的项目的索引。 |
|
指向 |
另请参阅:
如果您想保留列表中项目的顺序,请使用 |
时间复杂度:O(1)。
void igraph_vector_list_discard(igraph_vector_list_t *v, igraph_integer_t index);
此函数从列表中删除给定索引处的向量,并将列表中所有后续项目向左移动一个槽以填充空白。 从列表中删除的向量将自动销毁。
参数:
|
列表对象。 |
|
要丢弃和销毁的项目的索引。 |
另请参阅:
如果您不关心列表中项目的顺序,请使用 |
时间复杂度:O(n),其中 n 是列表中的项目数。
void igraph_vector_list_discard_back(igraph_vector_list_t *v);
此函数从列表中删除最后一个向量并销毁它。
参数:
|
列表对象。 |
时间复杂度:O(1)。
void igraph_vector_list_discard_fast(igraph_vector_list_t *v, igraph_integer_t index);
此函数从列表中删除给定索引处的向量,并将列表中的最后一个项目移动到 index
以填充空白。 从列表中删除的向量将自动销毁。
参数:
|
列表对象。 |
|
要丢弃和销毁的项目的索引。 |
另请参阅:
如果您想保留列表中项目的顺序,请使用 |
时间复杂度:O(1)。
igraph_error_t igraph_vector_list_permute(igraph_vector_list_t *v, const igraph_vector_int_t* index);
此函数接受列表 v
和相应的索引向量 index
,并置换 v
的元素,以便在函数执行后,v
[index[i]] 移动到 v
[i]。
使用不表示有效置换的索引向量调用此函数是错误的。 索引向量中的每个元素都必须介于 0 和列表长度减 1 之间(包括 0 和列表长度减 1),并且每个这样的元素必须只出现一次。 该函数不会尝试验证索引向量。 如果索引向量不满足这些条件,则可能会发生内存泄漏。
此函数采用的索引向量与从 igraph_vector_list_sort_ind()
返回的索引向量兼容;传入来自 igraph_vector_list_sort_ind()
的索引向量将对原始向量进行排序。
参数:
|
要置换的列表 |
|
索引向量 |
时间复杂度:O(n),列表中的项目数。
void igraph_vector_list_sort(igraph_vector_list_t *v, int (*cmp)(const igraph_vector_t*, const igraph_vector_t*));
参数:
|
指向已初始化列表对象的指针。 |
|
一个比较函数,它接受指向两个向量的指针,如果两个向量被认为是相等的,则返回零;如果第一个向量较小,则返回任何负数;如果第二个向量较小,则返回任何正数。 |
返回值:
错误代码。 |
时间复杂度:对于 n 个元素为 O(n log n)。
igraph_error_t igraph_vector_list_sort_ind( igraph_vector_list_t *v, igraph_vector_int_t *inds, int (*cmp)(const igraph_vector_t*, const igraph_vector_t*) );
将一个未排序的列表 v
作为输入,并计算一个索引数组 inds
,使得 v[ inds[i] ](i 从 0 递增)是根据比较函数 cmp
排序的数组。 相同元素的索引顺序未定义。
参数:
|
要排序的列表 |
|
索引的输出数组。必须初始化,但将调整大小 |
|
一个比较函数,它接受指向两个向量的指针,如果两个向量被认为是相等的,则返回零;如果第一个向量较小,则返回任何负数;如果第二个向量较小,则返回任何正数。 |
返回值:
错误代码。 |
时间复杂度:对于 n 个元素为 O(n log n)。
有时,使用邻接表格式的图更容易:向量列表;每个向量都包含给定顶点的相邻顶点或关联边。 通常,如果我们需要多次迭代所有顶点的邻居,则此表示形式很好。 例如,当查找所有顶点对之间的最短路径或计算所有顶点的紧密度中心性时。
igraph_adjlist_t 存储图的邻接表。 创建后,它独立于原始图,可以使用通常的向量操作自由修改,该图不受影响。 例如,邻接表可用于有效地重新连接图的边。 如果对每个删除和插入操作都使用直接的 igraph_delete_edges()
和 igraph_add_edges()
组合,这对于每次删除和插入操作都需要 O(|V|+|E|) 时间,因此如果重新连接许多边,则速度非常慢。 将图提取到邻接表中,对邻接表的向量执行所有重新连接操作,然后创建一个新图需要(取决于重新连接的具体方式)整个重新连接过程通常需要 O(|V|+|E|) 时间。
惰性邻接表略有不同。 创建惰性邻接表时,不会查询顶点的邻居,只会为向量分配一些内存。 首次对顶点 v 调用 igraph_lazy_adjlist_get()
时,会查询 v 的邻居并将其存储在邻接表的向量中,因此无需再次查询它们。 如果您有一个至少是线性操作(因为初始化通常是关于顶点数量的线性操作),但您不知道在计算期间会访问多少个顶点,则惰性邻接表很方便。
示例 7.12. 文件 examples/simple/adjlist.c
#include <igraph.h> int main(void) { igraph_t g, g2; igraph_adjlist_t adjlist; igraph_bool_t iso; /* Create a directed out-tree, convert it into an adjacency list * representation, then reconstruct the graph from the tree and check * whether the two are isomorphic (they should be) */ igraph_kary_tree(&g, 42, 3, IGRAPH_TREE_OUT); igraph_adjlist_init(&g, &adjlist, IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE); igraph_adjlist(&g2, &adjlist, IGRAPH_OUT, /* duplicate = */ 0); igraph_isomorphic(&g, &g2, &iso); if (!iso) { return 1; } igraph_adjlist_destroy(&adjlist); igraph_destroy(&g2); igraph_destroy(&g); return 0; }
igraph_adjlist_init
— 从给定图构造顶点邻接表。igraph_adjlist_init_empty
— 初始化一个空邻接表。igraph_adjlist_init_complementer
— 补图的邻接表。igraph_adjlist_init_from_inclist
— 从关联列表构造顶点邻接表。igraph_adjlist_destroy
— 释放邻接表的内存。igraph_adjlist_get
— 查询邻接表中的向量。igraph_adjlist_size
— 返回邻接表中的顶点数。igraph_adjlist_clear
— 从邻接表中删除所有边。igraph_adjlist_sort
— 对邻接表中的每个向量进行排序。igraph_adjlist_simplify
— 简化邻接表。
igraph_error_t igraph_adjlist_init(const igraph_t *graph, igraph_adjlist_t *al, igraph_neimode_t mode, igraph_loops_t loops, igraph_multiple_t multiple);
创建一个向量列表,其中包含图中所有顶点的邻居。 邻接表在创建后独立于该图,例如,可以销毁和修改该图,邻接表包含其初始化时的图的状态。
此函数以排序顺序返回每个邻居列表,就像 igraph_neighbors()
一样。
从 igraph 0.10 开始,将 loops
设置为与 IGRAPH_LOOPS_TWICE
不同的值,或者将 multiple
设置为与 IGRAPH_MULTIPLE
不同的值,会产生少量性能成本。
参数:
|
输入图。 |
|
指向未初始化的 igraph_adjlist_t 对象的指针。 |
|
一个常量,用于指定邻接表中是否只包含传出 ( |
|
指定如何处理循环边。 |
|
指定如何处理多(并行)边。 |
返回值:
错误代码。 |
另请参阅:
用于获取各个顶点的邻居列表的 |
时间复杂度:O(|V|+|E|),顶点数和边数的线性关系。
igraph_error_t igraph_adjlist_init_empty(igraph_adjlist_t *al, igraph_integer_t no_of_nodes);
创建一个向量列表,每个顶点对应一个向量。 当您构造使用邻接表表示的图时,这很有用,因为它不需要您的图已经存在。
参数:
|
顶点的数量 |
|
指向未初始化的 igraph_adjlist_t 对象的指针。 |
返回值:
错误代码。 |
时间复杂度:O(|V|),顶点数量呈线性。
igraph_error_t igraph_adjlist_init_complementer(const igraph_t *graph, igraph_adjlist_t *al, igraph_neimode_t mode, igraph_bool_t loops);
此函数为输入图的补图创建邻接表。 在补图中,所有原始图中不存在的边都存在。 输入图中的多条边将被忽略。
此函数以排序顺序返回每个邻居列表。
参数:
|
输入图。 |
|
指向尚未初始化的邻接表的指针。 |
|
一个常量,用于指定要在邻接表中包含传出 ( |
|
是否考虑循环边。 |
返回值:
错误代码。 |
另请参阅:
时间复杂度:O(|V|^2+|E|),顶点数量呈二次方。
igraph_error_t igraph_adjlist_init_from_inclist( const igraph_t *graph, igraph_adjlist_t *al, const igraph_inclist_t *il);
在某些算法中,拥有邻接表和同一图的关联列表表示形式很有用,并且在许多情况下,如果它们彼此一致,则最有用,即可以保证顶点 v 的邻接列表的第 i 个条目中的顶点 ID 是同一顶点的关联列表的第 i 个条目中边的另一个端点。 此函数通过查找关联列表中每条边的端点并构造相应的邻接向量,从相应的关联列表创建这样的邻接列表。
邻接表在创建后独立于该图或关联列表;换句话说,对图或关联列表所做的修改不会反映在邻接列表中。
参数:
|
输入图。 |
|
指向未初始化的 igraph_adjlist_t 对象的指针。 |
|
指向将转换为邻接列表的已初始化 igraph_inclist_t 对象的指针。 |
返回值:
错误代码。 |
时间复杂度:O(|V|+|E|),顶点数和边数的线性关系。
#define igraph_adjlist_get(al,no)
返回指向邻接表中的 igraph_vector_int_t
对象的指针。 可以根据需要修改该向量。
参数:
|
邻接表对象。 |
|
将返回其相邻顶点的顶点。 |
返回值:
指向 |
时间复杂度:O(1)。
igraph_integer_t igraph_adjlist_size(const igraph_adjlist_t *al);
参数:
|
邻接表。 |
返回值:
邻接表中的顶点数。 |
时间复杂度:O(1)。
void igraph_adjlist_clear(igraph_adjlist_t *al);
参数:
|
邻接表。 时间复杂度:取决于内存管理,通常为 O(n),其中 n 是邻接表中元素的总数。 |
void igraph_adjlist_sort(igraph_adjlist_t *al);
对邻接表的每个向量进行排序。 请注意,igraph_adjlist_init()
已经生成排序的邻居列表。 当邻接表以不同的方式生成或以不保留排序顺序的方式修改时,此函数很有用。
参数:
|
邻接表。 |
时间复杂度:O(n log n),n 是邻接表中元素的总数。
igraph_error_t igraph_adjlist_simplify(igraph_adjlist_t *al);
简化邻接表,即删除循环边和多条边。
当使用 igraph_adjlist_init()
创建邻接表时,请改为使用该函数的 loops
和 multiple
参数。
参数:
|
邻接表。 |
返回值:
错误代码。 |
时间复杂度:O(|V|+|E|),在边和顶点的数量上是线性的。
igraph_error_t igraph_inclist_init(const igraph_t *graph, igraph_inclist_t *il, igraph_neimode_t mode, igraph_loops_t loops);
创建一个向量列表,其中包含所有顶点的关联边。 关联列表在创建后独立于该图,图对象的后续更改不会更新关联列表,并且对关联列表的更改不会更新该图。
当 mode
是 IGRAPH_IN
或 IGRAPH_OUT
时,每个边 ID 将在关联列表中出现一次。当 mode
是 IGRAPH_ALL
时,每个边 ID 将在关联列表中出现两次,一次表示源顶点,一次表示目标边。 这也意味着循环边的边 ID 可能会为同一顶点出现两次。使用 loops
参数来控制是否会出现这种情况 (IGRAPH_LOOPS_TWICE
) 或不出现 (IGRAPH_LOOPS_ONCE
或 IGRAPH_NO_LOOPS
)。
从 igraph 0.10 开始,将 loops
设置为与 IGRAPH_LOOPS_TWICE
不同的值会产生少量性能成本。
参数:
|
输入图。 |
|
指向未初始化的关联列表的指针。 |
|
一个常量,用于指定是否将传入边 ( |
|
指定如何处理循环边。 |
返回值:
错误代码。 |
时间复杂度:O(|V|+|E|),顶点数和边数的线性关系。
#define igraph_inclist_get(il,no)
返回指向关联列表中包含边 ID 的 igraph_vector_int_t 对象的指针。 可以根据需要修改、调整大小等向量。
参数:
|
指向关联列表的指针。 |
|
将为其返回关联边的顶点。 |
返回值:
指向 igraph_vector_int_t 对象的指针。 |
时间复杂度:O(1)。
igraph_error_t igraph_lazy_adjlist_init(const igraph_t *graph, igraph_lazy_adjlist_t *al, igraph_neimode_t mode, igraph_loops_t loops, igraph_multiple_t multiple);
为顶点创建一个惰性邻接表。 此函数仅分配一些内存用于存储邻接表的向量,但不会查询相邻顶点,仅在调用 igraph_lazy_adjlist_get()
时才会查询。 邻居列表将按排序顺序返回。
从 igraph 0.10 开始,将 loops
设置为与 IGRAPH_LOOPS_TWICE
不同的值,或者将 multiple
设置为与 IGRAPH_MULTIPLE
不同的值,会产生少量性能成本。
参数:
|
输入图。 |
|
指向未初始化的邻接表对象的指针。 |
|
一个常量,用于指定邻接表中是否只包含传出 ( |
|
指定如何处理循环边。 |
|
指定如何处理多(并行)边。 |
返回值:
错误代码。 |
另请参阅:
用于获取各个顶点的邻居列表的 |
时间复杂度:O(|V|),顶点数,可能取决于底层内存管理。
void igraph_lazy_adjlist_destroy(igraph_lazy_adjlist_t *al);
释放为惰性邻接表分配的所有内存。
参数:
|
要释放的邻接表。 |
时间复杂度:取决于内存管理。
#define igraph_lazy_adjlist_get(al,no)
如果首次为顶点调用该函数,则结果将存储在邻接列表中,并且在再次查询同一顶点的邻居时,不需要进一步的查询操作。
参数:
|
惰性邻接表。 |
|
要查询的顶点 ID。 |
返回值:
指向向量的指针,或者发生错误时指向 |
另请参阅:
使用 |
时间复杂度:首次为 O(d),顶点数量,后续调用为 O(1)。
#define igraph_lazy_adjlist_has(al,no)
参数:
|
惰性邻接表。 |
|
要查询的顶点 ID。 |
返回值:
如果已计算并存储此顶点的相邻顶点,则为 True,否则为 false。 |
时间复杂度:O(1)。
igraph_error_t igraph_lazy_inclist_init(const igraph_t *graph, igraph_lazy_inclist_t *il, igraph_neimode_t mode, igraph_loops_t loops);
为边创建一个惰性关联列表。 此函数仅分配一些内存用于存储关联列表的向量,但不会查询关联边,仅在调用 igraph_lazy_inclist_get()
时才会查询。
当 mode
是 IGRAPH_IN
或 IGRAPH_OUT
时,每个边 ID 将在关联列表中出现一次。当 mode
是 IGRAPH_ALL
时,每个边 ID 将在关联列表中出现两次,一次表示源顶点,一次表示目标边。 这也意味着循环边的边 ID 将为同一顶点出现两次。
从 igraph 0.10 开始,将 loops
设置为与 IGRAPH_LOOPS_TWICE
不同的值会产生少量性能成本。
参数:
|
输入图。 |
|
指向未初始化的关联列表的指针。 |
|
一个常量,用于指定是否考虑传入边 ( |
|
指定如何处理循环边。 |
返回值:
错误代码。 |
时间复杂度:O(|V|),顶点数,可能。 但这也取决于底层内存管理。
void igraph_lazy_inclist_destroy(igraph_lazy_inclist_t *il);
释放为惰性关联列表分配的所有内存。
参数:
|
要释放的关联列表。 |
时间复杂度:取决于内存管理。
#define igraph_lazy_inclist_get(il,no)
如果该函数是第一次为一个顶点调用,则结果存储在关联列表中,当再次查询同一顶点的关联边时,不需要进一步的查询操作。
参数:
|
惰性关联列表对象。 |
|
要查询的顶点 ID。 |
返回值:
指向向量的指针,或者发生错误时指向 |
另请参阅:
|
时间复杂度:O(d),首次调用时为关联边的数量,对于使用相同 no
参数的后续调用,时间复杂度为 O(1)。
#define igraph_lazy_inclist_has(il,no)
参数:
|
惰性关联列表。 |
|
要查询的顶点 ID。 |
返回值:
如果该顶点的关联边已被计算并存储,则为 True;否则为 false。 |
时间复杂度:O(1)。
igraph_psumtree_init
— 初始化部分前缀和树。igraph_psumtree_destroy
— 销毁部分前缀和树。igraph_psumtree_size
— 返回树的大小。igraph_psumtree_get
— 检索树中与某个项对应的值。igraph_psumtree_sum
— 返回树中叶子的值的总和。igraph_psumtree_search
— 给定一个值,在树中查找一个项。igraph_psumtree_update
— 更新树中与某个项关联的值。igraph_psumtree_reset
— 将树中的所有值重置为零。igraph_psumtree_t 数据类型表示部分前缀和树。 部分前缀和树是一种数据结构,可用于从动态概率的离散概率分布中抽取样本,这些概率会频繁更新。 这是通过创建一个二叉树来实现的,其中叶子是各项。 每个叶子包含与该项对应的概率。 树的中间节点始终包含其两个子节点的总和。 当叶节点的值更新时,其祖先的值也会相应更新。
可以通过生成 0(包括)到树的根的值(不包括)之间的均匀随机数,然后按照以下步骤沿着树的分支进行,从而从树表示的概率分布中抽取样本。 在每个步骤中,将当前节点中的值与生成的数字进行比较。 如果节点中的值较大,则采用树的左分支;否则,生成的数字减去节点中的值,然后采用树的右分支,直到到达叶节点。
请注意,仅当树中的所有值均为非负数时,采样过程才有效。 这是由对象强制执行的;特别是,尝试为某一项设置负值会产生 igraph 错误。
igraph_error_t igraph_psumtree_init(igraph_psumtree_t *t, igraph_integer_t size);
树使用固定数量的元素进行初始化。 初始化后,与每个元素对应的值均为零。
参数:
|
要初始化的树。 |
|
树中的元素数。 必须至少为一。 |
返回值:
错误代码,如果没有足够的内存,通常为 |
时间复杂度:对于包含 n 个元素的树,时间复杂度为 O(n)
void igraph_psumtree_destroy(igraph_psumtree_t *t);
由 igraph_psumtree_init()
初始化的所有部分前缀和树都应通过此函数正确销毁。 如果要再次使用已销毁的树,则需要通过 igraph_psumtree_init()
重新初始化。
参数:
|
指向要销毁的(先前已初始化)树的指针。 |
时间复杂度:操作系统相关。
igraph_integer_t igraph_psumtree_size(const igraph_psumtree_t *t);
参数:
|
树对象 |
返回值:
树中的离散项的数量。 |
时间复杂度:O(1)。
igraph_real_t igraph_psumtree_get(const igraph_psumtree_t *t, igraph_integer_t idx);
参数:
|
要查询的树。 |
|
要检索其值的项的索引。 |
返回值:
与给定索引的项对应的值。 |
时间复杂度:O(1)
igraph_real_t igraph_psumtree_sum(const igraph_psumtree_t *t);
参数:
|
树对象 |
返回值:
树中叶子的值的总和。 |
时间复杂度:O(1)。
igraph_error_t igraph_psumtree_search(const igraph_psumtree_t *t, igraph_integer_t *idx, igraph_real_t search);
此函数查找具有最低索引的项,在该项中,所有索引较低的项的总和小于或等于给定值,并且所有索引较低的项的总和加上该项本身大于给定值。
如果您将部分前缀和树视为从离散概率分布中采样的工具,那么重复调用此函数,并将 0(包括)到树中所有值的总和(不包括)范围内的均匀分布的随机数作为参数,将以与其关联值成比例的概率对树中的项进行采样。
参数:
|
要查询的树。 |
|
此处返回项的索引。 |
|
用于搜索的值。 必须在区间 |
返回值:
错误代码;当前搜索始终成功。 |
时间复杂度:O(log n),其中 n 是树中项的数量。
igraph_bitset_t 数据类型是包含布尔值的数组的简单而有效的接口。 它类似于 C++ 标准库中的 bitset 模板,尽管主要区别在于 C++ 版本的位集大小在编译时初始化。
igraph_bitset_t 类型使用 O(n/w) 空间来存储 n 个元素,其中 w 是 igraph_integer_t 的位宽,igraph_integer_t 是整个库中使用的整数类型(32 或 64)。 有时它们会使用更多空间,这是因为位集可以缩小,但即使它们缩小,当前的实现也不会释放任何内存。
igraph_bitset_t 对象及其变体中的元素从零开始索引,我们在此遵循通常的 C 约定。 位集从右到左索引,这意味着索引 0 是最低有效位,索引 n - 1
是最高有效位。
位集的元素始终占用单个内存块,可以使用 VECTOR()
宏查询此内存块的起始地址。 这样,位集对象可以与标准数学库(如 GNU 科学库)一起使用。
请注意,虽然位集函数的接口类似于 igraph 的向量函数,但有一个主要区别:位集函数(例如 igraph_bitset_and()
)不会验证输入参数的大小是否兼容,也不会自动调整输出参数的大小。 这样做是用户的责任。
igraph_bitset_t 对象在使用之前必须初始化,这类似于对它们调用构造函数。 为了您的方便,有两种 igraph_bitset_t 构造函数。 igraph_bitset_init()
是基本构造函数,它创建一个给定长度的位集,并用零填充。 igraph_bitset_init_copy()
创建一个已存在并已初始化的位集的新相同副本。
如果不再需要 igraph_bitset_t 对象,则应通过调用 igraph_bitset_t 析构函数 igraph_bitset_destroy()
来销毁它以释放其分配的内存。
igraph_error_t igraph_bitset_init(igraph_bitset_t *bitset, igraph_integer_t size);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
每个位集在使用之前都需要初始化,并且有许多初始化函数或以其他方式调用的构造函数。 此函数构造一个给定大小的位集,并将每个条目初始化为 0。
由该函数初始化的每个位集对象都应在不再需要时销毁(即,为其分配的内存应释放),igraph_bitset_destroy()
函数负责此操作。
参数:
|
指向尚未初始化的位集对象的指针。 |
|
位集的大小。 |
返回值:
错误代码:如果没有足够的内存,则为 |
时间复杂度:取决于操作系统,分配 O(n/w) 个元素所需的时间量,n 是元素的数量。 w 是机器的字大小(32 或 64)。
igraph_error_t igraph_bitset_init_copy(igraph_bitset_t *dest, const igraph_bitset_t *src);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
现有位集对象的内容将被复制到新的位集对象中。
参数:
|
指向尚未初始化的位集对象的指针。 |
|
要复制的原始位集对象。 |
返回值:
错误代码:如果没有足够的内存,则为 |
时间复杂度:取决于操作系统,通常为 O(n/w),n 是位集的大小,w 是机器的字大小(32 或 64)。
void igraph_bitset_destroy(igraph_bitset_t *bitset);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
由 igraph_bitset_init()
初始化的所有位集都应通过此函数正确销毁。 销毁的位集需要通过 igraph_bitset_init()
或另一个构造函数重新初始化。
参数:
|
指向要销毁的(先前已初始化的)位集对象的指针。 |
时间复杂度:操作系统相关。
访问位集元素的***简单方法是使用 IGRAPH_BIT_TEST()
、IGRAPH_BIT_SET()
和 IGRAPH_BIT_CLEAR()
宏。
还有一些其他宏允许手动操作位集。 这些宏是 VECTOR()
、IGRAPH_BIT_SLOT()
、IGRAPH_BIT_MASK()
和 IGRAPH_BIT_NSLOTS()
。
#define IGRAPH_BIT_MASK(i)
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
与 IGRAPH_BIT_SLOT()
结合使用以访问位集的元素。 用法
IGRAPH_BIT_MASK(10)
获得一个整数,其中仅设置了第 11 个最低有效位。 请注意,在此处传递负值会导致未定义的行为。
参数:
|
唯一应设置其位的位索引。 |
时间复杂度:O(1)。
#define IGRAPH_BIT_SLOT(i)
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
与 IGRAPH_BIT_MASK
结合使用以访问位集的元素。 用法
IGRAPH_BIT_SLOT(70)
如果使用 64 位字,将返回 1;如果使用 32 位字,将返回 2。
参数:
|
应确定其槽的位索引。 |
时间复杂度:O(1)。
#define IGRAPH_BIT_SET(bitset, i)
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
用法
IGRAPH_BIT_SET(bitset, 3)
会将位集中第四个最低有效位设置为 1。
参数:
|
位集 |
|
应将其位在操作后设置为 1 的位索引。 |
时间复杂度:O(1)。
#define IGRAPH_BIT_CLEAR(bitset, i)
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
用法
IGRAPH_BIT_CLEAR(bitset, 4)
会将位集中第五个最低有效位设置为 0。
参数:
|
位集 |
|
应将其位在操作后设置为 0 的位索引。 |
时间复杂度:O(1)。
igraph_bitset_fill
— 使用常量值填充位集。igraph_bitset_null
— 清除位集中的所有位。igraph_bitset_or
— 两个位集的按位或。igraph_bitset_and
— 两个位集的按位与。igraph_bitset_xor
— 两个位集的按位异或。igraph_bitset_not
— 位集的按位取反。igraph_bitset_popcount
— 位集的总体计数。igraph_bitset_countl_zero
— 位集中前导零的数量。igraph_bitset_countl_one
— 位集中前导一的数量。igraph_bitset_countr_zero
— 位集中尾随零的数量。igraph_bitset_countr_one
— 位集中尾随一的数量。igraph_bitset_is_all_zero
— 所有位是否均为零?igraph_bitset_is_all_one
— 所有位是否均为一?igraph_bitset_is_any_zero
— 是否有任何位为零?igraph_bitset_is_any_one
— 是否有任何位为一?
void igraph_bitset_fill(igraph_bitset_t *bitset, igraph_bool_t value);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
将位集的所有位设置为相同的值。
参数:
|
要修改的位集对象。 |
|
要为所有位设置的值。 |
另请参阅:
时间复杂度:O(n/w)。
void igraph_bitset_null(igraph_bitset_t *bitset);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
参数:
|
要在其中清除所有位的位集对象。 |
另请参阅:
时间复杂度:O(n/w)。
void igraph_bitset_or(igraph_bitset_t *dest, const igraph_bitset_t *src1, const igraph_bitset_t *src2);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
将按位或应用于两个位集的内容,并将其存储在已初始化的位集中。 目标位集可能等于一个(甚至两个)源位集。 使用位集时,通常创建的位集是大小固定的相同大小。 因此,此函数不检查传递给它的位集的大小,如有必要,调用方必须这样做。
参数:
|
存储结果的位集对象 |
|
位集。 必须具有与 |
|
位集。 必须具有与 |
时间复杂度:O(n/w)。
void igraph_bitset_and(igraph_bitset_t *dest, const igraph_bitset_t *src1, const igraph_bitset_t *src2);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
将按位与应用于两个位集的内容,并将其存储在已初始化的位集中。 目标位集可能等于一个(甚至两个)源位集。 使用位集时,通常创建的位集是大小固定的相同大小。 因此,此函数不检查传递给它的位集的大小,如有必要,调用方必须这样做。
参数:
|
存储结果的位集对象 |
|
位集。 必须具有与 |
|
位集。 必须具有与 |
时间复杂度:O(n/w)。
void igraph_bitset_xor(igraph_bitset_t *dest, const igraph_bitset_t *src1, const igraph_bitset_t *src2);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
将按位异或应用于两个位集的内容,并将其存储在已初始化的位集中。 目标位集可能等于一个(甚至两个)源位集。 使用位集时,通常创建的位集是大小固定的相同大小。 因此,此函数不检查传递给它的位集的大小,如有必要,调用方必须这样做。
参数:
|
存储结果的位集对象 |
|
位集。 必须具有与 |
|
位集。 必须具有与 |
时间复杂度:O(n/w)。
void igraph_bitset_not(igraph_bitset_t *dest, const igraph_bitset_t *src);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
将按位非应用于位集的内容,并将其存储在已初始化的位集中。 目标位集可能等于源位集。 使用位集时,通常创建的位集是大小固定的相同大小。 因此,此函数不检查传递给它的位集的大小,如有必要,调用方必须这样做。
参数:
|
存储结果的位集对象 |
|
位集。 必须具有与 |
时间复杂度:O(n/w)。
igraph_integer_t igraph_bitset_popcount(const igraph_bitset_t *bitset);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
返回位集中已设置位的数量,也称为总体计数。
参数:
|
位集对象 |
返回值:
位集的总体计数。 |
时间复杂度:O(n/w)。
igraph_integer_t igraph_bitset_countl_zero(const igraph_bitset_t *bitset);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
返回位集中第一个一之前的前导(从最高有效位开始)零的数量。 如果位集全为零,则返回其大小。
参数:
|
位集对象 |
返回值:
位集中前导零的数量。 |
时间复杂度:O(n/w)。
igraph_integer_t igraph_bitset_countl_one(const igraph_bitset_t *bitset);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
返回位集中第一个零之前的前导(从最高有效位开始)一的数量。 如果位集全为一,则返回其大小。
参数:
|
位集对象 |
返回值:
位集中前导一的数量。 |
时间复杂度:O(n/w)。
igraph_integer_t igraph_bitset_countr_zero(const igraph_bitset_t *bitset);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
返回位集中第一个一之前的尾随(从最低有效位开始)零的数量。 如果位集全为零,则返回其大小。
参数:
|
位集对象 |
返回值:
位集中尾随零的数量。 |
时间复杂度:O(n/w)。
igraph_integer_t igraph_bitset_countr_one(const igraph_bitset_t *bitset);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
返回位集中第一个零之前的尾随(从最低有效位开始)一的数量。 如果位集全为一,则返回其大小。
参数:
|
位集对象 |
返回值:
位集中尾随一的数量。 |
时间复杂度:O(n/w)。
igraph_bool_t igraph_bitset_is_all_zero(const igraph_bitset_t *bitset);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
参数:
|
要测试的位集对象。 |
返回值:
如果未设置任何位,则为 True。 |
时间复杂度:O(n/w)。
igraph_bool_t igraph_bitset_is_all_one(const igraph_bitset_t *bitset);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
参数:
|
要测试的位集对象。 |
返回值:
如果所有位均已设置,则为 True。 |
时间复杂度:O(n/w)。
igraph_integer_t igraph_bitset_size(const igraph_bitset_t *bitset);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
参数:
|
位集对象 |
返回值:
位集的大小。 |
时间复杂度:O(1)。
igraph_integer_t igraph_bitset_capacity(const igraph_bitset_t *bitset);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
请注意,这可能与位集的大小(由 igraph_bitset_size()
查询)不同,并指定位集可以在不重新分配的情况下容纳多少个元素。
参数:
|
指向要查询的(先前已初始化的)位集对象的指针。 |
返回值:
已分配容量。 |
另请参阅:
时间复杂度:O(1)。
igraph_error_t igraph_bitset_reserve(igraph_bitset_t *bitset, igraph_integer_t capacity);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
igraph 位集是灵活的,它们可以增长和缩小。 但是,增长偶尔需要复制位集中的数据。 为了避免这种情况,您可以调用此函数来为位集的未来增长预留空间。
请注意,此函数不会更改位集的大小。 让我们看一个小例子来澄清一下:如果您为 100 个元素预留空间,并且您的位集的大小是(并且仍然是)60,那么您肯定可以在位集被复制之前向其添加额外的 40 个元素。
参数:
|
位集对象。 |
|
位集的新的已分配大小。 |
返回值:
错误代码:如果没有足够的内存,则为 |
时间复杂度:取决于操作系统,应在 O(n/w) 附近,n 是位集的新分配大小,w 是机器的字大小(32 或 64)。
igraph_error_t igraph_bitset_resize(igraph_bitset_t *bitset, igraph_integer_t new_size);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
请注意,此函数不会释放任何内存,只会将位集的大小设置为给定的大小。 另一方面,如果新大小大于先前的大小,它可能会分配更多内存。 在这种情况下,位集中新出现的元素将设置为零。
参数:
|
位集对象 |
|
位集的新大小。 |
返回值:
错误代码,如果没有足够的内存,则为 |
另请参阅:
请参阅 |
时间复杂度:如果新大小较小,则为 O(1);如果新大小较大,则取决于操作系统。 在后一种情况下,它通常在 O(n/w) 附近,n 是位集的新大小,w 是机器的字大小(32 或 64)。
igraph_error_t igraph_bitset_update(igraph_bitset_t *dest, const igraph_bitset_t *src);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
dest
的大小和内容将与 src
的大小和内容相同。
参数:
|
指向已初始化的位集对象的指针。 这将被更新。 |
|
要从中更新的位集。 |
返回值:
错误代码:如果没有足够的内存,则为 |
时间复杂度:取决于操作系统,通常为 O(n/w),n 是位集的大小,w 是机器的字大小(32 或 64)。
← 第 6 章. 内存(取消)分配 | 第 8 章. 随机数 → |