c语言单链表释放内存函数,C++链表如何释放内存

C语言链表中释放内存函数的问题,请高手解答。

首先你要搞明白,List本身已经被定义为Node*类型,因此List*实际上是一个二级指针

鹿城ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为创新互联的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:18982081108(备注:SSL证书合作)期待与您的合作!

你的疑问中,如果改成*list = p-next,运行应该是可以通过的。但是不推荐这样做。为什么呢?

这就要先理解FreeMem这个函数,为什么用List*做参数,而不是List。如果只是为了释放链表内存,只要一级指针就可以了,用二级指针只会增加代码的复杂程度,降低可读性。二级指针的作用就在于,在这个函数内,你可以修改这个函数的主调函数(比如main函数)中链表头结点的指针值。在这个例子中,显而易见的就是,链表释放了内存,head指针应该是NULL。

如果上面这段话你能明白的话,那么我的建议是,使用你问题中“可行”的那段代码,并添加*list = NULL;在结尾。或者这样做也可以达到同样的效果:传入参数使用一级指针,配合函数的返回值来保证功能的完整性,这样调用的时候需要诸如head = FreeMem(head);以达到释放内存后置head指针为NULL的目的。

看了楼主的追问,看来楼主对二级指针的理解还不太到位。其实mornslit兄的解释已经说清楚你这种写法的问题在哪了。我再帮你分析下:

pt = p-next;

*list = p-next;

这两种写法,效果是一样的,都是保存了下一个节点的地址(也就是p-next的值)

list = p-next;

这种写法,是保存了p这个节点的next指针的地址,通过*运算,看似可以获取next的值,其实在p被free掉之后,next指针本身的值已经不能保证了

简言之,你错在哪了:p-next是下一个节点的地址,是与p共存亡的,你可以保存p-next的值,但不应该保存它的地址

说实话,还是建议楼主先搞清楚为什么要用二级指针,杀鸡用牛刀未必一定好~

编写一个C语言程序 实现单链表的基本操作

# include stdio.h

# include malloc.h

# include stdlib.h

typedef struct Node

{

int data;

struct Node * pNext;

} * PNODE, NODE;

PNODE establish_list (void);

void traverse_list (PNODE pHead);

bool is_empty(PNODE pHead);

int length_list(PNODE pHead);

void sort_list(PNODE pHead);

void insert_list(PNODE pHead, int pos, int val);

int delete_list(PNODE pHead, int pos, int val);

void freeer(PNODE pHead);

int main(void)

{

PNODE pHead;

int len, i, j, val;

pHead = establish_list();

traverse_list(pHead);

if(is_empty(pHead))

printf("链表为空\n");

else

printf("链表不空\n");

len = length_list(pHead);

printf("链表的长度为: %d\n", len);

sort_list(pHead);

traverse_list(pHead);

printf("请输入您要在第几个节点插入\n");

scanf("%d", i);

printf("请输入您要在第%d个节点插入的值\n", i);

scanf("%d", j);

insert_list(pHead, i, j);

traverse_list(pHead);

printf("请输入您要第几个删除的节点\n");

scanf("%d", i);

val = delete_list(pHead, i, val);

printf("您删除的节点值为: %d\n", val);

traverse_list(pHead);

freeer(pHead);

return 0;

}

PNODE establish_list(void)//初始化链表,返回头结点地址

{

int val, len;

PNODE Tem;

PNODE pNew;

PNODE pHead;

pHead = (PNODE)malloc(sizeof(NODE));

Tem = pHead;

if(NULL == pHead)

{

printf("分配失败");

exit(-1);

}

Tem-pNext = NULL;

printf("请输入您要定义节点的长度: ");

scanf("%d", len);

for (int i=0;ilen;++i)

{

printf("请输入第%d个节点的值: ", i+1);

scanf("%d", val);

pNew = (PNODE)malloc(sizeof(NODE));

if(NULL == pNew)

{

printf("分配失败");

exit(-1);

}

pNew-data = val;//首先把本次创建的新节点的值付给新节点的数据域

Tem-pNext = pNew;//然后使用临时的节点变量的指针域保存了新节点的地址,也就是指向了新节点

pNew-pNext = NULL;//如何再不循环,新节点成为最后一个节点

Tem = pNew;//把本次分配的新节点完全的赋给Tem,Tem就成为了这次新节点的影子,那么下次分配新节点时可以使用上个新节点的数据

}

return pHead;

}

void traverse_list(PNODE pHead)

{

PNODE p = pHead;//使用P是为了不改写头结点里保存的地址

p = pHead-pNext;//使P指向首节点

while(p != NULL)//P本来就是头结点的指针域,也就是首节点的地址,既然是地址就可以直接判断p是否等于NULL

{

printf("%d ", p-data);

p = p-pNext;//使P每循环一次就变成P的下一个节点

}

}

