链表:创建一个简单的链表并输出链表内容
链表的专业术语:
首节点:存放第一个有效数据的节点
尾节点:存放最后一个有效数据的节点
头结点:
1.头结点的数据类型和首节点的数据类型是一模一样的
2.头结点是首节点前面的那个节点
3.头结点并不存放有效数据
4.设置头结点的目的是为了方便对链表的操作
头指针:存放头结点地址的指针变量
用一张图片来展示链表的基本框架:
⭐尾节点的指针域为空,可以表示为NULL
⭐想要确定一个链表,需要最基本的信息是头指针,之后的信息都可以通过头指针找出来。
接下来编写程序,只有用实际的例子,才能更全面的理解!
1 #include <stdio.h> 2 #include <stdlib.h> 3 struct Node //定义一个链表结构 4 { 5 int data; //链表节点的数据 6 struct Node * pNext; //链表节点指向下一个节点的指针 7 }; 8 int i; 9 struct Node * create_list(void); //创建链表的函数声明 10 void traverse_list(struct Node *); //打印链表的函数声明 11 int main() 12 { 13 struct Node * pHead = NULL; //先给头指针赋值为NULL 14 pHead = create_list(); //调用链表创建函数,并将头指针的值赋给pHead 15 traverse_list(pHead); //打印链表 16 return 0; 17 } 18 struct Node * create_list(void) //创建链表的函数 19 { 20 int len; //链表的节点数 21 int val; //链表节点中数据域的值 22 struct Node * pHead=(struct Node *)malloc(sizeof(struct Node)); //动态分配头结点的内存 23 if(pHead == NULL) 24 { 25 printf("内存分配失败,程序终止!\n"); 26 exit(-1); 27 } 28 struct Node * pTail = pHead; //定义一个尾节点指针,将pHead的值赋给它 29 pTail->pNext = NULL; //尾节点的指针域一定为空 30 printf("请输入您需要生成的链表节点的个数:len ="); 31 scanf("%d",&len); 32 for (i=0;i<len;i++) 33 { 34 printf("请输入第%d个节点的值:",i+1); 35 scanf("%d",&val); 36 struct Node * pNew=(struct Node *)malloc(sizeof(struct Node)); //动态分配新节点的内存 37 if(pNew== NULL) 38 { 39 printf("内存分配失败,程序终止!\n"); 40 exit(-1); 41 } 42 pNew->data = val; //把输入的值传给*pNew数据域 43 pNew->pNext = NULL; // *pNew是新的尾节点,所以 pNew->pNext应该为空 44 pTail->pNext = pNew; //把*pNew的地址传给pTail->pNext指针域,等效于*pTail.pNext=pNew 45 //第一次的pTail->pNext = pNew相当于把首节点的地址给了头结点 46 47 pTail = pNew; 48 //执行此操作,*pNew就变成了新的*pTail 49 //之后的pTail = pNew则是让最后一个与上一个节点连接上 50 } 51 return pHead; //返回 pHead的值 52 } 53 void traverse_list(struct Node * pHead) //遍历链表 54 { 55 struct Node * p = pHead->pNext; //定义一个指向下一个节点的指针 56 while(p!=NULL) //尾节点的指针域一定是NULL,如果非NULL,则继续打印 57 { 58 printf("%d\t",p->data); 59 p = p->pNext; //下一个节点的地址赋值给p 60 } 61 return; //循环结束 62 }
在这个程序中,我对44行和47行的代码思考了很久
最开始总觉得有了44行代码 pTail->pNext = pNew ,47行的代码 pTail = pNew 重复了,删去之后,发现不行,下面对两者的区别进行画图解析:
第1步:*pTail的地址就是pHead,所以pHead指向*pTail,另外,新创建的*pNew还没有赋值。
第2步:将val赋值给*pNew的数据域,NULL赋值给*pNew的指针域,并把*pNew的地址传给*pTail的指针域
第3步:把*pNew的地址赋值给pTail,让*pNew变成新的*pTail
整个过程大致就是如此,理解了,其实也不难,要掌握更多的知识,需要进一步学习数据结构。