摧毁和清空的含义及区别
摧毁
是先销毁了链表的头,然后接着一个一个的把后面的销毁了,这样这个链表就不能再使用了,即把包括头的所有节点全部释放。
清空
是先保留了链表的头,然后把头后面的所有的都销毁,最后把头里指向下一个的指针设为空,这样就相当与清空了,但这个链表还在,还可以继续使用;即保留了头,后面的全部释放。
区别:
清空是链表的头还在,可以继续插入节点;销毁就是链表没了,整个链表(包括头)的空间都被释放了,不能进行任何操作了。
摧毁链表实例
int destroy(struct node *head)
{
struct node *p; //定义结构体指针
if(head==NULL)//如果链表不存在则返回0
{
return 0;
}
while(head != 0)//如果存在则进行摧毁,直到head为空,所有节点被销毁
{
p = head->next;//把head指向的下一个节点被P保存
free(head);//释放掉head指向的节点
head = p;//把P保存的节点被head保存
}
};
清空链表实例
int clear(struct node *head)
{
struct node *p;//定义结构体指针
struct node *q;
if(head == 0)
{
return 0;
}
p = head->next;//把头节点的下一个节点被p保存
while(p != 0)//当p存在时,进行清空操作
{
q = p->next;//使q保存p指向的下一个节点
free(p);//释放掉P里的内容
p = q;//让p保存q指向的节点
}
head->next = NULL;//当上面循环完成时,已经只有一个头结点存在,使head- >next=NULL,表示链表结束
};
下面是完整代码示例
发现一个vi编辑器的小技巧,:set nonumber可以删除代码前的序号
/*********************************************************************************
* Copyright: (C) 2017 fanmaolin<fanmaolinn@gmail.com>
* All rights reserved.
*
* Filename: make4.c
* Description: This file
*
* Version: 1.0.0(08/05/2017)
* Author: fanmaolin <fanmaolinn@gmail.com>
* ChangeLog: 1, Release initial version on "08/05/2017 07:24:41 AM"
*
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#define LEN sizeof(struct node)
struct node
{
int data;//存储数据
struct node *next;//指向下一个节点
};
int n;//统计是第几个节点
struct node *creat()
{
struct node *head;//头指针,指向第一个节点
struct node *p1 = NULL;//p1保存创建的新节点的地址
struct node *p2 = NULL;//p2保存原链表最后一个节点的地址
n = 0;
p1 = (struct node *)malloc(LEN);//新建一个节点
p2 = p1;
if(p1==NULL)//创建节点失败
{
printf("creat fail\n");
return 0;
}
else
{
head = NULL;//头指针为空
printf("please input %d node\n",n+1);
scanf("%d",&(p1->data));//输入数据
}
while((p1->data)!=0) //循环进行的条件
{
n = n + 1;//计算创建的节点数
if(n==1)
{
head = p1;//head保存头结点的位置
p2->next = NULL;//因为前面p1 = p2,而且现在只有一个节点,把next设置为空
}
else
{
p2->next = p1;//当不是第一个节点时,p2的next指向p1新创建的节点
}
p2 = p1;//p2保存p1的指向的节点,为p1创建新的节点做准备
p1 = (struct node *)malloc(LEN);//p1创建新的节点
printf("Please input %d node\n", n+1);
scanf("%d", &(p1->data));//向新的节点输入数据
}
p2->next = NULL;//最后一个节点指向为空
free(p1);//释放结束时p1申请的内存空间
p1 = NULL;//避免p1成为野指针
return head;//返回头指针
};
void print(struct node *head)
{
struct node *p;
p = head;
printf("head is %o\n", head);
do
{
printf("p is %o ,data is %d, pnext is %o\n", p, p->data, p->next);//打印节点的地址,数据,下一个节点的地址
p = p->next;//p指向下一个节点
}while(p != NULL);
};
int destroy(struct node *head)
{
struct node *p;//定义结构体指针
if(head==NULL)//如果链表不存在则返回0
{
return 0;
}
while(head != 0)//如果存在则进行摧毁,直到head为空,所有节点被销毁
{
p = head->next;//把head指向的下一个节点被P保存
free(head);//释放掉head指向的节点
head = p;//把P保存的节点被head保存
}
make4.c
};
int clear(struct node *head)
{
struct node *p;//定义结构体指针
struct node *q;
if(head == 0)
{
return 0;
}
p = head->next;//把头节点的下一个节点被p保存
while(p != 0)//当p存在时,进行清空操作
{
q = p->next;//使q保存p指向的下一个节点
free(p);//释放掉P里的内容
p = q;//让p保存q指向的节点
}
head->next = NULL;//当上面循环完成时,已经只有一个头结点存在,使head->next=NULL,表示链表结束
};
int main(void)
{
struct node *head;
head = creat();//创建链表
print(head);//打印链表信息
destroy(head);摧毁链表
//clear(head);//清空链表
print(head);检查摧毁或清空的效果
}
摧毁结果
[fanmaolin@Centeros lianbiao]$ gcc make4.c
[fanmaolin@Centeros lianbiao]$ ./a.out
please input 1 node
1
Please input 2 node
2
Please input 3 node
3
Please input 4 node
4
Please input 5 node
5
Please input 6 node
0
head is 155540020
p is 155540020 ,data is 1, pnext is 155540060
p is 155540060 ,data is 2, pnext is 155540120
p is 155540120 ,data is 3, pnext is 155540160
p is 155540160 ,data is 4, pnext is 155540220
p is 155540220 ,data is 5, pnext is 0
head is 155540020
p is 155540020 ,data is 28754080, pnext is 155540060
p is 155540060 ,data is 28753920, pnext is 155540120
p is 155540120 ,data is 28753952, pnext is 155540160
p is 155540160 ,data is 28753984, pnext is 155540220
p is 155540220 ,data is 28754016, pnext is 0
可以清楚的看到,摧毁链表后数据已经变为垃圾数据,链表不能使用
清空效果
[fanmaolin@Centeros lianbiao]$ gcc make4.c
[fanmaolin@Centeros lianbiao]$ ./a.out
please input 1 node
1
Please input 2 node
2
Please input 3 node
3
Please input 4 node
4
Please input 5 node
5
Please input 6 node
0
head is 33470020
p is 33470020 ,data is 1, pnext is 33470060
p is 33470060 ,data is 2, pnext is 33470120
p is 33470120 ,data is 3, pnext is 33470160
p is 33470160 ,data is 4, pnext is 33470220
p is 33470220 ,data is 5, pnext is 0
head is 33470020
p is 33470020 ,data is 1, pnext is 0
可以看到清空链表后,仅仅只有表头存在,依然可以进行插入等操作。
总结:
关于摧毁链表后依然可以根据头指针找到后面链表的地址
首先,我们虽然free()掉了,但是在没有其他人使用那块地址时,指针依然指向那块地址。假设你是新生时学校给你分配了宿舍,你一直记得,等你毕业离开时宿舍依旧存在,你也记得宿舍,但是你现在不能住了。
发现一个vi编辑器的小技巧,:set nonumber可以删除代码前的序号,U撤回之前的操作
参考链接:http://blog.youkuaiyun.com/bzhxuexi/article/details/41721429