第一篇博文,谈一谈链表吧。因为学的时候困于书上艰涩难懂的定义,所以想尽力用比较通俗的精炼的话语来解释链表。
先说说单链表,与其回答单链表是什么的问题不如回答链表像什么的问题来的更通俗易懂,有人会说链表像一列火车,我觉得其实不是很像,因为火车往往是显性的,而链表给我的感觉往往是隐藏在内存之中的。链表更想散落在世界各地的宝箱,每一个宝箱除了里面的宝藏外,还藏着一张藏宝图。用这张藏宝图才能找到下一个宝箱。而想要获得这一连串宝箱的任何一个,你都必须要先找到第一张藏宝图。
一. 构造一个链表
1. 好,故事的开头就从一个个藏宝箱开始吧,这一个个藏宝箱就是一个个结点。根据我们上面的描述,节点应含有以下两个内容:1.结构体所要承载的内容(宝藏)2.指向下一个节点的指针(藏宝地图)。
typedef struct *treasure
{
int a;//宝藏a
char b[20];//宝藏b
struct *treasure;//下一个宝藏的藏宝图
}Treasure;
然后我们得找个地方把这个箱子放好
Treasure *node;
if(node=(Treasure *)malloc(sizeof(Treasure))==NULL);//看是否有地方放宝藏
exit(1);//没有的话,就异常退出。
else
{
scanf("%d\n%c\n",&node->a,node->b)//放宝藏,这里注意node->b前是没有&符号的,因为b是数组类型
}
2. 而第一个头结点比较特殊,他就仅仅是第一张藏宝图。但这张藏宝图至关重要,因为你没有他,就无法获得之后任何的宝藏。
Treasure *head;//藏宝图类型的数据
head==NULL;//没有宝藏,仅仅是个藏宝图
3.好了,到此为止,各个要素已经交代完了,现在该将他们链接在一起了
Treasure *p;(关于为什么要在额外设置一个指针,我的理解是node一直在开辟新地址的,需要有一个来存储node变化前的上一个地址)
if(head==0) //头结点为空的时候
{
head=node; //此node接第二条中的node
p=node ;
p->next=NULL;
}
else
{
p->next=node;
p=node;//始终保持p处在最后一个节点的位置。
p->next=NULL;
}
这就是一个简易的链表了。(文末附完整代码)。
二. 往一个已知的链表中加入节点。
这就要考虑到三种情况了,主要是考虑到插入位置与头结点的关系。
//想在头结点之前插入节点
Treasure *p,Treasure *q;//第三种情况会用到
Treasure *insertnode(Treasure *head,Treasure *node1)
{
if(head==0) //1.头结点为空的时候
{
head=node;
p=node ;
p->next=NULL;
return head;//返回头结点,因为他是整个链表的关键
}
else
if(strcmp(head->b,node1->b)>0)
{
node1->next=head;
head=node1;//head始终要为第一个节点
return head;
}
p=q=head;//为何要设两个节点的意义具体可参考前文
else if (strcmp(q->b,node1->b)<0)/*插在链表中*/
{
p=q;
q=q->next;
}//一直到找到结束
if(strcmp(q->b,node1->b)=0)
{
node1->next=q;//如果你要插一个节点进去,要将头尾都链进链表里
p->next=node1;
}
三.删除一个链表(也要分三种情况,还是与头结点有莫大联系)
Treasure *delete(Treasure *head,int n)//n是用来找删除位置的。
Treasure *p,*q;//老规矩,设置两个指针变量
if(head==NULL)
exit(1);//啥也没有,就啥也删不了。
else if(head->a==n)//巧了,要删的就是头结点
{
p=head;//存储原先头节点的位置。
head=head->next;//因为第一个头结点被删了,所以只能用第二个作头结点。
free(p);//删除原先头结点的位置。
}
p=q=head;
while(head->a!=n)
{
p=q;
q=q->next;//可参照前文的增加节点
}
if(head->a==n)
{
p->next=q->next;//跳过q链接在一起
free(q);释放q节点
}
十分钟搞定链表,看完不会你找我
最新推荐文章于 2023-08-26 13:07:25 发布