关于malloc函数和free函数的使用中出现的问题

// rogram received signal SIGABRT, Aborted.
// __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:49
// 49 ../sysdeps/unix/sysv/linux/raise.c: 没有那个文件或目录.
这是为啥

image.png
当在主函数中出现两个层序遍历时就出现问题
但是当把int pop(Queue *pqueue)中的free()函数注释掉就可以。
代码:
主函数:

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

int main (void)
{
    Tree_Node *root=(Tree_Node *)malloc(sizeof(Tree_Node));

    init(root,23);


    insert(root,15);
    insert(root,25);
    insert(root,24);
    insert(root,27);
    insert(root,7);
    insert(root,16);
    insert(root,3);
    insert(root,9);
    insert(root,8);

    printf("中序遍历:\n");
    inorder(root);

    // 层序遍历
    putchar('\n');
    level_order(root);
    // level_order(root);
    // putchar('\n');
    // level_order(root);
    // reverse(root);
    // printf("翻转后的中序遍历:\n");
    // inorder(root);
    // putchar('\n');
    // putchar('\n');

    putchar('\n');
    printf("该树的深度为:%d\n",treedepth(root));

    printf("该树中的最小值为:\n");
    dispaly(findmin(root));
    putchar('\n');
    
    printf("该树中的最大值为:\n");
    dispaly(findmax(root));
    putchar('\n');


    dispaly(find(root,23));
    putchar('\n');


    root=Delete(root,23);
    printf("中序遍历:\n");
    inorder(root);
    putchar('\n');

    level_order(root);
    putchar('\n');

    root=Delete(root,9);
    printf("中序遍历:\n");
    inorder(root);
    putchar('\n');
    

    root=Delete(root,3);
    printf("中序遍历:\n");
    inorder(root);
    putchar('\n');
    
    // level_order(root);

    return 0;
}

tree.h:

/*
树的实现
*/

#ifndef _TREE_H
#include <stdbool.h>

typedef int ElementType;

// // 树的定义
// typedef struct tree_node{
//     ElementType data;
//     struct tree_node *firstchild;       // 第一个儿子
//     struct tree_node *nextsibling;      // 下一个(第一个)兄弟
// }Tree_NOde;

// 二叉树的定义
typedef struct tree_node{
    ElementType data;
    struct tree_node *leftchild;
    struct tree_node *rightchild;
    // struct tree_node *parent;    // 双亲结点
}Tree_Node;

// 层序遍历所使用的队列
typedef struct queue{
    struct queue *prev;
    struct queue *next;
    int data;
    // int size;
}Node;

typedef struct sq{
    Node *head;
    int size;
}Queue;

// 初始化队列
void init_queue(Queue *pqueue);

// 向队列中插入一个元素
void push(Queue *pqueue, int value);

// 从队列中取出一个数据
int pop(Queue *pqueue);

// 清空队列
void mkempty_queue(Queue *pqueue);



// 初始化树
void init(Tree_Node *root, ElementType e);

// 判断该节点是否是树叶
bool is_leaf(Tree_Node *pnode);

// 清空树
void mkempty(Tree_Node *root);

// 查找一个特定元素所在的节点
Tree_Node *find(Tree_Node *root, ElementType e);

// 查找二叉树中的最小值
Tree_Node *findmin(Tree_Node *root);

// 查找二叉树中的最大值
Tree_Node *findmax(Tree_Node *root);

// 插入一个元素,并返回二叉树的根节点
Tree_Node *insert(Tree_Node *root, ElementType e);

// 删除一个元素所在的节点,并返回根节点
Tree_Node *Delete(Tree_Node *root, ElementType e);

// 二叉树的翻转
Tree_Node *reverse(Tree_Node *root);


// 中序遍历二叉树
void inorder(Tree_Node *root);

// 读取该节点的信息
void dispaly(Tree_Node *pnode);

// 先序遍历
void preorder(Tree_Node *root);

// 后续遍历
void postorder(Tree_Node *root);

// 求二叉树的高度
int treedepth(Tree_Node *root);

// 层序遍历
void level_order(Tree_Node *root);


// 得到某个节点的信息
int get_data(Tree_Node *pnode);

// 交换两个节点
void exchange(Tree_Node *p);

#endif

tree.c:

/*
tree.h中的函数实现
*/

#include "tree.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void init(Tree_Node *root, ElementType e)
{
    memcpy(&root->data,&e,sizeof(ElementType));

    root->leftchild=NULL;
    root->rightchild=NULL;
}

bool is_leaf(Tree_Node *pnode)
{
    if(pnode->rightchild==NULL && pnode->leftchild==NULL)
        return true;
    else
        return false;
}

void mkempty(Tree_Node *root)
{
    if(root==NULL)
        return;
    mkempty(root->leftchild);
    mkempty(root->rightchild);
    free(root);
}

Tree_Node *find(Tree_Node *root, ElementType e)
{
    if(root==NULL)
        return NULL;
    if(e>root->data)
        return find(root->rightchild,e);
    else if(e<root->data)
        return find(root->leftchild,e);
    else
        return root;
}

Tree_Node *findmin(Tree_Node *root)
{
    if(root==NULL)
        return NULL;
    if(root->leftchild==NULL)
        return root;
    else
        return findmin(root->leftchild);
    // return root;
}

Tree_Node *findmax(Tree_Node *root)
{
    if(root==NULL)
        return NULL;
    if(root->rightchild==NULL)
        return root;
    else
        return findmax(root->rightchild);
}

