鱼C论坛

 找回密码
 立即注册
查看: 1100|回复: 4

[已解决]关于给结构体内数组分配内存空间的问题求解!

[复制链接]
发表于 2023-7-18 12:59:02 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
代码如下:
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. int MinData = -1;
  4. typedef struct TreeNode *HuffmanTree;
  5. typedef struct Heap *MinHeap;
  6. typedef int ElenmentType ;
  7. struct TreeNode
  8. {
  9.     ElenmentType Weight;//权值
  10.     HuffmanTree Left;
  11.     HuffmanTree Right;
  12. };
  13. struct Heap
  14. {
  15.     HuffmanTree *Data;
  16.     ElenmentType Size;
  17.     ElenmentType Capacity;
  18. };

  19. MinHeap CreateHeap(int MaxSize);   // 建堆
  20. void InsertHeap(MinHeap H,HuffmanTree T);
  21. HuffmanTree DeleteHeap(MinHeap H);
  22. HuffmanTree CreateHuffman(MinHeap H);
  23. void Print(HuffmanTree HF);
  24. void P(MinHeap H);

  25. MinHeap CreateHeap(int MaxSize)
  26. {
  27.     MinHeap H = malloc(sizeof(struct Heap));
  28.     H->Data = malloc((MaxSize + 1)* sizeof(struct TreeNode));
  29.     H->Size = 0;
  30.     H->Capacity = MaxSize;
  31.     //H->Data[0] = malloc(sizeof(struct TreeNode));
  32.     H->Data[0]->Weight = MinData;
  33.     int i;
  34.     for(i = 1;i <= MaxSize;i++)
  35.             H->Data[i] = NULL;

  36.     return H;
  37. }

  38. void InsertHeap(MinHeap H,HuffmanTree T)
  39. {
  40.         if(H->Size == H->Capacity)
  41.         {
  42.                 printf("最小堆满");
  43.                 return;
  44.         }
  45.         int i = ++H->Size;
  46.         for(;H->Data[i/2]->Weight > T->Weight;i/=2)
  47.                 H->Data[i] = H->Data[i/2];
  48.         H->Data[i] = T;
  49. }

  50. HuffmanTree DeleteHeap(MinHeap H)
  51. {
  52.         if(H->Size == 0)
  53.         {
  54.                 printf("最小堆空");
  55.                 return;
  56.         }
  57.         HuffmanTree MinData = H->Data[1];
  58.         HuffmanTree temp = H->Data[H->Size--];
  59.         int i,j;
  60.         for(i = 1;i*2 <= H->Size;i = j)
  61.         {
  62.                 j = i*2;
  63.                 if((j != H->Size) && (H->Data[j]->Weight > H->Data[j+1]->Weight))
  64.                 j++;
  65.                 if(temp->Weight <= H->Data[j]->Weight)break;
  66.                 else
  67.                         H->Data[i] = H->Data[j];
  68.         }
  69.         H->Data[i] = temp;
  70.        
  71.         P(H);
  72.         return MinData;
  73. }
  74. HuffmanTree CreateHuffman(MinHeap H)
  75. {
  76.         while(H->Size > 1)
  77.         {
  78.                 HuffmanTree A = DeleteHeap(H);
  79.                 HuffmanTree B = DeleteHeap(H);
  80.                 HuffmanTree Troot = (HuffmanTree)malloc(sizeof(struct TreeNode));
  81.                 Troot->Weight = A->Weight+B->Weight;
  82.                 Troot->Left = A;
  83.                 Troot->Right = B;
  84.                 InsertHeap(H,Troot);
  85.         }
  86.         return H->Data[1];
  87. }

  88. void Print(HuffmanTree HF)
  89. {
  90.         if(HF)
  91.         {
  92.                 printf("%d ",HF->Weight);
  93.                 Print(HF->Left);
  94.                 Print(HF->Right);
  95.         }
  96.                         printf("\n");
  97. }

  98. void P(MinHeap H)
  99. {
  100.         int i = 1;
  101.         if(H->Size > 0)
  102.                 for(;i <= H->Size;i++)
  103.                         printf("%d ",H->Data[i]->Weight);
  104.                 printf("\n");
  105. }
  106. int main()
  107. {
  108.        
  109.         int i;
  110.         scanf("%d\n",&i);
  111.         MinHeap H = CreateHeap(i);
  112.         while(i--)
  113.         {
  114.                 char a;
  115.                 ElenmentType Weight;
  116.                 scanf("%c %d",&a,&Weight);
  117.                 HuffmanTree T  = malloc(sizeof(struct TreeNode));
  118.                 T->Left = T->Right = NULL;
  119.                 T->Weight = Weight;
  120.                 getchar();
  121.                 InsertHeap(H,T);
  122.         }
  123.         HuffmanTree HF = CreateHuffman(H);
  124.         Print(HF);

  125.   return 0;
  126. }
