Utiliser le langage C pour implémenter les opérations de base des listes à chaînage unique (code complet ci-joint)

Introduction:

Qu'il s'agisse d'une structure de stockage séquentielle ou d'une structure de stockage en chaîne, lors du stockage d'éléments en mémoire, non seulement les informations pertinentes de l'élément doivent être stockées, mais également la relation entre l'élément et les autres éléments. Nous avons appris auparavant La structure physique « innée » peut naturellement exprimer la relation entre les éléments et ne nécessite pas d'informations supplémentaires pour exprimer la relation entre les éléments. Pour les structures de stockage non séquentielles telles que le stockage en chaîne, Des pointeurs supplémentaires sont nécessaires pour représenter cette relation.

Liste unique :

En plus de stocker des éléments de données, chaque nœud stocke également un pointeur vers le nœud suivant.

Caractéristiques d'une liste à chaînage unique :

Avantages : Ne nécessite pas de grand espace continu, capacité facile à changer

Inconvénients : Pas d'accès aléatoire, il faut un certain espace pour stocker les pointeurs

définition:

typedef struct LNode {
    
    
	int data;
	struct LNode* next;//指针指向下一个节点,指针的类型为节点类型;
}*LinkNode;//声明*LinkNode为结构体指针类型

En plus de la méthode ci-dessus, nous pouvons également d'abord déclarer LinkNode comme type de structure. Lors de l'utilisation de ce type, il suffit de définir la variable correspondante comme pointeur.

Les listes chaînées sont divisées en nœuds principaux et nœuds non principaux. Nous étudions généralement principalement les nœuds principaux.

Insérer la description de l'image ici

Opération d'initialisation :

Avant toutes les opérations, nous devons d’abord créer une liste vide à chaînage unique, puis la première chose que nous devons faire est d’attribuer le nœud principal.

void InistLinkNode(LinkNode& L) {
    
    
	L = (LNode*)malloc(sizeof(LNode));//分配头结点
	L->next = NULL;
}

Méthode d'insertion de la tête :

"La méthode d'insertion de tête", comme son nom l'indique, consiste à insérer l'élément après le nœud principal. L'insérer une fois ne semble pas être différent de ce dont nous parlons habituellement, mais l'insérer plusieurs fois après le nœud principal est le "premier véritable node", alors y aura-t-il un phénomène où les données finales stockées seront dans l'ordre opposé à celui dans lequel nous les avons insérées ?

void InsertLinkNode(LinkNode& L) {
    
    
	LNode* s;
	int x,Length;
	printf("请输入你要插入的元素个数:");
	scanf("%d", &Length);
	printf("请输入你要插入的元素:\n");
	for (int j = 0; j < Length; j++) {
    
    
		s = (LNode*)malloc(sizeof(LNode));//每插入一个元素之前,都需要给它分配节点空间
		scanf("%d", &x);
		s->data = x;
		s->next = L->next;
		L->next = s;
	}

} 

Vérifiez les éléments suivants via le programme :

Insérer la description de l'image ici

Méthode d'insertion de la queue :

"La méthode d'insertion de queue", comme son nom l'indique, consiste à insérer des éléments jusqu'à la fin du tableau, ce qui est notre insertion ordinaire . Alors, comment trouver la position de la fin du tableau ? Dans une table de séquence, nous pouvons utiliser pleinement les caractéristiques naturelles de sa structure de stockage séquentielle et la trouver via des indices. Cependant, il n'existe aucun moyen de le faire avec une liste à chaînage unique. Nous n'avons que deux manières, soit de la parcourir en boucle, soit d'essayer pour le faire en bout de table.

Alors, quelle méthode est la bonne ?

La réponse est la deuxième ! La manière de parcourir la boucle ne semble poser aucun problème si vous n'insérez qu'un seul élément, mais si vous répétez la boucle plusieurs fois, cela augmentera sans aucun doute la complexité temporelle, ce qui n'est évidemment pas une bonne méthode.

La deuxième méthode ne pose pas le problème de la complexité temporelle.只需要在表尾位置做个标记,使它永远指向表尾即可。

void TailInsertLinkNode(LinkNode& L) {
    
    
	LNode* s,*r;
	int x,Length;
	r = L;//r为表尾指针
	printf("请输入你要插入的元素个数:");
	scanf("%d", &Length);
	printf("请输入你要插入的元素:\n");
	for (int j = 0; j < Length; j++) {
    
    
		s = (LNode*)malloc(sizeof(LNode));
		scanf("%d", &x);
		s->data = x;
		r->next = s;
		r = s;//s为当前的表尾指针,将他的值赋值给r----使r永远指向表尾
	}
	printf("\n");
	r->next = NULL;
}

Supprimez le i-ième élément :

Puisque nous voulons supprimer un élément, nous devons d’abord le faire 保证这个元素是非NULL, et deuxièmement, nous devons également garantir 它前面的那个节点也是非NULL, pourquoi ? Car si l'élément est supprimé de la liste chaînée, la connexion entre l'élément suivant et la sous-liste précédente ne peut être réalisée que si le nœud précédent est non NULL.

void DeleteLinkNode(LinkNode& L) {
    
    
	int x, j = 0,e;
	printf("请输入你要删除的元素位序:\n");
	scanf("%d", &x);
	LNode*p = L;
	while (p != NULL && j < x - 1) {
    
    //寻找要删除元素前的元素
		p = p->next;
		j++;
	}
	if (p == NULL)
	{
    
    
		printf("不存在我们要删除的元素!");
	}
	if (p->next == NULL)//判断该要删除的节点是否为NULL
	{
    
    
		printf("不存在我们要删除的元素!");
	}
	LNode* q = p->next;//q为我们要删除的节点
	e = q->data;
	p->next = q->next;
	free(q);//需要及时的将删除了的元素空间进行释放
}

