奥普瓯江 发表于 2018-2-19 23:39:46

链表的两种free释放方法,一种是学来的一种是自己更改的还请高手指点

我是一个刚学习链表的,这里有两种链表的free释放方法,一种是我通过视频学来的一种是,我通过,学写自己模仿出来的,我减少了一些指针的层次,但是不知道是不是,值的减少或者说减少了,指针的层次,反而增加运算的次序,还望高手能给指点一下我已经把两种的释放方式在程序中标注了出来,先在这里说声谢谢麻烦了。

#include<stdio.h>
#include<stdlib.h>


//建立一个节点类型
typedef struct Day
{
                int number;//建立数据域
                char name;
                struct Day *next;//建立信息域
}NODE, *PNODE;

void list(PNODE *head);//建立链表并调用付值函
void my_scanf(PNODE phead);//建立付值函数
void my_printf(PNODE head);//打印链表
void my_release(PNODE head);//这是自己改的释放方法
/*void my_release(PNODE *head); //这是通过视频学来的释放方*/

int main(void)
{
                int i = 3;
                PNODE head = NULL;//建立头节点并给头节点付空值
                /*head->next = NULL;*/
               
                while(i--)
                {
                                list(&head);//把新建的头结点指针的地址付给新建指针函数
                }

                my_printf(head); //打印链表函数调用
                my_release(head); //释放链表函数调用
                /*my_release(&head);//这是通过视频学来的释放方*/
                my_printf(head);//再次打印链表函数调用测试是否成功释放
                return 0;
}

//建立链表并调用付值函数
void list(PNODE *head)
{
                PNODE phead;//新建首节点
                PNODE temp;   //新建临时节点

                phead = (PNODE)malloc(sizeof(NODE));//给首节点分配内存储存空间
                //检测首节点分配内存地址是否成功
                if(phead == NULL)
                {
                                printf("内存地址分配失败!");
                                exit(1);
                }

                my_scanf(phead);

                if(phead != NULL)
                {
                                temp = *head;    //把头节点的地址传给临时节点
                                *head = phead;//把头节点的指针指向首节点
                                phead->next = temp;//在把临时节点中的头节点地址传给首节点中的信息域

                }
                //如果无数据输入则直接把头结点的指针指向首节点,并把首节点的信息域清空
                else
                {
                                *head= phead;
                                phead->next = NULL;
                }


}

//建立付值函数
void my_scanf(PNODE phead)
{
                printf("请输入一个数字:");
                scanf("%d", &phead->number);
                printf("请输入一个名字:");
                scanf("%s", &phead->name);
}
//打印链表
void my_printf(PNODE head)
{
                PNODE temp;

                while(temp != NULL)
                {
                                printf("您输入的数字是:%d\n", temp->number);
                                printf("您输入的单词是:%s\n", temp->name);
                                temp = temp->next;
                }
}
//释放链表函数
//这是通过视频学来的释放方法
/*void my_release(PNODE *head)
{
                PNODE temp;

                while(*head != NULL)
                {
                                temp = *head;
                                *head = (*head)->next;
                                free(temp);
                }
}*/

//这是自己改的释放方法
void my_release(PNODE head)
{
                PNODE temp;

                while(head != NULL)
                {
                                temp = head;
                                head = head->next;
                                free(temp);
                }
}

BngThea 发表于 2018-2-20 15:22:27

看你用head指针的意图了,如果只是用来做链表头部而不存放数据就需要第一种方式,如果你将第一个节点当做头结点,那么就可以用你的方式

ABC23 发表于 2018-2-21 09:47:57

free函数只能用来释放指针,你这里第二个函数传入的是一个结构体变量但不是结构体指针

奥普瓯江 发表于 2018-2-22 18:08:20

BngThea 发表于 2018-2-20 15:22
看你用head指针的意图了,如果只是用来做链表头部而不存放数据就需要第一种方式,如果你将第一个节点当做头 ...