复制代码


在CreateHeap函数里,首先生成了一个H的最小堆指针
MinHeap H = malloc(sizeof(struct Heap));
然后为其H堆里的数组成员Data分配内存空间
    H->Data = malloc((MaxSize + 1)* sizeof(struct TreeNode));
分配了之后,访问H->Data[0]居然是无效空间
必须加一句我注释掉的 H->Data[0] = malloc(sizeof(struct TreeNode));
e6980b38685656dbd2e803502b7e327.png
蓝色这行代码就是出错的地方,我分配了内存空间为什么还是无效访问?
最佳答案
2023-7-18 12:59:34
在你的代码中,你首先为 MinHeap H 结构体变量的 Data 成员,也就是一个指向 HuffmanTree 的指针数组,分配了内存空间。然后你尝试访问 H->Data[0] 并尝试修改其 Weight 属性。然而,你只为 Data 指针数组分配了内存空间,这意味着你已经有了一个可以存储 HuffmanTree 指针的内存空间,但你并没有实际为这些指针所指向的 HuffmanTree 节点分配内存。也就是说,你的数组可以存储指向 HuffmanTree 的指针,但是这些指针本身现在指向的是未分配的内存。

在你尝试执行 H->Data[0]->Weight = MinData; 这行代码时, H->Data[0] 指向的内存区域还没有被分配,所以你遇到了无效访问。

因此,你需要对每个 HuffmanTree 结构体实例分配内存,这就是为什么你需要使用 H->Data[0] = malloc(sizeof(struct TreeNode)); 这行代码的原因。这行代码会为 H->Data[0] 指针分配一个 struct TreeNode 类型的内存空间,所以你可以在这个内存区域上进行操作,例如修改其 Weight 属性。这样,你就不会遇到无效访问的问题了。

以下是你可能需要修改的部分:
  1. MinHeap CreateHeap(int MaxSize)
  2. {
  3.     MinHeap H = malloc(sizeof(struct Heap));
  4.     H->Data = malloc((MaxSize + 1) * sizeof(struct TreeNode *));
  5.     H->Size = 0;
  6.     H->Capacity = MaxSize;
  7.     H->Data[0] = malloc(sizeof(struct TreeNode));
  8.     H->Data[0]->Weight = MinData;
  9.     int i;
  10.     for(i = 1; i <= MaxSize; i++)
  11.         H->Data[ i] = NULL;
  12.     return H;
  13. }
复制代码

在这段代码中,我将 H->Data 的内存分配改为 malloc((MaxSize + 1) * sizeof(struct TreeNode *)); ,因为 Data 是一个 HuffmanTree (也就是 struct TreeNode * )类型的数组。然后,我为 H->Data[0] 分配了一个新的 struct TreeNode 类型的内存空间。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-7-18 12:59:14 | 显示全部楼层
在给结构体内的数组分配内存空间时,你出现了无效访问的问题。这是因为你分配了H->Data的内存空间,但没有为H->Data[0]分配内存空间。

解决这个问题的方法是,你可以在分配H->Data的内存后,再单独为H->Data[0]分配内存空间,例如:
  1. H->Data = malloc((MaxSize + 1)* sizeof(struct TreeNode));
  2. H->Data[0] = malloc(sizeof(struct TreeNode));
复制代码

这样,你就为H->Data[0]分配了内存空间,之后就可以正常使用了。希望能帮到你!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-18 12:59:34 | 显示全部楼层    本楼为最佳答案   
在你的代码中,你首先为 MinHeap H 结构体变量的 Data 成员,也就是一个指向 HuffmanTree 的指针数组,分配了内存空间。然后你尝试访问 H->Data[0] 并尝试修改其 Weight 属性。然而,你只为 Data 指针数组分配了内存空间,这意味着你已经有了一个可以存储 HuffmanTree 指针的内存空间,但你并没有实际为这些指针所指向的 HuffmanTree 节点分配内存。也就是说,你的数组可以存储指向 HuffmanTree 的指针,但是这些指针本身现在指向的是未分配的内存。

在你尝试执行 H->Data[0]->Weight = MinData; 这行代码时, H->Data[0] 指向的内存区域还没有被分配,所以你遇到了无效访问。

