C语言链表超简单教程
笔者作为一名C语言的初学者在刚接触链表时几乎找不到教程能用很通俗易懂的语言去讲解链表。大多数时候找到的关于链表的教程或许是生硬的塞给读者一大段代码或许是使用了一些过于专业的词汇对于萌新非常地不友好。这就是我写这篇教程的原因。好吧即使这篇教程会相对简单但是在阅读之前读者还是需要首先简单了解结构体部分和指针部分的内容。好那我们就开始吧。首先通俗地解释一下链表是一种特殊的结构体创建链表只需要下面这些代码struct node { int num; struct node *next; };到此为止你就成功建立了一个链表。我们来详细分析一下首先我们使用了创建结构体的标准格式创建了一个struct nodestruct node有两个成员(int, struct node)在这个结构中int类型非常的平淡无奇而struct node本来是我们定义的结构体但是在结构体里面的成员里再次出现(这时很多教程就会告诉你这是C语言里先使用后定义的特例云云但我们不管)并且定义了一个指针变量根据我们对指针的了解某一类型的指针指向相同类型的数据(void是空指针int型指针指向整形变量char型指针指向字符型变量)那么struct node型指针就指向struct node型结构我们先看一个图了解一下那么这个特殊的指针是怎么运作呢这个特殊的指针指向另一个结构而这个结构同样拥有一个指向其他结构的指针就构成了这样一个关系循环下去就会产生一条“链”链表分为单向链表双向链表以及循环链表大家可以自行去了解不同种类的链表这里我们以单向链表为例子分析一下对链表的操作。(请先行了解malloc函数的作用它是必不可少的)#include #include struct node { int num; struct node *next; }; int main() { struct node *head; //声明表头head(链表开始的位置) headNULL; //建一个空表 struct node *p1,*p2; int i1; //利用malloc()申请分配节点(也就是一个地址) p1p2(struct node*)malloc(sizeof(struct node)); //新节点 printf(请输入值值小于等于0结束值存放地址为p1_ADDR %d\n,p1); scanf(%d,p1-num); p1-noi; p1-nextNULL; while(p1-num0) //输入的节点数值大于0 { if(headNULL) headp1; //空表接入表头 else p2-nextp1; //非空表接到表尾 p2p1; p1(struct node*)malloc(sizeof(struct node)); //下一个新节点 ii1; printf(请输入值值小于等于0结束值存放地址为p%d_ADDR %d\n,i,p2); scanf(%d,p1-num);//输入节点的值 p1-noi; //判断一下是否有后续节点要接入链表若无则结束; } free(p1); //申请到的没录入所以释放掉 p1NULL; //使指向空 p2-next NULL; //到表尾了指向空 printf(链表输入结束END\n); getchar(); return 0; }这段程序执行完毕后我们得到了链表表头head但是其余空间都是系统分配的我们并不能直接找到对应的变量。但是这就是单向链表的神奇之处只要知道表头就可以一步一步摸到表尾。不过在此之前我们要先理清思路。首先head-next代表什么它既是首个结构的一个成员也是第二个结构的地址。那么head-next-next又是什么呢它既是第二个结构的一个成员也是第三个结构的地址。所以我们可以在代表结束的getchar();语句之前插入printf(“%d”,head-next-next-num);试一试你会发现如果你的节点达到了三个或更多的话这条语句能够精准地输出第三个结构里num的值。现在想一想怎么将刚刚创建的单向链表所有的节点反向反向也就是将所有结构中的指针成员从指向下一个结构改为指向上一个结构。想好了吗我们开始了哦。我们首先从表头开始操作创建三个struct node型指针x1,x2,temp作为暂存器(为什么是三个呢想想我们在学习交换a,b两个变量的值时是ca;ab;bc;这个样子的)。先保存好head-next-next指向的地址 x1head-next-next;然后把x1放一边儿凉快去。再保存第二个结构的地址 x2head-next;之后让第二个结构里的成员next指向首个结构 head-nexthead;再然后令表头指向空 headNULL;第一步反向就完成了那么接下来再完成第二步。还记得我们之前使用的x1和x2吗马上就能派上用场了。因为head指向了NULL故head已经不复存在但我们还有temp。先把x1的值留住 tempx1;而x1再往后移动一次x1x1-next; //这里将x1-next看作下一结构此时x1就又可以放在一边儿凉快了。(x1:”嘤嘤嘤”)我们的目的是让第三个结构里的指针成员指向第二个结构找找我们在第一步里做了什么。第二个结构的地址被保存在x2中第三个结构的地址被保存在了temp中temp-nextx2; //这里将temp-next看作成员这样就又完成了一次逆向不过还没结束这一步因为这是循环操作要保持语句一致性。所以我们还要将x2向后移动一次x2temp;后面每一步的操作都和第二步类似但是循环结束是什么时候呢由于x1每次只是单纯后移几乎没有操作那么后移之后的x1里的next是不是空指针(NULL)就成了关键。if(x1-nextNULL) { temp-nextx2; x1-nexttemp; headx1; break; }此时表头地址再次存入了head不过单向链表已经反向(这个教程是有陷阱的如果链表比较短在x1head-next-next;时就会崩溃想想怎么解决吧)。现在您已经可以去阅读其他的教程更加详细地研究链表。如果您在这篇文章中发现问题欢迎随时提出宝贵的意见我将不甚感激作为一名初学者对于很多专业的知识不了解也因此避免了使用难以理解的专业词汇进行讲解如有错误请以标准文档为准。