bool is_empty(PNODE pHead)

{

if(NULL == pHead-pNext)

return true;

else

return false;

}

int length_list(PNODE pHead)

{

PNODE p = pHead-pNext;

int len = 0;

while(p != NULL)

{

len++;

p = p-pNext;

}

return len;

}

void sort_list(PNODE pHead)

{

int i, j, t, len;

PNODE p, q;

len = length_list(pHead);

for(i=0,p=pHead-pNext;ilen;i++,p=p-pNext)//逗号后只是为了找到下一个节点,因为不是数组,所以不能使用下标来++

{

for(j=0,q=pHead-pNext;jlen;j++,q=q-pNext)

if(q-data p-data)//这里的大小与号可以决定是升序还是降序,如果是大于号就是升序,反之小于号就是降序

{

t = q-data;

q-data = p-data;

p-data = t;

}

}

return;

}

void insert_list(PNODE pHead, int pos, int val)

{

int i;

PNODE q = pHead;

PNODE p = pHead;

if(pos 0 pos = length_list(pHead))

{

for(i=0;ipos;i++)

{

q = q-pNext;//q就是要插入的连接点

}

for(i=1;ipos;i++)

{

p = p-pNext;//p就是要插入连接点的前一个节点

}

PNODE pNew = (PNODE)malloc(sizeof(NODE));

p-pNext = pNew;

pNew-data = val;

pNew-pNext = q;

}

else if(pos length_list(pHead))//追加

{

PNODE t;

t = pHead;

PNODE PN;

PN = (PNODE)malloc(sizeof(NODE));

if(PN == NULL)

printf("分配失败");

else

while(t-pNext != NULL)

{

t = t-pNext;//使T-pNext成为尾结点

}

PN-data = val;//给新节点赋予有效数据

t-pNext = PN;//使尾结点的指针域指向了新的结点

PN-pNext = NULL;//新节点成为尾结点

}

else

printf("error\n");

return;

}

int delete_list(PNODE pHead, int pos, int val)

{

int i, j;

PNODE q, p;

q = pHead;

p = pHead;

if(pos 0 pos = length_list(pHead))//保证删除的是节点的有效数

{

for(i=0;ipos;i++)

{

p = p-pNext;

}

for(j=1;jpos;j++)

{

if(pos == 0)

q = pHead;

else

q = q-pNext;

}

q-pNext = p-pNext;

val = p-data;

free(p);

return val;

}

else

printf("error");

}

void freeer(PNODE pHead)

{

PNODE pT = pHead;

while(NULL != pHead-pNext)

{

free(pT);

pT = pT-pNext;

}

return;

}

/*

好久以前写的一个链表了,有排序,插入,删除,输出,判断是否为空,甚至还有释放堆中内存的功能

*/

C语言中是如何释放内存单元的;原理又是什么?

C管理内存大致可以理解为两种,分配在栈上的,一个是分配在堆上的。

临时变量,动态变量,分配在栈上,运行完,直接弹出栈,就没了。

分配在堆上的内存,释放的时候,基本上可以理解为,指针不指这里了。也就失去了对这块内存的控制。其实所谓的释放。字面意思容易让人理解错。

有些机器有些操作系统,会在释放的时候清空这段内存,但是这种做法效率不高,但是安全,很少有机器这么做,多数都是所谓释放,就是不让你控制这块内存了而已。

C语言 链表 释放,清楚之类的问题不是很清楚。

写法一主函数少了clear调用,写法2好像不能全部释放内存吧,L你最后只是设置为空,但没有delete掉。

两个写法区别就是一个是在主函数中调用函数,另一个是直接在主函数里面进行操作,对于你这小问题两者都行,但大一点问题,比如学生信息管理系统,第一种方法比较好。

C语言释放链表内存的问题

把链表创建的函数贴出来。否则难以判断。

还有LNode 和LinkList的类型定义贴出来

再请求一次,把LNode 和LinkList的类型定义贴出来!

从 L-next;的用法,我推测LinkList是一个结构体指针类型,,作用是指向链表头。可是你在malloc的时候,用的sizeof(LinkList)),也就是对指针类型取size,通常固定是4,也就是说的你原意是要申请一个结构体大小的buff,结果是申请到一个指针大小的buf

如果LinkList是一个结构体类型,而不是指针类型,那么s=L 这样的语句就是彻底错误的,要知道void ListFree(LinkList L),这里的L是局部变量,进入函数时从堆栈中得到的,而不是你malloc出来的。所以你的free一定是失败的。


当前标题:c语言单链表释放内存函数,C++链表如何释放内存
文章地址:http://scyanting.com/article/hseeoi.html