你所说的头节点是不是就是我所说的首节点呢?还有一个问题你的意思是我这里的头节点是存放了数据的是么?我的意图是头节点不存放数据而是首节点存放数据,如果按照我的理解你说的是我自己写的这个释放方法没有达到,我的意图对么?
{:9_241:}
谢谢麻烦了

人造人 发表于 2018-2-22 20:27:48

NODE *head 的头结点不存放数据
#include<stdio.h>
#include<stdlib.h>

typedef struct NODE_tag
{
        int data;
        struct NODE_tag *next;
} NODE;

void ListAppend(NODE *head, int data)
{
        NODE *p = head;

        while(p->next != NULL)
                p = p->next;

        p->next = malloc(sizeof(NODE));
        p->next->data = data;
        p->next->next = NULL;
}

void ListPrint(NODE *head)
{
        NODE *p = head->next;

        while(p != NULL)
        {
                printf("%d ", p->data);
                p = p->next;
        }
        putchar('\n');
}

void ListFree(NODE *head)
{
        NODE *p = head->next;
        NODE *temp;

        while(p != NULL)
        {
                temp = p;
                p = p->next;
                free(temp);
        }

        free(head);
}

int main(void)
{
        NODE *head = malloc(sizeof(NODE));
        head->next = NULL;

        for(int i = 0; i < 10; ++i)
                ListAppend(head, i);

        ListPrint(head);
        ListFree(head);
        printf("head: 0x%.8X\n", (unsigned int)head);

        return 0;
}

0 1 2 3 4 5 6 7 8 9
head: 0x034B61E0
请按任意键继续. . .


但这并不是说 NODE *head 的头结点就不能存放数据
#include<stdio.h>
#include<stdlib.h>

typedef struct NODE_tag
{
        int data;
        struct NODE_tag *next;
} NODE;

void ListAppend(NODE *head, int data)
{
        NODE *p = head;

        if(head->data == -1)
        {
                head->data = data;
                return;
        }

        while(p->next != NULL)
                p = p->next;

        p->next = malloc(sizeof(NODE));
        p->next->data = data;
        p->next->next = NULL;
}

void ListPrint(NODE *head)
{
        NODE *p = head;

        while(p != NULL)
        {
                printf("%d ", p->data);
                p = p->next;
        }
        putchar('\n');
}

void ListFree(NODE *head)
{
        NODE *p = head->next;
        NODE *temp;

        while(p != NULL)
        {
                temp = p;
                p = p->next;
                free(temp);
        }

        free(head);
}

int main(void)
{
        NODE *head = malloc(sizeof(NODE));
        head->data = -1;        // 一个不可能的值,用来判断头结点有没有创建
        head->next = NULL;

        for(int i = 0; i < 10; ++i)
                ListAppend(head, i);

        ListPrint(head);
        ListFree(head);
        printf("head: 0x%.8X\n", (unsigned int)head);

        return 0;
}

0 1 2 3 4 5 6 7 8 9
head: 0x031161E0
请按任意键继续. . .




NODE **head 的头结点存放数据
#include<stdio.h>
#include<stdlib.h>

typedef struct NODE_tag
{
        int data;
        struct NODE_tag *next;
} NODE;

void ListAppend(NODE **head, int data)
{
        NODE *node = malloc(sizeof(NODE));
        node->data = data;
        node->next = NULL;

        if(*head == NULL)
        {
                *head = node;
                return;
        }

        NODE *p = *head;
        while(p->next != NULL)
                p = p->next;

        p->next = node;
}

//void ListPrint(NODE **head)
//{
//        NODE *p = *head;
//
//        while(p != NULL)
//        {
//                printf("%d ", p->data);
//                p = p->next;
//        }
//        putchar('\n');
//}

void ListPrint(NODE *head)
{
        NODE *p = head;

        while(p != NULL)
        {
                printf("%d ", p->data);
                p = p->next;
        }
        putchar('\n');
}

