La réalisation de liste chaînée unique et les opérations associées

La réalisation de liste chaînée unique et les opérations associées

Enregistrez les connaissances que vous avez apprises. S'il y a des erreurs, pardonnez-moi. Veuillez les signaler et je les remodelerai. C'est un amant grandissant avec ma propre compréhension.

1> Qu'est-ce qu'une seule liste chaînée?

Différent du stockage séquentiel dans une table linéaire, chaque nœud ne stocke que des éléments de données (et est une adresse physique continue pendant l'allocation), et chaque nœud d'une liste liée à un seul lien stocke des données en plus de stocker un pointeur vers le nœud suivant (et fait ne pas allouer d' espace d'adressage physique contigu nécessaire )

                                                       Donc en théorie, les deux implémentations sont différentes

Avantages et inconvénients des tableaux séquentiels

Avantages: accès aléatoire, densité d'accès élevée Avantages: aucun espace d'adressage continu n'est requis et il est pratique de déplacer des éléments

Inconvénients: nécessite des adresses d'espace continu, il n'est pas pratique de déplacer des éléments. Inconvénients: l'accès aléatoire n'est pas possible et il faut un certain espace pour stocker les pointeurs

2> Définissez une seule liste liée

La signification et l'utilisation de typedef: Typedef est utilisé dans les langages de programmation informatique pour définir des alias simples pour des déclarations complexes , ce qui est quelque peu différent des définitions de macro. C'est lui-même une sorte de mot - clé de stockage , et des mots - clés tels que auto, extern, mutable, static, register ne peuvent pas apparaître dans la même expression ( le type de données peut être redéfini )

Par exemple: assign int i

Lorsque le type de données n'est pas redéfini: int i = 5

Après avoir redéfini le type de données: i = 5;

On peut voir que, comme la liste liée à un seul lien est une table de nœuds de chaîne, son type est struct (type de structure), il peut donc être plus facile d'écrire du code et d'améliorer l'efficacité après avoir utilisé la redéfinition.

typedef struct LNode //定义单链表的类型
{
	int data;//每个节点存放的数据元素
	struct LNode *next;//指针指向下一个节点
}LNode,*LinkList;//对struct LNode进行重命名,用LinkList去表示指向struct LNode的指针

En même temps, LNode * et LinkList sont équivalents mais les objets mis en valeur sont différents: LNode * -> node   LinkList-> liste liée (vous pouvez vous concentrer sur la distinction de la signification des deux)

3> Initialiser la liste liée à l'unité (nœud principal et nœud non principal)

Aucun nœud principal

void InitList(LinkList &L)//不带头节点
{
    L=NULL;//空表暂时没有数据
    if(L==NULL)
    {
        printf("初始化成功");
    }

}

Le fonctionnement de la table vide sur L = NULL est d'empêcher les données sales à l'intérieur de l'ordinateur

Ne pas diriger le nœud n'est pas propice à l'écriture de code, car le traitement du premier nœud de données et le traitement des nœuds suivants nécessitent une logique différente, et le traitement des listes vides et non vides nécessite également une logique différente.

Noeud principal

void InitList(LinkList &L)
{
	L = (LNode*)malloc(sizeof(LNode));//分配一个头节点
	if (L==NULL)//校验内存分配
	{
		printf("内存分配失败");
	}
	else {
		L->next = NULL;
	}
}

L'initialisation de la liste chaînée consiste principalement à allouer un nœud principal, et une attention particulière doit être portée à la vérification de l'allocation. L-> next = NULL est dû au fait que la table actuelle n'a qu'un seul nœud de tête qui doit pointer vers null, et le pointeur de tête ne stocke pas de données

4> Ajouter des données à la liste liée individuellement

Voici l'entrée des données de la liste liée à l'aide d'une interpolation de queue

Idée: Après l'initialisation, la liste liée à une seule liaison actuelle est une table vide -> la liste à liaison simple est différente d'une table linéaire avec un espace d'adressage continu (chaque donnée est directement liée par un pointeur) -> similaire à a, b pour l'échange de données

De même, pour les nœuds, un nœud peut être utilisé pour contenir des données de la même manière, et un nœud peut pointer vers le champ de pointeur du nœud suivant. Une fois l’affectation au nœud précédent terminée, passez au nœud suivant.

Par conséquent, l'affectation de boucle n'affectera pas le contenu du nœud D. Parce qu'il est passé au nœud suivant

 

void CreatList(LinkList &L)//输入数据
{
	LNode *P,*D;//DATA是用来保持每次输入的数据,P的作用是指向单链表尾部
	L = (LNode*)malloc(sizeof(LNode));//创建头节点
	L->next = NULL;//初始化单链表,一开始为空表
	P = L;//空表时头节点也是尾部节点
	int n;//输入数据的个数
	printf("请输入数据的个数:");
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		D = (LinkList)malloc(sizeof(LNode));//给D节点开辟一个空间
		printf("data[%d]=",i);
		scanf("%d",&D->data);//每次输入的数据到D
		D->next=P->next;//第一个节点已经填充,将移动下一个节点
		P->next = D;//D代表的是一个节点,P->next是指向下一个节点
		P = D;
	}

}