Tree_Node *insert(Tree_Node *root, ElementType e)
{
    if(root==NULL)          // 找到位置,进行插入
    {
        root=(Tree_Node *)malloc(sizeof(Tree_Node));
        if(root==NULL)
        {
            printf("内存分配失败\n");
            return NULL;
        }
        memcpy(&root->data,&e,sizeof(ElementType));
        // printf("插入:%d\t",root->data);
        root->leftchild=NULL;
        root->rightchild=NULL;
    }
    else if(e>root->data)
        root->rightchild=insert(root->rightchild,e);
    else if(e<root->data)
        root->leftchild=insert(root->leftchild,e);
    
    // printf("aaa\n")  ;
    // inorder(root);
    // printf("\n");
    return root;
}


Tree_Node *Delete(Tree_Node *root, ElementType e)
{
    if(root==NULL)
        return NULL;
    else
    {
        if(e>root->data)
            root->rightchild=Delete(root->rightchild,e);
        else if(e<root->data)
            root->leftchild=Delete(root->leftchild,e);
        else
        {
            if(root->leftchild!=NULL && root->rightchild!=NULL)     // 有两棵子树
            {
                Tree_Node *temp=findmin(root->rightchild);
                memcpy(&root->data,&temp->data,sizeof(ElementType));

                root->rightchild=Delete(root->rightchild,root->data);       // 删除代替的那个节点
            }
            else            // 只有一棵子树或者没有子树
            {
                Tree_Node *t=root;
                if(t->rightchild==NULL)
                    root=root->leftchild;       // 当t为叶子节点时,确保它的父节点指向该节点的那个指针为NULL,
                else if(t->leftchild==NULL)
                    root=root->rightchild;
                free(t);
            }
        }
    }
    return root;
}

void dispaly(Tree_Node *pnode)
{
    if(pnode==NULL)
        return ;
    else
        printf("%d,",pnode->data);
}

void inorder(Tree_Node *root)
{
    if(root==NULL)
        return ;
    inorder(root->leftchild);
    dispaly(root);
    inorder(root->rightchild);
}


void preorder(Tree_Node *root)
{
    if(root==NULL)
        return ;
    dispaly(root);
    preorder(root->leftchild);
    preorder(root->rightchild);
}

void postorder(Tree_Node *root)
{
    if(root==NULL)  return ;
    postorder(root->leftchild);
    postorder(root->rightchild);
    dispaly(root);
}

int treedepth(Tree_Node *root)
{
    if(root==NULL)
        return -1;
    int llenth=treedepth(root->leftchild);
    int rlenth=treedepth(root->rightchild);

    return llenth>rlenth?llenth+1:rlenth+1;
}


void init_queue(Queue *pqueue)
{
    pqueue->head=(Node *)malloc(sizeof(Node));
    pqueue->head->next=pqueue->head->prev=NULL;
    pqueue->size=0;
}

void push(Queue *pqueue, int value)
{
    Node *head=pqueue->head;
    while(head->next!=NULL)
        head=head->next;
    Node *n=(Node *)malloc(sizeof(Node));
    n->prev=head;
    head->next=n;
    n->next=NULL;
    n->data=value;
    pqueue->size++;

}

int pop(Queue *pqueue)
{
    Node *n=pqueue->head->next;     // 第一个数据节点
    if(n!=NULL)
    {
        pqueue->size--;
        int result=n->data;
        pqueue->head->next=n->next;
        if(n->next!=NULL)
        {
            n->next->prev=pqueue->head;
        }
        free(n);        // 这里存在问题,将这里注释后就能正常运行多次层序遍历
        n->next=NULL;
        n->prev=NULL;
        return result;
    }
    else
    {
        printf("队列为空\n");
        exit(1);
    }
}

void mkempty_queue(Queue *pqueue)
{
    Node *first=pqueue->head->next;
    while(first!=NULL)
    {
        pqueue->size--;
        Node *n=first->next;
        free(first);
        first->next=first->prev=NULL;
    }
}

void level_order(Tree_Node *root)
{
    printf("层序遍历:\n");
    Queue *pq=(Queue *)calloc(1,sizeof(Queue));
    init_queue(pq);

    int a=get_data(root);
    push(pq,a);
    while(pq->size!=0)
    {
        int t=pop(pq);
        printf("%d ",t);
        Tree_Node *temp=find(root,t);
        Tree_Node *l_child=temp->leftchild;
        Tree_Node *r_child=temp->rightchild;
        if(l_child!=NULL)
        {
            int l=get_data(l_child);
            push(pq,l);
        }
        if(r_child!=NULL)
        {
            int r=get_data(r_child);
            push(pq,r);
        }
        // int r
    }
    mkempty_queue(pq);
    free(pq);
    putchar('\n');
}

// int get_size(Tree_Node *root)
// {
//     if(root==NULL)
//         return 0;
    
// }

int get_data(Tree_Node *pnode)
{
    if(pnode!=NULL)
        return pnode->data;
    else
    {
        printf("该节点空\n");
        exit(1);
    }
}


Tree_Node *reverse(Tree_Node *root)
{
    if(root==NULL)
        return NULL;
    Tree_Node *temp=root->leftchild;
    root->leftchild=reverse(root->rightchild);       // 翻转左子树
    root->rightchild=reverse(temp);         // 翻转右子树
    // exchange(root);                 // 交换root的左右子节点
    return root;                    // 返回root;
}


void exchange(Tree_Node *p)
{
    if(p==NULL)
        return ;
    Tree_Node *temp=p->leftchild;
    p->leftchild=p->rightchild;
    p->rightchild=temp;
}
阅读 1.7k
1 个回答
free(n);
n->next=NULL; // n的内存已經被釋放,不能再對其操作賦值
n->prev=NULL; // n的内存已經被釋放,不能再對其操作賦值
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进