有关链表(第六阶段笔记-星期一记录)
在csdn写过链表,当时没有熟悉markdown的语法,所以排版很糟糕,虽然排版目前也不怎么样,但是看还是可以的。很用心去研究链表了。我将我的思想写下来。
结点这个词组可能写的不对,还希望原谅,明白意思就好。
结构体指针通过动态内存申请,会转变为结构体变量,你理解了吗?如果不对,请指教。
当然啦,结构体的理解是学好链表的前提。众所周知,链表这种数据结构在数据结构与算法中的地位是极其重要的。我拼了也要把它搞懂。
1:先总结一下如何创建静态链表
显然这个没有任何难度,所谓静态就是它的内存空间并不是动态分配的,这应该是与动态链表的一个主要的区别。静态链表很明显是采用数组来实现这种连续的存储结,动态链表是通过不断动态申请内存空间的,所以链表的长度上没有限制。物理地址的不连续,导致动态链表需要我们使用指针去很好的访问。
终于可以自己完整的写出这两种链表了,先从静态开始。
简单建立一个静态链表
//静态链表的创建 #include<stdio.h> typedef struct Student{ int age; struct Student *next; }stu1; int main(){ int i; int age1; stu1 stu[4];//申明变量,静态链表用数组来代替指针,很明显,这种空间是固定的。 printf("请给结构体变量赋值\n"); for(i=0;i<3;i++){ scanf("%d",&age1);//现在给各结点的数据域赋值 stu[i].age = age1;//用.引用的话,是结构体变量的特权。如果是->,那就是结构体指针引用的方式 } stu1 *head =&stu[0];//定义一个头指针指向第一个元素,只是指针,没有空间,所以head不是结点。可以认为,当定义的指针,赋予它空间的时候,那么就会成为结点。 stu[0].next = &stu[1];//一下是各个结点串起来,很好理解,依次类推 stu[1].next = &stu[2]; stu[2].next = &stu[3]; stu[3].next =NULL;//没有在stu[3]里面存数据,并且将其指针域的指向赋值为NULL while((head->next!=NULL)){ printf("%d\n",head->age); head=head->next; } return 0; }
简单建立一个动态链表
插入我的小小的潦草的草稿比划,希望有用。哈哈哈哈
动态链表的各方面理解的话,可能并不是很好理解,在不断学习的过程中,一定要有直接的理解,永远顺从别人的代码思路去理解看的话很大可能在后来还回迷惑。比较管用的学习方式就是一定自己去写,并加以思考。
//goal:实现动态申请单链表(动态内存分配)采用了头插法实现 #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct Student { int age;//数据域 struct Student* next;//指针域 }Student; Student* create_head(Student *head){//创建头结点 head = (Student*)malloc(sizeof(Student)); head->next=NULL; //printf("Hello"); if(head == NULL){ printf("空间申请失败\n"); }else{ printf("申请空间成功\n"); } return head; } Student*insert(Student *head){//插入结点,本次采用了头插法,每个插入方法只要理解一种,就基本都通了。关键在于理解这个过程 int i=1; Student *p1 = head;//好,定义一个指针指向头结点,再次申明此处没有给指针申请空间,并不等同于结点。 p1->next = NULL; printf("请输入要插入结点数据域的值\n"); printf("输入1结束输入\n"); while(i!=0){ scanf("%d",&i); Student *p2 = (Student*)malloc(sizeof(Student));//此处给p2申请了空间,所以可以注意一下两者的区别以及用法。 p2->age = i; p2->next = p1;//插入连接 p1 = p2;//将p1指针指向p2结点,我这样说就很区别了。因为要用p2申请空间,然后p1会对其进行连接插入的操作。 } return p1; } Student *printf1(Student *head){//打印操作 Student *p = head; if(p->next==NULL){ printf("没有可遍历的结点\n"); }else{ printf("可遍历的结点的值为\n"); while(p->next!=NULL){ printf("%d,",p->age); p=p->next; } } } int main() { Student *head= create_head(head); Student * p2 = insert(head); printf1(p2); return 0; }
一个小小的感想:
终于把动态链表自己去按照自己的思想写出来了。相比当初大一下学期假期在家里上数据结构是并不是太好。近来一定要把不会的东西自己补起来。当我完整的将他人讲课的思维转换为我自己的思维的时候,并可以实现出来完整的东西,这是多么让人喜悦的事情啊。我不怕花费太多的时间,当然前提是自己一直在思考,这个过程充满了痛苦与苦恼,但是很有趣,根是苦的,但是果实是甜的。