因此,你需要对每个 HuffmanTree 结构体实例分配内存,这就是为什么你需要使用 H->Data[0] = malloc(sizeof(struct TreeNode)); 这行代码的原因。这行代码会为 H->Data[0] 指针分配一个 struct TreeNode 类型的内存空间,所以你可以在这个内存区域上进行操作,例如修改其 Weight 属性。这样,你就不会遇到无效访问的问题了。

以下是你可能需要修改的部分:
  1. MinHeap CreateHeap(int MaxSize)
  2. {
  3.     MinHeap H = malloc(sizeof(struct Heap));
  4.     H->Data = malloc((MaxSize + 1) * sizeof(struct TreeNode *));
  5.     H->Size = 0;
  6.     H->Capacity = MaxSize;
  7.     H->Data[0] = malloc(sizeof(struct TreeNode));
  8.     H->Data[0]->Weight = MinData;
  9.     int i;
  10.     for(i = 1; i <= MaxSize; i++)
  11.         H->Data[ i] = NULL;
  12.     return H;
  13. }
复制代码

在这段代码中,我将 H->Data 的内存分配改为 malloc((MaxSize + 1) * sizeof(struct TreeNode *)); ,因为 Data 是一个 HuffmanTree (也就是 struct TreeNode * )类型的数组。然后,我为 H->Data[0] 分配了一个新的 struct TreeNode 类型的内存空间。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-18 13:50:34 From FishC Mobile | 显示全部楼层
isdkz 发表于 2023-7-18 12:59
在你的代码中,你首先为 MinHeap H 结构体变量的 Data 成员,也就是一个指向 HuffmanTree 的指针数组,分配 ...

谢谢你的回答,你能帮我看一下我构造的这个哈夫曼树是正确的吗?正常分配空间后构造的哈夫曼树WPL值好像不对。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-18 14:39:53 | 显示全部楼层
a905448839 发表于 2023-7-18 13:50
谢谢你的回答,你能帮我看一下我构造的这个哈夫曼树是正确的吗?正常分配空间后构造的哈夫曼树WPL值好像 ...


你在代码中创建了一个 `MinHeap` 堆,并为 `H->Data` 分配了内存空间,这个内存空间的大小是 `(MaxSize + 1) * sizeof(struct TreeNode)`。然而,你需要注意的是 `H->Data` 是一个指针数组,它存储的是 `HuffmanTree` (也是指针)类型的数据。因此,你分配的内存应该是用来存储 `HuffmanTree` 指针的,而不是 `struct TreeNode` 结构体。

当你尝试访问 `H->Data[0]->Weight` 时,事实上你正在试图访问一个 `HuffmanTree` 结构的 `Weight` 成员。但是在这个时候,`H->Data[0]` 还没有被初始化,它指向的是一个未知的内存位置,这就是为什么你会遇到无效访问的问题。

如果你想要初始化 `H->Data[0]`,你确实需要为其分配内存空间。你注释掉的这行代码 `H->Data[0] = malloc(sizeof(struct TreeNode));` 是正确的,它会为 `H->Data[0]` 分配一个新的 `struct TreeNode` 结构体的内存空间,并将 `H->Data[0]` 指向这个新的内存空间。这样你就可以通过 `H->Data[0]` 访问并修改这个 `struct TreeNode` 结构体的成员了。

所以,你的代码应该修改为:

  1. MinHeap CreateHeap(int MaxSize)
  2. {
  3.         MinHeap H = malloc(sizeof(struct Heap));
  4.         H->Data = malloc((MaxSize + 1)* sizeof(struct TreeNode *));
  5.         H->Size = 0;
  6.         H->Capacity = MaxSize;

  7.         H->Data[0] = malloc(sizeof(struct TreeNode));
  8.         H->Data[0]->Weight = MinData;

  9.         int i;
  10.         for(i = 1;i <= MaxSize;i++)
  11.                 H->Data[i] = NULL;

  12.         return H;
  13. }
复制代码

上述代码中,我将 `H->Data = malloc((MaxSize + 1)* sizeof(struct TreeNode));` 修改为 `H->Data = malloc((MaxSize + 1)* sizeof(struct TreeNode *));`,以确保为 `H->Data` 分配的内存空间足够存储 `(MaxSize + 1)` 个 `HuffmanTree` 指针。此外,我取消了 `H->Data[0] = malloc(sizeof(struct TreeNode));` 这行代码的注释,以确保 `H->Data[0]` 能指向一个有效的内存空间。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-11 10:50

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表