链表
在学到链表时我停留了很长时间,或许是强迫症,总是想要把一小段代码读懂,磨了好久才想通。
接下来让我来讲讲我对链表的理解吧。
创建链表的代码(我苦思冥想的部分)奉上
struct Student* Create()
{
struct Student* pHead=NULL;
//定义结构体头指针并指向为空
struct Student* pConnect;
//定义用来连接链表的连接指针(也许你很迷茫,但请先这么想着)
struct Student* pNew;
//定义新节点
iCount=0;
iCount++;
//全局变量自加
pConnect=pNew=(struct Student*)malloc(sizeof(struct Student));
//为这两个指针分配内存(不理解?后面细说)
printf("输入数据:\n");
scanf_s("%d\n",pNew->Data);
//分配好了内存就可以输入并存储数据了
//重点来了
while(pNew->Data!=0)
{
if(iCount==1)
{
pNew->pNext=pHead;
//第一个新节点结构体的尾部指向NULL(后面没有新节点就还是NULL,如果有就会被覆盖,沙子填空桶式操作嘛)
pConnect=pNew;
//连接指针指向第一个新节点
pHead=pNew;
//头指针指向第一个新节点(即开端)
//这三段代码可以这样表述:
//pNew,pConnect,pHead都指向同一个地址,但这只是第一个节点展现出的情况,与第二个节点连接这三个指针的功能就会被区分开:
//pNew为新节点的创建提供支持,
//pConnect为节点之间的连接提供支持,
//pHead为链表的开头(保持初始,它不用动,这就是为什么这个函数的后半段代码没它的戏份的原因。)
}
else
{
pNew->pNext=NULL;
//第二个(或第n个)新节点结构体的尾部指向NULL
pConnect->pNext=pNew;
//连接指针结构体的尾部指向第二个(第n个)新节点,这不就连接上了么
pConnect=pNew;
//连接指针重新指向第二个(第n个)新节点,为的是下次再和第三个(第n+1个)新节点连接上
//要是没有这一步第二个(第n个)新节点可就有兄弟了(第二个新节点与第三到第n个节点并列,计算机该选择哪个节点呢?)
}
pNew=(struct Student*)malloc(sizeof(struct Student));
//新节点重新分配内存
scanf_s("%d\n",pNew->Data);
}
free(pNew);
//释放新节点未使用的内存
return pHead;
//返回头指针
};
这样就结束了,对了,还有一段代码我需要解读一下,既然这样,完整的代码我直接连带打出来好了。
pNew=(struct Stduent*)malloc(sizeof(struct Stuent));
左侧,普普通通的指针没啥说的
右侧,
(struct Student*)
看到括号了么,强制转换为结构体指针类型 sizeof,这个本身是测量类型所占内存大小的一个。。。东东吧。
malloc的用法是:void*malloc(unsigned int size)
动态分配一块内存大小为size的内存空间,malloc会返回一个指向分配内存空间的指针,如果出现错误就返回NULL。这要清楚哦。
接下来就是代码时间(累晕了啊)
完整创建链表的代码
#include<stdio.h>
#include<stdlib.h>
//这个预处理文件是给malloc函数以支持的
struct Student
{
int Data;
//数据域
struct Student* pNext;
//指向下一个节点的尾指针
};
//Student结构体
int iCount;
//定义全局变量
struct Student* Create()
{
struct Student* pHead=NULL;
//定义结构体头指针并指向为空
struct Student* pConnect;
//定义用来连接链表的连接指针(也许你很迷茫,但请先这么想着)
struct Student* pNew;
//定义新节点
iCount=0;
iCount++;
//全局变量自加
pConnect=pNew=(struct Student*)malloc(sizeof(struct Student));
//为这两个指针分配内存(不理解?后面细说)
printf("输入数据:\n");
scanf_s("%d\n",&pNew->Data);
//分配好了内存就可以输入并存储数据了
//重点来了
while(pNew->Data!=0)
{
if(iCount==1)
{
pNew->pNext=pHead;
//第一个新节点结构体的尾部指向NULL(后面没有新节点就还是NULL,如果有就会被覆盖,沙子填空桶式操作嘛)
pConnect=pNew;
//连接指针指向第一个新节点
pHead=pNew;
//头指针指向第一个新节点(即开端)
//这三段代码可以这样表述:
//pNew,pConnect,pHead都指向同一个地址,但这只是第一个节点展现出的情况,与第二个节点连接这三个指针的功能就会被区分开:
//pNew为新节点的创建提供支持,
//pConnect为节点之间的连接提供支持,
//pHead为链表的开头(保持初始,它不用动,这就是为什么这个函数的后半段代码没它的戏份的原因。)
}
else
{
pNew->pNext=NULL;
//第二个(或第n个)新节点结构体的尾部指向NULL
pConnect->pNext=pNew;
//连接指针结构体的尾部指向第二个(第n个)新节点,这不就连接上了么
pConnect=pNew;
//连接指针重新指向第二个(第n个)新节点,为的是下次再和第三个(第n+1个)新节点连接上
//要是没有这一步第二个(第n个)新节点可就有兄弟了(第二个新节点与第三到第n个节点并列,计算机该选择哪个节点呢?)
}
pNew=(struct Student*)malloc(sizeof(struct Student));
//新节点重新分配内存以供下面输入的数据使用
scanf_s("%d\n",&pNew->Data);
}
free(pNew);
//释放新节点未使用的内存
return pHead;
//返回头指针
};
//Create创建链表
void Print(struct Student* pHead)
{
int iIndex=0;//定义循环变量记录链表节点个数
while(pHead!=NULL)
{
iIndex++;
printf("NO%d.:\n",iIndex);
printf("%d\n",pHead->Data);
printf("\n");
pHead=pHead->pNext;
//头指针指向第二个(第n个)节点
}
}
//打印链表
int main()
{
struct Student* pHead;//可以不是pHead,这个pHead和前面定义的没关系
pHead=Create();//使刚刚定义的指针指向Create返回的pHead的地址值
Print(pHead);
return 0;
}
//主函数
自己写的代码可能多多少少有些问题,我测试过,好像前面输入的数反倒到了后面,不过无伤大雅,嘿嘿,不管怎么说,自己想出来的代码才能被自己真正接受,希望各位能有所启发吧。