Liste chaînée statique laissée dans le temps (stockage statique de liste linéaire) - version langage C

Comme nous le savons tous, les pointeurs sont l'âme du langage C, et les pointeurs rendent l'implémentation des listes chaînées simple et claire.
Mais le problème est qu'à l'ère où le langage C n'est pas encore disponible, je veux décrire la liste chaînée, que dois-je faire ?
Ceci est la liste liée statique de notre protagoniste aujourd'hui

Résolvons d'abord un des problèmes les plus importants : sans pointeur, comment indiquer la position de l'élément suivant ?

La solution que les gens ont trouvée à l'époque était de remplacer le pointeur par l'indice du tableau. Nous appelons l'indice de ce tableau un curseur.

La deuxième question, lorsque nous voulons insérer des éléments dans le tableau, comment déterminer quels composants du tableau sont inutilisés et où les insérer ? Lorsque nous supprimons un élément, où devons-nous lier les composants du tableau qui ne stockent plus de données après la suppression, puis être réutilisés ?

La solution consiste à enchaîner tous les composants inutilisés et supprimés dans une liste de rechange avec un curseur.
Chaque fois qu'une insertion est utilisée, le premier nœud est obtenu à partir de la liste chaînée en attente en tant que nouveau nœud à insérer.
Au contraire, lors de la suppression, le nœud sera supprimé de la liste liée et lié à la liste liée de secours.

Pensez-vous que la description ci-dessus est particulièrement familière ? C'est en fait ce que font les mallocfonctions et freeles fonctions dans le langage C. Dans la liste chaînée statique, nous devons l'implémenter nous-mêmes, mais l'opération n'est pas compliquée.

La dernière question, nous savons maintenant que nous divisons la liste liée statique en deux parties, une partie stocke des données, l'autre partie ne stocke pas de données, nous l'appelons une liste de rechange. Alors comment identifier ces deux parties ?

