数据结构-哈夫曼树

经过两天,不断的调试,不断的改bug,终于按照自己的思想把哈夫曼树的建立写出来了,说实话有点辛苦,但是感觉还不错,感觉挺有成就感的,在代码过程中发现了不少的问题,比如不知为何传递过去的是指针,是地址,但是他在主函数的值不会改变,需要使用返回值来改变主函数的值,还有使用递归无法直接传递最后一轮的值给主函数等等一系列问题。

附代码:

  1 #include"stdio.h"
  2 #include"stdlib.h"
  3 //定义哈夫曼节点类型
  4 typedef struct node{
  5     int weight; //权值
  6     struct node *left;  //左孩子
  7     struct node *right;  //右孩子
  8     struct node *next;  //下一个节点
  9 }Huffman;
 10 //初始化哈夫曼
 11 int length = 0;
 12 Huffman* creatHuffman()
 13 {
 14     int n;
 15     Huffman *h;
 16     Huffman *p;
 17     Huffman *q;
 18     h = q = (Huffman*)malloc(sizeof(Huffman));
 19     printf("请输入您需要几个节点:");
 20     scanf("%d",&n);
 21     if(n <= 0 )
 22     {
 23         printf("您输入的数值有错误!");
 24         return NULL;
 25     }
 26     else
 27     {
 28         for( int i = 0; i < n; i++)
 29         {
 30             p = (Huffman*)malloc(sizeof(Huffman));
 31             printf("请输入第%d个节点的值:",i+1);
 32             scanf("%d",&p->weight);
 33             p->left = NULL;
 34             p->right = NULL;
 35             q->next = p;
 36             q = p;
 37         }
 38         p->next = NULL;
 39         //返回h的下一个节点,h是哈夫曼节点链表的头结点,这里直接返回有值的节点就可以了;
 40         return h->next;
 41     }
 42 }
 43 //删除节点
 44 Huffman *delNode(Huffman *h, int index)
 45 {
 46     Huffman *p = h;
 47     Huffman *q;
 48     if(index == 1)
 49     {
 50         h = h->next;
 51         length--;
 52         return h;
 53     }
 54     if(index == length)
 55     {
 56         for(int i = 1; i < index - 1; i++)  //移动到要删除的节点的前一个
 57         {
 58             p = p->next;
 59         }
 60         p->next = NULL; //因为要删除的节点是链表中的最后一个,最后一个节点的next为NULL,删除后就由最后一个节点的前一个节点为结束
 61         length--;
 62         return h;
 63     }
 64     for(int i = 1; i < index -1; i++)  //移动到要删除的节点的前一个
 65     {
 66         p = p->next;
 67     }
 68     q = p;  //将q指向p的前一个节点
 69     p = p->next;    //p移动到了要删除的节点
 70     q->next = p->next;  //链表中该元素消除
 71     length--;
 72     return h;
 73 }
 74 //合并两个节点,成为一个新的节点,并将两个节点作为该节点的左右孩子
 75 Huffman *mergeNode(Huffman *h ,Huffman *min1, Huffman *min2)
 76 {
 77     Huffman *newNode =(Huffman*)malloc(sizeof(Huffman));    //建立新的节点
 78     Huffman *p = h;
 79     newNode->weight = min1->weight + min2->weight;  //合并两个节点的权值赋值给合并的节点
 80     newNode->left = min1;
 81     newNode->right = min2;
 82     if(h ==NULL)
 83     {
 84         h = newNode;
 85     }
 86     else
 87     {
 88         while(p->next != NULL)
 89         {
 90             p = p->next;
 91         }
 92         p->next = newNode;  //将新节点放入节点链表的最后一个,以便于后面比较大小
 93     }
 94     newNode->next = NULL;
 95     length++;
 96     return h;
 97 }
 98 //比较大小,找出两个最小的值的节点
 99 Huffman *compareNode(Huffman *h)
100 {
101     //退出递归条件,当这个节点链表只剩最后一个节点(根节点)时退出
102 //    if(h->next == NULL)
103 //    {
104 //        return;
105 //    }
106     int index;  //标记最小值的位置
107     int count;  //标记当前在第几个节点
108     Huffman *min1,*min2;
109     Huffman *p;
110     while(h->next != NULL)
111     {
112         index = 1;
113         count = 1;
114         min1 = h;
115         p = h->next;
116         //寻找最小值
117         while(p != NULL)
118         {
119             count++;
120             if(p->weight < min1->weight)
121             {
122                 min1 = p;
123                 index = count;
124             }
125             p = p->next;
126         }
127         h = delNode(h, index);  //调用删除节点函数删除链表中的该节点
128         count = 1;  //节点重头开始
129         index = 1;  //最小值下标位置置1
130         p = h->next;
131         min2 = h;
132         //寻找第二个最小值
133         while(p != NULL)
134         {
135             count++;
136             if(p->weight < min2->weight)
137             {
138                 min2 = p;
139                 index = count;
140             }
141             p = p->next;
142         }
143         h = delNode(h, index);  //调用删除节点函数删除链表中的该节点
144         h = mergeNode(h , min1, min2);//调用合并节点函数构造一个新的节点
145 
146     }
147     return h;
148    //    h = compareNode(h); //递归调用自己
149 }
150 //计算总节点个数
151 void getLength(Huffman *h)
152 {
153     Huffman *p = h;
154     while(p != NULL)
155     {
156         length++;
157         p = p->next;
158     }
159 }
160 //输出二叉树
161 void printTree(Huffman *h)
162 {
163     if(h != NULL)
164     {
165         printf("%d  ",h->weight);
166         printTree(h->left);
167         printTree(h->right);
168     }
169     }
170 main()
171 {
172     Huffman *h;
173     Huffman *p;
174     h = creatHuffman();
175     getLength(h);
176     printf("总长度为:%d \n",length);
177     h = compareNode(h);
178     printTree(h);
179 }

转载于:https://www.cnblogs.com/sucker/p/11020177.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哈夫曼树是一种最优二叉树,它的构造算法如下:首先将n个结点作为n棵仅含有一个根结点的二叉树,构成一个森林F。然后,生成一个新结点,并从F中找出根结点权值最小的两棵树作为它的左右子树,新结点的权值为两棵子树根结点的权值之和。接着,从F中删除这两个树,并将新生成的树加入到F中。重复以上步骤,直到F中只有一棵树为止。 哈夫曼树具有以下性质: 1)每个初始结点都会成为叶节点,双支结点都为新生成的结点 2)权值越大离根结点越近,反之权值越小离根结点越远 3)哈夫曼树中没有结点的度为1 4)n个叶子结点的哈夫曼树的结点总数为2n-1,其中度为2的结点数为n-1。 哈夫曼树的应用之一是解决编码问题。在编码中,我们使用二进制来表示字符,其中固定长度编码和前缀编码是两种常见的编码方式。前缀编码要求没有一个编码是另一个编码的前缀,而哈夫曼树构造的编码正是满足前缀编码的要求。 所以,哈夫曼树数据结构考研中是一个重要的概念,它可以用于构造最优二叉树和解决编码问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [数据结构考研笔记(十六) ——哈夫曼树、编码应用](https://blog.csdn.net/sf9090/article/details/109154652)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值