小牛成长记--链表学习
寒假已经过去了吗? 哎,
寒假刷了一下数据结构,由于时间问题,刷的比较快,说实话有很多知识点都没掌握,就像是上英语课一样,老师教你一遍单词,你只能说你知道这个单词了,却不能说你会了。我就是这样的
首先说一下需掌握的链表知识点:1.结点的概念。
2.单链表的建立:包括正序建表和逆序建表。
3. 单链表结点的查找,插入,删除。
4. 单链表的逆置,归并, 拆分。
今天我又看了一下链表(因为当时没刷完题,有些题还不能太熟练地敲出,这样是不可以的),我们的课本也不知道怎么了,刚介绍完几种内存分配方式,当然重点是动态内存分配,然后直接开讲单链表节点的基本操作,比如单链表结点的查找,插入,删除。 。。。我想说的是我当时只是对单链表的基本组成单元--节点有了初步认识,对单链表都没有个整体概念,这可让我怎么学啊。所以第一次直接跪了。看的我雨里雾里的,好在一不小心往后翻书的时候看到了单链表的建立,顿时泪奔,然后就把单链表的头插法和尾插法给收了,为我所用,我此时又多了一项技能。真不好意思。
然后再返回来继续攻克单聊表的应用,时间不等人啊,此时已经过去了一上午和一下午,晚上还有任务--刷题,不过不怕,因为我觉得刷10道题,不如把一个知识点完全掌握,顿时我又来了激情。继续奋战。既然说到这了,我想你可能总结了一下学习单链表的顺序吧,哈哈,看来我猜对了。 首先对结点要了解,然后从基本组成单元到整体,也就是从结点到单链表,现在可能你非常好奇如何建立单链表吧,那就学习如何建立单链表吧。
建立单链表有两种方法:1.逆序建立单链表(头插法); 2.顺序建立单链表(尾插法);
首先先讲一下顺序建表:1.首先建立一个头结点(不理解可以google一下)。2.然后就是开始建表了,现贴代码讲一下:
代码(顺序建立链表):
struct node *head, *tail, *p;//定义结构体类型的指针变量head,tail,p,其中tail充当游动指针 head = (struct node*)malloc(sizeof(struct node));//建立空节点,不放数据,只存放第一个节点的地址 head->next = NULL;//指空 tail = head;//头指针和尾指针开始时都指向head for(i=1; i<=n; ++i)//假设要建立n个节点,所以循环n次 { //接下来为尾插法的核心代码 p = (struct node *)malloc(sizeof(struct node));//申请内存,共申请n次 scanf("%d", &p->data);//每申请一个结点,往里输入一个数据 p->next = NULL; tail->next = p;//连接新申请的结点 tail = p;//使tail指针往后移动一位 }再讲一下逆序建立链表:步骤和顺序建表差不多,只须改下核心代码即可:
代码:
struct node *head, *p;//定义结构体类型的指针变量head,p,其中p充当游动指针 head = (struct node*)malloc(sizeof(struct node));//建立空节点,不放数据,只存放第一个节点的地址 head->next = NULL;//使头结点指空 for(i=1; i<=n; ++i)//假设要建立n个节点,所以循环n次 { //接下来为头插法的核心代码 p = (struct node *)malloc(sizeof(struct node));//申请内存,共申请n次 scanf("%d", &p->data);//每申请一个结点,往里输入一个数据 p->next = head->next;//把头结点后的第一个结点的地址赋给p(注意:当第一次循环时,head->next 指向NULL //此时p指针指向为空),则p指向头结点的下一个结点。 head->next = p;//使p结点连在head结点后。 }
建立完后,你又想了,我建单链表到底有什么用啊,这时你碰巧发现了单链表的应用。
你此时是不是忽然想起了数组,。。。对。。。,我记得在数组中可以查找,删除,或插入某个值,那么在链表中可不可以呢?
答案是肯定的,而且比用数组更简洁。
1.查找
首先来看一下如何在链表中查找某个值是否存在吧,核心代码:
struct node { int data; struct node *next; }; struct node *search(struct node *head, int key) { struct node *p;//p为游动指针 p = head->next;游动指针指向第一个实际结点 while(p!=NULL) { if(p->data==key) return(p);//找到,返回该节点的地址 else p = p->next;//未找到,指向下一个结点继续查找 } return NULL;//循环正常结束,说明不存在该节点 }
查找是不是很简单啊,就像在数组中查找某元素是否存在一样。在数组中是借助下标来遍历整个数组,而在单链表中是借组指针(next 指针)来遍历。现在你应该掌握了单链表的查找吧,不要着急,接下来你就要学习单链表的插入了,在讲之前,首先回忆一下,怎么往数组中插入一个元素呢?,其实往数组中也是可以插入某个元素的,但是比较麻烦,有兴趣的同学可以自己写一下,那么有没有更简单的方法呢?
当然有了,那就是用链表代替数组,往单链表中插入元素就会很简单了。接下了就讲讲如何往单链表中插入元素。
2.插入
思路:假如现在需往1, 2两个结点中插入3结点,那么只需把第一结点中存放的地址赋给3,然后再把第三个结点的地址赋给第一个结点即可。
是不是很简单啊
核心代码:
void insert(struct node *head, int key)
{
struct node *q;
q = (struct node *)malloc(sizeof(struct node));
if(!q)
{
printf("不能分配内存空间!");
exit(0);
}
q->data = key;//在p结点后插入q结点
q->next = NULL;
q->next = p->next;
p->next = q;
}
现在你已经知道了如何往单链表中查找结点,如何插入结点,还有就是如何删除某个结点呢?
3.删除
思路:假如现在需在1, 3两个结点中删除2结点,那么只需把第3个结点的地址赋给1,然后再把第2个结点的释放(free())即可。
核心代码:
//此函数为删除带头结点的单链表中第一个值为key的结点的函数
int del(struct node *head, int key)
{
struct node *p, *q;
int flag = 0;
p = head;
while(p->next!=NULL)
{
if(p->next->data==key)
{
flag = 1;
break;
}
else
p = p->next;
}
if(flag==1)
{
q = p->next;
p->next = q->next;
free(q);
return 1;
}
else
return 0;
}
以上就是对单链表的基础操作,现在是不是很高兴啊,你已经掌握了单链表的基础知识了,接下来你会发现,这些基本操作是多么的重要;
接下来就应该更上一层了.,你做好准备了吗?
由于课程太紧,所以只能分几次写了
。。。。。。。。。。。。。。。。。。。。未完未完未完未完。。。。。。。。。。。。