5> Sortie des données de la liste liée individuellement

Pour la sortie de la liste à liaison unique, un nouveau nœud doit être défini pour pointer vers le nœud principal L de la même manière. Utilisez des conditions de boucle pour imprimer le tableau entier

void ShowList(LinkList L)
{
	LNode * P;
	P =(LNode*)malloc(sizeof(LNode));//分配空间
	P = L->next;//单链表从P点开始遍历,等同于从头节点开始
	int i = 0;//记录位序
	printf("打印单链表\n");
	while (P!=NULL)//只要节点不为空就可以继续输出
	{
		printf("data[%d]=%d\n",i,P->data);
		i++;
		P = P->next;
	}
}

6> Insertion d'une seule liste chaînée

Insertion d'éléments (1 insérer 2 nœuds dans l'ordre de position, insérer 3 nœuds avant d'insérer)

Insérer dans l'ordre des bits (nœud principal)

Idée: Trouvez le i-1e nœud -> insérez l'élément après lui ( pointez le pointeur du i-1e élément vers l'élément inséré, et pointez le pointeur de l'élément inséré vers le i + 1e élément )

void ListInsert(LinkList &L, int i, int e)//插入数据
{
	if (i < 1)
		printf("插入位置不合法");
	else {
		LNode *p;//用来指向查询元素的指针
		int number = 0;//记录节点的位置
		p = L;//查询节点应从头开始,所以指向头节点
		while (p != NULL && number < i - 1)
		{
			p = p->next;//只是寻找到第i-1节点
			number++;
		}
		if (p == NULL)
			printf("插入位置不合法");
		printf("插入位置为%d是%d\n", i, e);
		LNode*s = (LNode*)malloc(sizeof(LNode));//为插入元素分配一个节点
		s->data = e;//将e赋值新节点的数据域
		s->next = p->next;//将插入元素的指针指向第i+1个元素
		p->next = s;//将第i-1和插入元素连接
	}
}

Pour le pointeur de tête Ne pas utiliser si vous utilisez un pointeur de tête causer de la confusion et un espace de stockage de données chaotique, donc pour redéfinir un nouveau nœud * p pour que les éléments pointent vers une requête, vous avez également besoin d'un enregistrement de données de nœud .

LNode * s = (LNode *) malloc (sizeof (LNode)) alloue un nœud pour l'élément inséré
        s -> data = e; assigne e au champ de données du nouveau nœud
        s-> next = p-> next; sera insérer l'élément Le pointeur pointe vers le i +
        1e élément p-> suivant = s; connectez le i-1e élément avec l'élément inséré

s-> suivant = p-> suivant; Pointez le pointeur de l'élément inséré vers le i +
        1e élément p-> suivant = s; Connectez le i-1e à l'élément inséré (ne peut pas être inversé, le nœud s pointera vers s Node) alors les données derrière seront confondues

Insérer un élément sans nœud principal (au niveau du bit )

void ListInsert(LinkList &L, int i, int e)//无头节点插入
{
	if (i < 1)
		printf("插入位置不合法");
	if (i == 1)//插入到头节点
	{
		LNode* s = (LNode*)malloc)(sizeof(LNode));//分配空间
		s->data = e;//元素传递给头节点
		s->next = L;//和单链表进行链接
		L = s;//现在s就是头节点方便变量
	}
	else {
		LNode *p;//用来指向查询元素的指针
		int number = 0;//记录节点的位置
		p = L;//查询节点应从头开始,所以指向头节点
		while (p != NULL && number < i - 1)
		{
			p = p->next;//只是寻找到第i-1节点
			number++;
		}
		if (p == NULL)
			printf("插入位置不合法");
		printf("插入位置为%d是%d\n", i, e);
		LNode*s = (LNode*)malloc(sizeof(LNode));//为插入元素分配一个节点
		s->data = e;//将e赋值新节点的数据域
		s->next = p->next;//将插入元素的指针指向第i+1个元素
		p->next = s;//将第i-1和插入元素连接
	}
}

