算法思路:node
主要包括兩部分算法,一個是在數組中找到權值最小、且無父結點兩個結點位置,由於只有無父結點才能繼續組成樹; 另外一個就是根據這兩個結點來修改相關結點值。 算法
數組
1 #include <stdio.h> 2 #include <malloc.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 #define OVERFLOW -1 7 8 typedef struct { 9 int weight;//結點權值 10 int lchild, rchild, parent;//結點左、右孩子、父結點 11 }HNode,*HTree;
在數組中找到目前權值最小的兩個結點 因爲哈夫曼樹規定結點左子樹權值小於右子樹,因此我這裏把權值較小的那個結點位置賦給p1 函數
這部分我先找到前兩個無父結點的結點位置賦給p1和p2,再繼續遍歷以後的與當前的p1和p2位置的結點權值比較spa
若結點有父結點,直接跳過3d
若結點無父結點,且權值小於p1,則將該位置賦給p1,令p2等於以前的p1調試
若結點無父結點,且權值大於p一、小於p2,則將該位置賦給p2code
1 void selectMin(HTree HT,int length, int* p1, int* p2) {//搜索當前數組中無父結點的權值最小的兩個結點的下標 2 int i = 1;//數組下標從1開始,0不用 3 4 while (HT[i].parent!= 0 && i <= length)//遍歷到第一個無父結點的結點位置 5 i++; 6 *p1 = i; i++; 7 while (HT[i].parent!= 0 && i <= length)//遍歷到第二個無父結點的結點位置 8 i++; 9 *p2 = i; i++; 10 11 if (HT[*p1].weight > HT[*p2].weight) {//令p1始終指向較小權值的結點位置 12 int temp = *p1; 13 *p1 = *p2; 14 *p2 = temp; 15 } 16 17 for (int n = i; n <= length; n++) {//繼續遍歷,比較以後的無父結點的結點權值與p一、p2 18 if (HT[n].parent != 0)//若該結點有父結點,直接跳過 19 continue; 20 else if (HT[n].weight < HT[*p1].weight) {//若該結點權值小於p1,令p1等於n,p2等於p1 21 *p2 = *p1; 22 *p1 = n; 23 } 24 else if (HT[n].weight > HT[*p1].weight&& HT[n].weight < HT[*p2].weight)//若該結點權值大於p1,小於p2,令*p2=n 25 *p2 = n; 26 } 27 28 return; 29 }
構建哈夫曼樹blog
1 void createHuffmanTree() {//構建哈夫曼樹 2 int lnode;//哈夫曼樹葉子結點數 3 printf("input leafnode number:"); 4 scanf_s("%d", &lnode); 5 int length=2*lnode-1;//哈夫曼樹結點數=2*葉子節點數-1 6 7 HTree HT = (HTree)malloc(sizeof(HNode) * (length + 1));//數組下標從1開始,因此分配(length+1)大小空間 8 if (!HT) exit(OVERFLOW); 9 memset(HT, 0, sizeof(HNode) * (length + 1));//將數組內元素都初始化爲0 10 11 HTree p = HT; 12 for (int i = lnode + 1; i <=length; i++) {//把全部非葉子節點的結點權值規定爲無窮大,不然會影響接下來選擇結點最小值 13 (p + i)->weight = 65535; 14 } 15 16 17 printf("input leafnode weight:"); 18 for (int i = 1; i <= lnode; i++) {//輸入葉子結點權值 19 scanf_s("%d", &(p+i)->weight); 20 } 21 22 int p1, p2; 23 for (int i = lnode+1; i <= length; i++) {//從第一個非葉子結點開始遍歷 24 selectMin(p, length, &p1, &p2); 25 (p + i)->lchild = p1;//修改左子樹的值 26 (p + i)->rchild = p2;//修改左子樹的值 27 (p + i)->weight = (p + p1)->weight + (p + p2)->weight;//修改權值 28 (p + p1)->parent = i;//修改左子樹的父結點值 29 (p + p2)->parent = i;//修改右子樹的父結點值 30 } 31 32 for (int i = 1; i <= length; i++) { 33 printf("%3d %3d %3d %3d %3d\n", i, (p + i)->weight, (p + i)->parent, (p + i)->lchild, (p + i)->rchild);//遍歷輸出 34 } 35 36 return; 37 }
主函數及具體實例input
1 int main() { 2 3 createHuffmanTree(); 4 return 0; 5 }
寫這部分時候動態數組分配和使用那裏耗了點時間,主要緣由仍是不太熟以及vs的操做太迷了。通過此次訓練又加深了一點理解,vs的調試也逐漸可以熟練使用了,仍是挺開心的。