void ListFree(NODE **head)
{
        NODE *p = *head;
        NODE *temp;

        while(p != NULL)
        {
                temp = p;
                p = p->next;
                free(temp);
        }

        *head = NULL;
}

int main(void)
{
        NODE *head = NULL;

        for(int i = 0; i < 10; ++i)
                ListAppend(&head, i);

        ListPrint(head);
        ListFree(&head);
        printf("head: 0x%.8X\n", (unsigned int)head);

        return 0;
}

0 1 2 3 4 5 6 7 8 9
head: 0x00000000
请按任意键继续. . .


但这并不是说 NODE **head 的头结点就不能 不存放数据 ^_^
#include<stdio.h>
#include<stdlib.h>

typedef struct NODE_tag
{
        int data;
        struct NODE_tag *next;
} NODE;

void ListAppend(NODE **head, int data)
{
        if(*head == NULL)
        {
                *head = malloc(sizeof(NODE));
                (*head)->next = NULL;
                return;
        }

        NODE *node = malloc(sizeof(NODE));
        node->data = data;
        node->next = NULL;


        NODE *p = *head;
        while(p->next != NULL)
                p = p->next;

        p->next = node;
}

//void ListPrint(NODE **head)
//{
//        NODE *p = (*head)->next;
//
//        while(p != NULL)
//        {
//                printf("%d ", p->data);
//                p = p->next;
//        }
//        putchar('\n');
//}

void ListPrint(NODE *head)
{
        NODE *p = head->next;

        while(p != NULL)
        {
                printf("%d ", p->data);
                p = p->next;
        }
        putchar('\n');
}

void ListFree(NODE **head)
{
        NODE *p = *head;
        NODE *temp;

        while(p != NULL)
        {
                temp = p;
                p = p->next;
                free(temp);
        }

        *head = NULL;
}

int main(void)
{
        NODE *head = NULL;

        for(int i = 0; i < 10; ++i)
                ListAppend(&head, i);

        ListPrint(head);
        ListFree(&head);
        printf("head: 0x%.8X\n", (unsigned int)head);

        return 0;
}

1 2 3 4 5 6 7 8 9
head: 0x00000000
请按任意键继续. . .



使用二级指针可以修改main函数的head变量,还记得swap函数吧
#include<stdio.h>

void SwapInt(int *x, int *y)
{
        int temp = *x;
        *x = *y;
        *y = temp;
}

void SwapPointer(int **pa, int **pb)
{
        int *temp = *pa;
        *pa = *pb;
        *pb = temp;
}

int main(void)
{
        int x = 100, y = 0;
        SwapInt(&x, &y);
        printf("x: %d y: %d\n", x, y);

        int a = 123, b = 456;
        int *pa = &a, *pb = &b;
        SwapPointer(&pa, &pb);
        printf("pa: %d pb: %d\n", *pa, *pb);

        return 0;
}

x: 0 y: 100
pa: 456 pb: 123
请按任意键继续. . .

还有就是 ListPrint函数
因为是输出这个链表,所以使用 NODE **head 和 NODE *head 都可以
就像
#include<stdio.h>

void PrintInt(int x)
{
        printf("%d\n", x);
}

void PrintPointer(int *x)
{
        printf("%d\n", *x);
}

int main(void)
{
        int x = 100;
        PrintInt(x);
        PrintPointer(&x);

        return 0;
}

100
100
请按任意键继续. . .



至于怎么用,这好像也属于一种习惯问题
就像
#include<stdio.h>

int main(void)
{
        printf("hello world!\n");
        return 0;
}


#include<stdio.h>

int main(void) {
        printf("hello world!\n");
        return 0;
}

人造人 发表于 2018-2-22 20:33:51

以上纯属个人见解,不知道对不对
^_^
页: [1]
查看完整版本: 链表的两种free释放方法,一种是学来的一种是自己更改的还请高手指点