Le nœud non principal doit principalement tenir compte de la situation lors de l'insertion de la première position, et les autres positions sont les mêmes que le nœud principal

7> Supprimer les données de la liste liée individuellement (nœud principal)

Idée: Trouvez le i-1e nœud—> Après avoir supprimé l'élément ( pointez le pointeur du i-1e élément vers le champ de données du i + 1e élément ) en même temps, vous devez libérer l'espace du i-ème nœud

void ListDelet(LinkList &L, int i)
{
	if (i < 1)
		printf("删除位置不合法");
	LNode *p;//用来指向查询元素的指针
	int number = 0;//记录节点的位置
	p = L;//查询节点应从头开始,所以指向头节点
	while (p != NULL && number < i - 1)
	{
		p = p->next;//只是寻找到第i-1节点
		number++;
	}
	if (p == NULL)
		printf("删除内容为空");
	LNode*q = p->next;
	int e;
	e = q->data;//记录删除的数据
	p->next = q->next;
	free(q);//释放掉该节点
	printf("删除元素%d成功\n",e);
}

Similaire au point d'insertion et de suppression de données, supprimez le i-ème élément et pointez le i-1ème nœud directement sur le i + 1ème nœud.

Aucun nœud principal

Semblable au nœud principal, le point principal est que la suppression du premier nœud nécessite que le nœud suivant du premier nœud continue à pointer vers le nœud suivant en tant que nœud principal

8> Recherche d'une seule liste liée (bit à bit / valeur)

L'essence de la recherche est de parcourir la liste liée individuellement, et un compteur est nécessaire pour calculer le nombre de nœuds traversés

void GetElem(LinkList L, int i)
{
	if (i < 0)
		printf("查询位置不合法");
	else {
		LNode* P;//创建一个记录节点的指针
		int number = 0;//记录查询到几个节点
		P = L->next;//指向头节点,从头节点开始查询变量
		if (i == 0)
			printf("头节点为空");//头节点不存放数据
		while (P != NULL && number < i)
		{
			P = P->next;//寻找到第i节点
			number++;
		}
		printf("查询第%d个元素为%d\n", i,P->data );
	}
	
}

 Trouver par valeur

void GetElem_data(LinkList L, int e)
{
	LNode*P;//分配一个节点
	P = L->next;
	int number = 1;
	while (P!=NULL&&P->data!=e)
	{
		P = P->next;
		number++;
	}
	if (P = NULL)
	{
		printf("单链表中没有该元素");
	}
	else
	printf("链表中有该元素位置位%d",number);
}

S'il n'y a pas d'élément de requête dans la liste liée avec le pointeur se déplaçant vers le dernier nœud, le pointeur pointé est NULL, s'il y a cet élément, la condition de données! = E ne sera pas remplie, et la boucle sautera en dehors

9> Code global

Pour l'erreur vissual studio C4996, ajoutez _CRT_SECURE_NO_WARNINGS dans les propriétés du projet -> prétraitement C ++.

#include<stdio.h>
#include<stdlib.h>
typedef struct LNode //定义单链表的类型
{
	int data;//每个节点存放的数据元素
	struct LNode *next;//指针指向下一个节点
}LNode,*LinkList;//对struct LNode进行重命名,用LinkList去表示指向struct LNode的指针

void InitList(LinkList &L)//初始化单链表
{
	L = (LNode*)malloc(sizeof(LNode));//分配一个头节点
	if (L==NULL)//校验内存分配
	{
		printf("内存分配失败");
	}
	else {
		L->next = NULL;
	}
}

void CreatList(LinkList &L)//输入数据
{
	LNode *P,*D;//DATA是用来保持每次输入的数据,P的作用是指向单链表尾部
	L = (LNode*)malloc(sizeof(LNode));//创建头节点
	L->next = NULL;//初始化单链表,一开始为空表
	P = L;//空表时头节点也是尾部节点
	int n;//输入数据的个数
	printf("请输入数据的个数:");
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		D = (LinkList)malloc(sizeof(LNode));//给D节点开辟一个空间
		printf("data[%d]=",i);
		scanf("%d",&D->data);//每次输入的数据到D
		D->next=P->next;//第一个节点已经填充,将移动下一个节点
		P->next = D;//D代表的是一个节点,P->next是指向下一个节点
		P = D;
	}

}
void ShowList(LinkList L)
{
	LNode * P;
	P =(LNode*)malloc(sizeof(LNode));//分配空间
	P = L->next;//单链表从P点开始遍历,等同于从头节点开始
	int i = 0;//记录位序
	printf("打印单链表\n");
	while (P!=NULL)//只要节点不为空就可以继续输出
	{
		printf("data[%d]=%d\n",i,P->data);
		i++;
		P = P->next;
	}
}

