鱼C论坛

 找回密码
 立即注册
查看: 970|回复: 2

[已解决]此代码创建的哈夫曼树正确吗?

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

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

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

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 WPL(HuffmanTree HF,int depth);
  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.                 printf("合并前:\n");

  79.                 HuffmanTree A = DeleteHeap(H);
  80.                 HuffmanTree B = DeleteHeap(H);
  81.                 HuffmanTree Troot = (HuffmanTree)malloc(sizeof(struct TreeNode));
  82.                 Troot->Weight = A->Weight+B->Weight;
  83.                 Troot->Left = A;
  84.                 Troot->Right = B;
  85.                 InsertHeap(H,Troot);
  86.                 printf("合并后:\n");
  87.                 P(H);

  88.         }
  89.         return H->Data[1];
  90. }

  91. void WPL(HuffmanTree HF,int depth)
  92. {
  93.         // 找到二叉树的叶子节点并打印深度
  94.     if (HF == NULL) {
  95.         return;
  96.     }

  97.     if (HF->Left == NULL && HF->Right == NULL) {
  98.         printf("%d\n", HF->Weight * depth);
  99.     }

  100.     WPL(HF->Left, depth + 1);
  101.     WPL(HF->Right, depth + 1);


  102. }

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

  130.   return 0;
  131. }
复制代码


此代码创建的哈夫曼树正确吗?好像创造出来的不是正确的,哈夫曼树WPL值也不对。。。求解答哪里错误了。
最佳答案
2023-7-18 16:22:52
这段代码在创建哈夫曼树时没有任何错误。问题在于  WPL  函数,它打印了每个叶子节点的权值与深度的乘积,而没有实现真正的权值路径长度 (Weighted Path Length, WPL)。WPL 应该是所有叶子节点的权值与深度的乘积之和。

以下是修改后的  WPL  函数:
  1. int WPL(HuffmanTree HF, int depth)
  2. {
  3.     if (HF == NULL) {
  4.         return 0;
  5.     }
  6.     if (HF->Left == NULL && HF->Right == NULL) {
  7.         return HF->Weight * depth;
  8.     }
  9.     return WPL(HF->Left, depth + 1) + WPL(HF->Right, depth + 1);
  10. }
复制代码

然后,在  main  函数中,用下面的语句替换  WPL(HF,1); ,以打印总的 WPL 值:
  1. printf("%d\n", WPL(HF, 1));
复制代码

此外,对于输入部分,我注意到你用  scanf("%c %d", &a, &Weight);  获取了一个字符,但这个字符并没有在后续的操作中使用。如果这个字符的输入是不必要的,那么你可以直接输入权值,然后跟一个换行符。如果这个字符是重要的,那么你需要在  TreeNode  结构中添加一个字符字段来存储这个字符。

希望以上的建议可以帮助你改善你的代码。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-7-18 16:22:38 | 显示全部楼层
本帖最后由 陶远航 于 2023-7-18 16:37 编辑

根据你提供的代码,似乎存在一些问题导致创建的哈夫曼树和WPL值不正确。下面是我发现的几个可能的错误:

1. 在函数MinHeap CreateHeap(int MaxSize)中,你为最小堆的数据数组分配内存时,只给每个节点分配了sizeof(struct TreeNode)的内存,但实际上每个节点应该是指向struct TreeNode类型的指针,所以分配内存时应该使用sizeof(struct TreeNode*)

2. 在函数InsertHeap(MinHeap H, HuffmanTree T)中的循环条件判断部分存在错误。应该是H->Data[i/2]->Weight > T->Weight而不是H->Data[i/2]->Weight < T->Weight。这样才能保证最小堆的性质。

3. 在函数DeleteHeap(MinHeap H)中,在交换节点位置时,应该使用H->Data = H->Data[j][i]而不是H->Data = H->Data[j+1][i]。

4. 在函数CreateHuffman(MinHeap H)中的循环条件判断部分存在错误。应该是j != H->Size && (H->Data[j]->Weight < H->Data[j+1]->Weight)而不是j != H->Size && (H->Data[j]->Weight > H->Data[j+1]->Weight)

请根据以上建议修改代码,并重新运行以创建正确的哈夫曼树。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-18 16:22:52 | 显示全部楼层    本楼为最佳答案   
这段代码在创建哈夫曼树时没有任何错误。问题在于  WPL  函数,它打印了每个叶子节点的权值与深度的乘积,而没有实现真正的权值路径长度 (Weighted Path Length, WPL)。WPL 应该是所有叶子节点的权值与深度的乘积之和。

以下是修改后的  WPL  函数:
  1. int WPL(HuffmanTree HF, int depth)
  2. {
  3.     if (HF == NULL) {
  4.         return 0;
  5.     }
  6.     if (HF->Left == NULL && HF->Right == NULL) {
  7.         return HF->Weight * depth;
  8.     }
  9.     return WPL(HF->Left, depth + 1) + WPL(HF->Right, depth + 1);
  10. }
复制代码

然后,在  main  函数中,用下面的语句替换  WPL(HF,1); ,以打印总的 WPL 值:
  1. printf("%d\n", WPL(HF, 1));
复制代码

此外,对于输入部分,我注意到你用  scanf("%c %d", &a, &Weight);  获取了一个字符,但这个字符并没有在后续的操作中使用。如果这个字符的输入是不必要的,那么你可以直接输入权值,然后跟一个换行符。如果这个字符是重要的,那么你需要在  TreeNode  结构中添加一个字符字段来存储这个字符。

希望以上的建议可以帮助你改善你的代码。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-10 15:26

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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