Comme solution, nous utilisons ici le curseur avec l'indice de tableau 0 pour stocker l'indice du premier élément de la liste chaînée alternative (c'est-à-dire le premier élément du tableau qui ne stocke pas de données), et
ici nous définissons le tableau indice à 1. Le curseur de position sert à stocker l'indice du premier élément dont les données ne sont pas vides.Un
autre détail ici est que nous avons mis le curseur à 0 comme fin de ces deux parties.

En voyant ici, les problèmes liés à la liste liée statique sont presque résolus, commençons à la concevoir. Supposons que nous ayons un tableau de longueur 10. Comme suit:
insérez la description de l'image ici

Indice 0 : les données ne stockent rien et le curseur est utilisé pour pointer vers le premier élément du tableau qui ne stocke pas de données. (Ici pointe vers 6)
Indice 1 : les données ne stockent rien et le curseur est utilisé pour pointer vers le premier élément du tableau qui stocke les données. (Ici pointe vers 2)
Indices 2 à 5 : Cette partie stocke des données, et le curseur du dernier élément qui stocke des données est 0. (Le curseur avec l'indice 5 ici est 0, indiquant le dernier élément
pour stocker des données) Indice 6 - 9 : Cette partie ne stocke pas de données, la liste chaînée de rechange, le curseur du dernier élément utilisable est 0 (le curseur avec l'indice 9 ici est 0)

Ensuite, nous pouvons l'appliquer officiellement.

Définition de la liste liée statique

Étape 1 : Définir le type d'élément de données

#define ElemType char//这里我们使用的例子,采取字符

Étape 2 : Définir une liste liée statique

#define MaxSize 10  //链表的最大长度
typedef struct{
    
    
    ElemType data;//存储的数据元素
    int next;//游标,用来指示下一个数组分量的下标
}SLinkList[MaxSize];//静态链表

Opérations sur les listes chaînées statiques

initialisation

/*初始化*/
int InitSpace_SL(SLinkList space){
    
     
  int i;
  for (i = 2; i < MaxSize-1; i++){
    
    
      space[i].data=' ';
      space[i].next=i+1;
  }
  space[0].next=2;
  space[0].data=' ';
  space[1].next=0;
  space[1].data=' ';
  space[MaxSize-1].next=0;
  space[MaxSize-1].data=' ';
  return TRUE;
}

Exécutez le résultat d'impression :

初始化成功
数组下标=0,数据= ,游标为2
数组下标=1,数据= ,游标为0
数组下标=2,数据= ,游标为3
数组下标=3,数据= ,游标为4
数组下标=4,数据= ,游标为5
数组下标=5,数据= ,游标为6
数组下标=6,数据= ,游标为7
数组下标=7,数据= ,游标为8
数组下标=8,数据= ,游标为9
数组下标=9,数据= ,游标为0

La table vide après l'initialisation est la suivante :
insérez la description de l'image ici
alors pourquoi ne pas être curieux de savoir à quoi ressemble la table lorsqu'elle est pleine ?
insérez la description de l'image ici

demander la longueur du tableau

/*求表长*/
int ListLength(SLinkList space){
    
    
    int length=0;//空表长度为0
    int i=space[1].next;//指向第一个有数据的位置
    while (i!=0){
    
    
        length++;
        i=space[i].next;//相当于指针的p=p->next
    }
    return length;
}

L'opération principale est de parcourir la table :
ici l' i=space[i].next;équivalent d'un pointeurp=p->next

Allouer de l'espace

int Malloc_SL(SLinkList space){
    
    
    int i=space[0].next;//指向第一个没有数据的位置
    if(space[0].next) space[0].next=space[i].next;//如果还有空间,让space[0].next指向下一个空闲位置
    return i;//返回这个空闲位置
}

L'explication spécifique et l'opération d'insertion forment une seule pièce, qui ne sera pas répétée ici.

récupérer de l'espace

void Free_SL(SLinkList space,int k){
    
    
    space[k].data=' ';
    space[k].next=space[0].next;
    space[0].next=k;
}

L'explication spécifique et l'opération de suppression forment une seule pièce, et je ne la répéterai pas ici.

opération d'insertion

/*插入*/
int ListInsert_SL(SLinkList space,int i,ElemType e){
    
    
   int j,k,l;
   if(i<1||i>ListLength(space)+1) return FALSE;//位序无效
   j=Malloc_SL(space);//找到备用链表的第一个元素位置
   if (j!=0){
    
    //分配成功
       space[j].data=e;
       l=1;
       for ( k = 1; k < i; k++){
    
    //找到插入元素位序的前一个位置
           l=space[l].next;
       }
       space[j].next=space[l].next;
       space[l].next=j;
   } 
} 

Pas beaucoup de bêtises, il y a des images et la vérité
insérez la description de l'image ici

opération de suppression

/*删除*/
int ListDelete_SL(SLinkList space,int i){
    
       
    int k,l;
   if(i<1||i>ListLength(space)) return FALSE;//位序无效
       l=1;
       for ( k = 1; k < i; k++){
    
    //找到删除位序的前一个位置
           l=space[l].next;
       }
       k=space[l].next;
       space[l].next=space[k].next;
       Free_SL(space,k);//回收结点
}

Pas beaucoup de bêtises, il y a des images et la vérité
insérez la description de l'image ici

autres opérations

Le reste de la recherche par valeur, la recherche par bit et l'impression ne sont rien d'autre que de parcourir la liste chaînée.Afin de ne pas rendre l'article
redondant, l'opération complète est jointe à la fin. Je ne l'écrirai pas ici.

code source complet

#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0

#define ElemType char//这里我们使用的例子采取字符

#define MaxSize 10  //静态链表的最大长度
typedef struct{
    
    
    ElemType data;//存储的数据元素
    int next;//游标,用来指示下一个数组分量的下标
}SLinkList[MaxSize];//静态链表

/*初始化*/
int InitSpace_SL(SLinkList space){
    
     
  int i;
  for (i = 2; i < MaxSize-1; i++){
    
    
      space[i].data=' ';
      space[i].next=i+1;
  }
  space[0].next=2;
  space[0].data=' ';
  space[1].next=0;
  space[1].data=' ';
  space[MaxSize-1].next=0;
  space[MaxSize-1].data=' ';
  return TRUE;
}

int Malloc_SL(SLinkList space){
    
    
    int i=space[0].next;
    if(space[0].next) space[0].next=space[i].next;
    return i;
}

void Free_SL(SLinkList space,int k){
    
    
    space[k].data=' ';
    space[k].next=space[0].next;
    space[0].next=k;
}
/*求表长*/
int ListLength(SLinkList space){
    
    
    int length=0;
    int i=space[1].next;
    while (i!=0){
    
    
        length++;
        i=space[i].next;
    }
    return length;
}

/*插入*/
int ListInsert_SL(SLinkList space,int i,ElemType e){
    
    
   int j,k,l;
   if(i<1||i>ListLength(space)+1) return FALSE;
   j=Malloc_SL(space);
   if (j!=0){
    
    
       space[j].data=e;
       l=1;
       for ( k = 1; k < i; k++){
    
    
           l=space[l].next;
       }
       space[j].next=space[l].next;
       space[l].next=j;
   } 
} 

/*删除*/
int ListDelete_SL(SLinkList space,int i){
    
       
    int k,l;
   if(i<1||i>ListLength(space)) return FALSE;
       l=1;
       for ( k = 1; k < i; k++){
    
    
           l=space[l].next;
       }
       k=space[l].next;
       space[l].next=space[k].next;
       Free_SL(space,k);
}

/*按值查找*/
int LocateElem_SL(SLinkList space,ElemType e){
    
    
    int i=space[1].next;
    while (i!=0){
    
    
        if (space[i].data==e) return TRUE;
        i=space[i].next;
    }
    return FALSE;
}

/*按位查找*/
ElemType GetElem_SL(SLinkList space,int i){
    
    
    int l,k;
    if(i<1||i>ListLength(space)) return ' '; //不在有效范围内
    l=1;
    for ( k = 1; k <= i; k++){
    
    
           l=space[l].next;
    }
    return space[l].data;
}

/*打印*/
void PrintSpace_SL(SLinkList space){
    
    
    int i;
    for (i = 0; i < MaxSize; i++){
    
    
        printf("数组下标=%d,数据=%c,游标为%d\n",i,space[i].data,space[i].next);
    }   
}


int main(void){
    
    
///初始化
    
    SLinkList L;
    int i=InitSpace_SL(L);
    if (i==1){
    
    
        printf("初始化成功\n");
    }else{
    
    
        printf("初始化失败\n"); 
    }
    PrintSpace_SL(L);
    i=ListLength(L);
    printf("长度为%d\n",i);
    printf("\n");    
/插入
    ElemType a[4]={
    
    'c','b','e','f'};
    int j;
    for ( j = 0; j < 4; j++){
    
    
        i=ListInsert_SL(L,j+1,a[j]);
    }
    PrintSpace_SL(L);

    i=ListLength(L);
    printf("长度为%d\n",i);
    printf("\n"); 

    i=ListInsert_SL(L,4,'g');
    if (i==0){
    
    
        printf("插入位序无效!"); 
    }else{
    
    
        printf("插入成功!\n"); 
        PrintSpace_SL(L);
    }
    printf("\n"); 

删除
    
    i=ListDelete_SL(L,2);    
    if (i==0){
    
    
        printf("删除位序无效!"); 
    }else{
    
    
        printf("删除成功!\n"); 
        PrintSpace_SL(L);
    }
    printf("\n"); 
//按值查找
    i=LocateElem_SL(L,'a');    
    if (i==1){
    
    
        printf("按值查找成功\n");
    }else{
    
    
        printf("按值查找失败\n"); 
    }
    printf("\n");     
//按位查找
    ElemType e;
    e=GetElem_SL(L,2);    
    if (e==' '){
    
    
        printf("按值查找失败\n"); 
    }else{
    
    
        printf("查找到的元素为:%c",e);
    }

//    

}

résultat de l'opération

初始化成功
数组下标=0,数据= ,游标为2
数组下标=1,数据= ,游标为0
数组下标=2,数据= ,游标为3
数组下标=3,数据= ,游标为4
数组下标=4,数据= ,游标为5
数组下标=5,数据= ,游标为6
数组下标=6,数据= ,游标为7
数组下标=7,数据= ,游标为8
数组下标=8,数据= ,游标为9
数组下标=9,数据= ,游标为0
长度为0

数组下标=0,数据= ,游标为6
数组下标=1,数据= ,游标为2
数组下标=2,数据=c,游标为3
数组下标=3,数据=b,游标为4
数组下标=4,数据=e,游标为5
数组下标=5,数据=f,游标为0
数组下标=6,数据= ,游标为7
数组下标=7,数据= ,游标为8
数组下标=8,数据= ,游标为9
数组下标=9,数据= ,游标为0
长度为4

插入成功!
数组下标=0,数据= ,游标为7
数组下标=1,数据= ,游标为2
数组下标=2,数据=c,游标为3
数组下标=3,数据=b,游标为4
数组下标=4,数据=e,游标为6
数组下标=5,数据=f,游标为0
数组下标=6,数据=g,游标为5
数组下标=7,数据= ,游标为8
数组下标=8,数据= ,游标为9
数组下标=9,数据= ,游标为0

删除成功!
数组下标=0,数据= ,游标为3
数组下标=1,数据= ,游标为2
数组下标=2,数据=c,游标为4
数组下标=3,数据= ,游标为7
数组下标=4,数据=e,游标为6
数组下标=5,数据=f,游标为0
数组下标=6,数据=g,游标为5
数组下标=7,数据= ,游标为8
数组下标=8,数据= ,游标为9
数组下标=9,数据= ,游标为0

按值查找失败

查找到的元素为:e

en conclusion

Bien que nous ayons maintenant une liste liée individuellement et que nous n'utilisions plus une liste liée statique, son idée est toujours assez magique.
En général, cela ressemble beaucoup à une liste chaînée simple. L'insertion et la suppression ne nécessitent pas de déplacement d'éléments, c'est pourquoi nous l'appelons une liste chaînée statique.
Cependant, cela présente non seulement l'inconvénient qu'une liste à liaison unique ne peut pas être consultée de manière aléatoire, mais ne résout pas non plus le problème de la difficulté à déterminer la longueur de la table en raison de l'allocation continue (tableau).

Je suppose que tu aimes

Origine blog.csdn.net/weixin_47138646/article/details/121819130
conseillé
Classement