void ListInsert(LinkList &L, int i, int e)//插入数据
{
	if (i < 1)
		printf("插入位置不合法");
	else {
		LNode *p;//用来指向查询元素的指针
		int number = 0;//记录节点的位置
		p = L;//查询节点应从头开始,所以指向头节点
		while (p != NULL && number < i - 1)
		{
			p = p->next;//只是寻找到第i-1节点
			number++;
		}
		if (p == NULL)
			printf("插入位置不合法");
		printf("插入位置为%d是%d\n", i, e);
		LNode*s = (LNode*)malloc(sizeof(LNode));//为插入元素分配一个节点
		s->data = e;//将e赋值新节点的数据域
		s->next = p->next;//将插入元素的指针指向第i+1个元素
		p->next = s;//将第i-1和插入元素连接
	}
}
void ListInsert_no(LinkList L, int i, int e)//无头节点插入
{
	if (i < 1)
		printf("插入位置不合法");
	if (i == 1)//插入到头节点
	{
		LNode* s = (LNode*)malloc(sizeof(LNode));//分配空间
		s->data = e;//元素传递给头节点
		s->next = L;//和单链表进行链接
		L = s;//现在s就是头节点方便变量
	}
	else {
		LNode *p;//用来指向查询元素的指针
		int number = 0;//记录节点的位置
		p = L;//查询节点应从头开始,所以指向头节点
		while (p != NULL && number < i - 1)
		{
			p = p->next;//只是寻找到第i-1节点
			number++;
		}
		if (p == NULL)
			printf("插入位置不合法");
		printf("插入位置为%d是%d\n", i, e);
		LNode*s = (LNode*)malloc(sizeof(LNode));//为插入元素分配一个节点
		s->data = e;//将e赋值新节点的数据域
		s->next = p->next;//将插入元素的指针指向第i+1个元素
		p->next = s;//将第i-1和插入元素连接
	}
}

void ListDelet(LinkList &L, int i)
{
	if (i < 1)
		printf("删除位置不合法");
	LNode *P;//用来指向查询元素的指针
	int number = 0;//记录节点的位置
	P = L;//查询节点应从头开始,所以指向头节点
	while (P != NULL && number < i - 1)
	{
		P = P->next;//只是寻找到第i-1节点
		number++;
	}
	if (P== NULL)
		printf("删除内容为空");
	LNode*Q = P->next;
	int e;
	e = Q->data;//记录删除的数据
	P->next = Q->next;
	free(Q);//释放掉该节点
	printf("删除元素%d成功\n",e);
}

void GetElem(LinkList L, int i)
{
	if (i < 0)
		printf("查询位置不合法");
	else {
		LNode* P;//创建一个记录节点的指针
		int number = 0;//记录查询到几个节点
		P = L->next;//指向头节点,从头节点开始查询变量
		if (i == 0)
			printf("头节点为空");//头节点不存放数据
		while (P != NULL && number < i)
		{
			P = P->next;//寻找到第i节点
			number++;
		}
		printf("查询第%d个元素为%d\n", i,P->data );
	}
	
}

void GetElem_data(LinkList L, int e)
{
	LNode*P;//分配一个节点
	P = L->next;
	int number = 1;
	while (P!=NULL&&P->data!=e)
	{
		P = P->next;
		number++;
	}
	if (P = NULL)
	{
		printf("单链表中没有该元素");
	}
	else
	printf("链表中有该元素位置位%d",number);
}

void main()
{
	LinkList L;
	InitList(L);//初始化一个带头节点的单链表
	CreatList(L);//输入元素
	ListInsert(L,3,99);//插入元素(按位)
	ListInsert_no(L, 1, 11);//不带头节点
	ListDelet(L, 3);//删除节点数据
	GetElem(L,3);//按位查找
	GetElem_data(L,3);//按值查找
	ShowList(L);//打印表

}

 

Je suppose que tu aimes

Origine blog.csdn.net/qq_46861651/article/details/112751264
conseillé
Classement