C语言中的自引用结构体



什么是自引用结构体?

自引用结构体是C语言中的一种结构体数据类型,其中一个或多个元素是指向其自身类型变量的指针。自引用用户定义类型在C编程中具有极其重要的作用。它们被广泛用于构建复杂的动态数据结构,例如链表

在C编程中,数组在编译时分配所需的内存,并且数组大小在运行时无法修改。自引用结构体允许您通过动态处理大小来模拟数组。

Self-referential Structure

操作系统的文件管理系统建立在动态构建的树结构之上,这些结构由自引用结构体操作。自引用结构体也用于许多复杂的算法中。

定义自引用结构体

定义自引用结构体的通用语法如下:

strut typename{ type var1; type var2; ... ... struct typename *var3; }

让我们通过以下示例了解如何使用自引用结构体。我们定义了一个名为mystruct的结构体类型。它有一个整数元素“a”,而“b”是指向mystruct类型本身的指针。

我们声明三个mystruct类型的变量:

struct mystruct x = {10, NULL}, y = {20, NULL}, z = {30, NULL};

接下来,我们声明三个“mystruct”指针,并将xyz的引用赋值给它们。

struct mystruct * p1, *p2, *p3; p1 = &x; p2 = &y; p3 = &z;

变量“x”、“y”和“z”是相互独立的,因为它们将位于随机位置,这与所有元素都在相邻位置的数组不同。

Elements Adjacent Locations

Explore our latest online courses and learn new skills at your own pace. Enroll and become a certified expert to boost your career.

自引用结构体的示例

示例1

为了明确建立三个变量之间的链接,我们可以在“x”中存储“y”的地址,在“y”中存储“z”的地址。让我们在下面的程序中实现这一点:

Open Compiler
#include <stdio.h> struct mystruct{ int a; struct mystruct *b; }; int main(){ struct mystruct x = {10, NULL}, y = {20, NULL}, z = {30, NULL}; struct mystruct * p1, *p2, *p3; p1 = &x; p2 = &y; p3 = &z; x.b = p2; y.b = p3; printf("Address of x: %d a: %d Address of next: %d\n", p1, x.a, x.b); printf("Address of y: %d a: %d Address of next: %d\n", p2, y.a, y.b); printf("Address of z: %d a: %d Address of next: %d\n", p3, z.a, z.b); return 0; }

输出

运行代码并检查其输出:

Address of x: 659042000 a: 10 Address of next: 659042016
Address of y: 659042016 a: 20 Address of next: 659042032
Address of z: 659042032 a: 30 Address of next: 0

示例2

让我们进一步改进上面的程序。我们不声明变量然后将它们的地址存储在指针中,而是使用malloc()函数动态分配内存,其地址存储在指针变量中。然后,我们像下面这样建立三个节点之间的链接:

Open Compiler
#include <stdio.h> #include <stdlib.h> struct mystruct{ int a; struct mystruct *b; }; int main(){ struct mystruct *p1, *p2, *p3; p1 = (struct mystruct *)malloc(sizeof(struct mystruct)); p2 = (struct mystruct *)malloc(sizeof(struct mystruct)); p3 = (struct mystruct *)malloc(sizeof(struct mystruct)); p1 -> a = 10; p1->b=NULL; p2 -> a = 20; p2->b=NULL; p3 -> a =30; p3->b=NULL; p1 -> b = p2; p2 -> b = p3; printf("Add of x: %d a: %d add of next: %d\n", p1, p1->a, p1->b); printf("add of y: %d a: %d add of next: %d\n", p2, p2->a, p2->b); printf("add of z: %d a: %d add of next: %d\n", p3, p3->a, p3->b); return 0; }

输出

运行代码并检查其输出:

Add of x: 10032160 a: 10 add of next: 10032192
add of y: 10032192 a: 20 add of next: 10032224
add of z: 10032224 a: 30 add of next: 0

示例3

我们可以从前面元素中存储的地址访问链接中的下一个元素,因为“p1 → b”指向“p2”的地址。我们可以使用while循环来显示链表,如下例所示:

Open Compiler
#include <stdio.h> #include <stdlib.h> struct mystruct{ int a; struct mystruct *b; }; int main(){ struct mystruct *p1, *p2, *p3; p1=(struct mystruct *)malloc(sizeof(struct mystruct)); p2=(struct mystruct *)malloc(sizeof(struct mystruct)); p3=(struct mystruct *)malloc(sizeof(struct mystruct)); p1 -> a = 10; p1 -> b = NULL; p2 -> a = 20; p2 -> b = NULL; p3 -> a = 30; p3 -> b = NULL; p1 -> b = p2; p2 -> b = p3; while (p1 != NULL){ printf("Add of current: %d a: %d add of next: %d\n", p1, p1->a, p1->b); p1 = p1 -> b; } return 0; }

输出

运行代码并检查其输出:

Add of current: 10032160 a: 10 add of next: 10032192
Add of current: 10032192 a: 20 add of next: 10032224
Add of current: 10032224 a: 30 add of next: 0

使用自引用结构体创建链表

在上面的示例中,动态构建的列表具有三个通过指针链接的离散元素。我们可以使用for循环通过动态分配内存来设置所需数量的元素,并将下一个元素的地址存储在前面的节点中。

示例

以下示例显示了如何使用自引用结构体创建链表:

Open Compiler
#include <stdio.h> #include <stdlib.h> struct mystruct{ int a; struct mystruct *b; }; int main(){ struct mystruct *p1, *p2, *start; int i; p1 = (struct mystruct *)malloc(sizeof(struct mystruct)); p1 -> a = 10; p1 -> b = NULL; start = p1; for(i = 1; i <= 5; i++){ p2 = (struct mystruct *)malloc(sizeof(struct mystruct)); p2 -> a = i*2; p2 -> b = NULL; p1 -> b = p2; p1 = p2; } p1 = start; while(p1 != NULL){ printf("Add of current: %d a: %d add of next: %d\n", p1, p1 -> a, p1 -> b); p1 = p1 -> b; } return 0; }

输出

运行代码并检查其输出:

Add of current: 11408416 a: 10 add of next: 11408448
Add of current: 11408448 a: 2 add of next: 11408480
Add of current: 11408480 a: 4 add of next: 11408512
Add of current: 11408512 a: 6 add of next: 11408544
Add of current: 11408544 a: 8 add of next: 11408576
Add of current: 11408576 a: 10 add of next: 0

使用自引用结构体创建双向链表

链表从开始遍历到到达NULL。您还可以构建一个双向链表,其中结构体有两个指针,每个指针都指向前一个和下一个元素的地址。

Doubly linked list

为此目的的结构体定义如下:

struct node { int data; int key; struct node *next; struct node *prev; };

使用自引用结构体创建树

自引用结构体也用于构建非线性数据结构,例如。二叉搜索树由下图逻辑表示:

Tree

实现树的结构体定义如下:

struct node { int data; struct node *leftChild; struct node *rightChild; };

要详细了解这些复杂的数据结构,您可以访问DSA教程:数据结构算法

广告