带头节点链表的创建:
初始化一个头结点(包含指向下一个节点的POINT *next),
执行初始化前判断这个链表是否有效
if(NULL == head) {
return FALSE;
}
主要部分:
添加节点分两种情况:
①添加的是第一个节点,直接让头结点指向现节点即可
②需在链表末尾添加节点,这时tail的作用就显现出来,tail是上次录入节点后的末尾节点,因为是末尾添加,直接让tail指向新节点即可
if(NULL == head->next) {
head->next = p;
} else {
tail->next = p;
}
tail = p;
重点:查找前驱节点:
所实现的前插入,删除都需要前驱节点。
定义两个POINT *类型 一个p遍历链表查找所要寻找的节点,另一个pre记录p的上一个节点
for(p = head.next; p; p = p->next) {
if (p->row == row && p->col == col) {
return pre;
}
pre = p;
}
最后返回pre
删除节点:
找到所要删除的节点的前驱节点,让前驱节点pre的next实例跳过所删节点p后 释放p空间
p = pre->next;
pre->next = p->next;
free(p);
插入节点:
类似于删除节点,新节点p的next指向pre->next,前驱节点的next指向新节点p
p->next = pre->next;
pre->next = p;
注:
①若前驱节点没有找到,返回值是最后一个节点,pre != NULL,但pre->next == NULL
②若所查找的节点为链表第一个节点,则前驱节点应为头结点,但实际的pre返回值为NULL,所以对于第一个节点的删除,前插入操作需要额外将pre赋值为头结点head
节点排序:
节点排序利用冒泡循环
for(p = head->next; p; p = p->next) {
for(q = p->next; q; q = q->next) {
}
}
但对于链表的冒泡排序,替换完节点内容后,所替换的节点的next实例应换回来,
如:1->4->3->2
2和4内容交换后,1->2 3->4->3 2的next实例是NULL,4的next指向3,若2和4的next不交换,链表无法连起来
所以交换过程如下:
temp = *p;
*p = *q;
*q = temp;
next = p->next;
p->next = q->next;
q->next = next;
摧毁链表:
因为链表除了头结点都是利用malloc或calloc申请空间实现,在程序运行完后应释放所申请的空间,
从第一个节点开始,p用于记录当前节点,先将头结点指向改为当前节点的指向,这样释放遍历才能进行。
若p不为空,释放p,用p重复操作,记录,改指向,释放。
p = head->next;
while (p) {
head->next = p->next;
free(p);
p = head->next;
}
本文详细解析了带头节点链表的创建、节点添加、删除、插入及排序等操作流程,包括查找前驱节点的技巧,以及如何正确处理链表冒泡排序中节点的next指针,最后介绍了链表摧毁的步骤。
2011

被折叠的 条评论
为什么被折叠?



