哈夫曼樹的構建(C語言)

哈夫曼樹的構建(C語言)

算法思路node

主要包括兩部分算法,一個是在數組中找到權值最小、且無父結點兩個結點位置,由於只有無父結點才能繼續組成樹; 另外一個就是根據這兩個結點來修改相關結點值。 算法

  1. 結構定義和頭文件數組

     
     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;

     

  2. 在數組中找到目前權值最小的兩個結點 因爲哈夫曼樹規定結點左子樹權值小於右子樹,因此我這裏把權值較小的那個結點位置賦給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  }

     

  3. 構建哈夫曼樹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  }

     

  4. 主函數及具體實例input

    1  int main() {
    2 3      createHuffmanTree();
    4      return 0;
    5  }

     

自我總結

寫這部分時候動態數組分配和使用那裏耗了點時間,主要緣由仍是不太熟以及vs的操做太迷了。通過此次訓練又加深了一點理解,vs的調試也逐漸可以熟練使用了,仍是挺開心的。

相關文章
相關標籤/搜索