其他的基本操作都是很常规化的,这里就不单独的进行解释了,需要注意的点,我会在文章结尾部分的完整代码的注释中展出。

Insérer à la position i :

void IncreaseLinkNode(LinkNode& L) {
    
    
	printf("请输入你要插入的元素和位序:(元素和位序之间用逗号隔开)\n");
	int x, j = 0, e;
	scanf("%d,%d",&e, &x);
	LNode* s = L, * r= (LNode*)malloc(sizeof(LNode));
	while (j < x-1  && s != NULL) {
    
    
		j++;
		s = s->next;
	}
	r->data = e;
	r->next = s->next;
	s->next = r;
}

如下所示的代码顺序不能发生改变,否则会出现无法和后面的节点;

r->next = s->next;
s->next = r;

Le code complet est le suivant :

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode {
    
    
	int data;
	struct LNode* next;
}*LinkNode;
//初始化
void InistLinkNode(LinkNode& L) {
    
    
	L = (LNode*)malloc(sizeof(LNode));//分配头结点
	L->next = NULL;
}
//头插法
void InsertLinkNode(LinkNode& L) {
    
    
	LNode* s;
	int x,Length;
	printf("请输入你要插入的元素个数:");
	scanf("%d", &Length);
	printf("请输入你要插入的元素:\n");
	for (int j = 0; j < Length; j++) {
    
    
		s = (LNode*)malloc(sizeof(LNode));
		scanf("%d", &x);
		s->data = x;
		s->next = L->next;
		L->next = s;
	}
} 
//尾插法
void TailInsertLinkNode(LinkNode& L) {
    
    
	LNode* s,*r;
	int x,Length;
	r = L;
	printf("请输入你要插入的元素个数:");
	scanf("%d", &Length);
	printf("请输入你要插入的元素:\n");
	for (int j = 0; j < Length; j++) {
    
    
		s = (LNode*)malloc(sizeof(LNode));
		scanf("%d", &x);
		s->data = x;
		r->next = s;
		r = s;
	}
	printf("\n");
	r->next = NULL;
}
//输出单链表
void PrintLinkNode(LinkNode& L)
{
    
    
	LNode* s=L->next;
	printf("单链表元素如下:\n");
	while (s != NULL) {
    
    
		printf("%d", s->data);
		s =s->next;
	}
	printf("\n");
}
//求线性表长度
void lengthLinkNode(LinkNode& L)
{
    
    
	LNode* s = L->next;
	int n=0;
	while (s != NULL) {
    
    
		n++;
		s = s->next;
	}
	printf("单链表长度为:%d",n);
	printf("\n");
}
//取第i个元素
void GetElemLinkNode(LinkNode& L) {
    
    
	printf("请输入你要查找的元素位序:\n");
	int i, j = 0;
	LNode* s=L;
	scanf("%d", &i);
	while (j < i && s != NULL) {
    
    
		j++;
		s = s->next;
	}
	if (s == NULL) {
    
    
		printf("不存在我们要查找的元素!");
	}
	else {
    
    
		printf("元素位序为%d的元素是%d",i, s->data);
	}
	printf("\n");
}
//删除第i个元素
void DeleteLinkNode(LinkNode& L) {
    
    
	int x, j = 0,e;
	printf("请输入你要删除的元素位序:\n");
	scanf("%d", &x);
	LNode*p = L;
	while (p != NULL && j < x - 1) {
    
    
		p = p->next;
		j++;
	}
	if (p == NULL)
	{
    
    
		printf("不存在我们要删除的元素!");
	}
	if (p->next == NULL)
	{
    
    
		printf("不存在我们要删除的元素!");
	}
	LNode* q = p->next;
	e = q->data;
	p->next = q->next;
	free(q);
}
//在第i个位置插入
void IncreaseLinkNode(LinkNode& L) {
    
    
	printf("请输入你要插入的元素和位序:(元素和位序之间用逗号隔开)\n");
	int x, j = 0, e;
	scanf("%d,%d",&e, &x);
	LNode* s = L, * r= (LNode*)malloc(sizeof(LNode));
	while (j < x-1  && s != NULL) {
    
    
		j++;
		s = s->next;
	}
	r->data = e;
	r->next = s->next;
	s->next = r;
}
//查找位序
void SearchLinkNode(LinkNode &L) {
    
    
	int x,j=1;
	LNode* p=L->next;
	printf("请输入你要查找的元素:\n");
	scanf("%d", &x);
	while (p != NULL && p->data != x) {
    
    
		p = p->next;
		j++;
	}
	if (p == NULL) {
    
    
		printf("您要查找的元素不存在!");
	}
	else {
    
    
		printf("你要查找的元素%d的位序为%d", x, j);
	}
}
int main() {
    
    
	LinkNode L;
	InistLinkNode(L);
	/*InsertLinkNode(L);*/
	TailInsertLinkNode(L);
	PrintLinkNode(L);
	lengthLinkNode(L);
	GetElemLinkNode(L);
	IncreaseLinkNode(L);
	PrintLinkNode(L);
	DeleteLinkNode(L);
	PrintLinkNode( L);
	SearchLinkNode(L);
}

Sortir:

Insérer la description de l'image ici

Je suppose que tu aimes

Origine blog.csdn.net/m0_64365419/article/details/127464995
conseillé
Classement