資料結構之---C語言實現哈夫曼樹和編碼
阿新 • • 發佈:2019-01-03
//哈夫曼樹 //楊鑫 #include <stdio.h> #include <stdlib.h> typedef int ElemType; struct BTreeNode { ElemType data; struct BTreeNode* left; struct BTreeNode* right; }; //遍歷哈夫曼樹 void PrintBTree_int(struct BTreeNode* BT) { if (BT != NULL) { printf("%d", BT->data); if (BT->left != NULL || BT->right != NULL) { printf(" ( "); PrintBTree_int(BT->left); //輸出左子樹 if (BT->right != NULL) printf(" , "); PrintBTree_int(BT->right); //輸出右子樹 printf(" ) "); } } } //建立哈夫曼樹 struct BTreeNode* CreateHuffman(ElemType a[], int n) { int i, j; struct BTreeNode **b, *q; b = malloc(n*sizeof(struct BTreeNode)); for (i = 0; i < n; i++) //動態記憶體分配 { b[i] = malloc(sizeof(struct BTreeNode)); b[i]->data = a[i]; b[i]->left = b[i]->right = NULL; } for (i = 1; i < n; i++) { //k1表示森林中具有最小權值的樹根結點的下標,k2為次最小的下標 int k1 = -1, k2; for (j = 0; j < n; j++) //讓k1初始指向森林中第一棵樹,k2指向第二棵 { if (b[j] != NULL && k1 == -1) { k1 = j; continue; } if (b[j] != NULL) { k2 = j; break; } } for (j = k2; j < n; j++) //構造最優解 { if (b[j] != NULL) { if (b[j]->data < b[k1]->data) { k2 = k1; k1 = j; } else if (b[j]->data < b[k2]->data) k2 = j; } } q = malloc(sizeof(struct BTreeNode)); q->data = b[k1]->data + b[k2]->data; q->left = b[k1]; q->right = b[k2]; b[k1] = q; b[k2] = NULL; } free(b); return q; } //計算帶權路徑 ElemType WeightPathLength(struct BTreeNode* FBT, int len)//len初始為0 { if (FBT == NULL) //空樹返回0 return 0; else { if (FBT->left == NULL && FBT->right == NULL) return FBT->data * len; else return WeightPathLength(FBT->left,len+1)+WeightPathLength(FBT->right,len+1); } } //構造哈夫曼編碼 void HuffManCoding(struct BTreeNode* FBT, int len) { static int a[10]; if (FBT != NULL) { if (FBT->left == NULL && FBT->right == NULL) { int i; printf("結點的值為%d的編碼:", FBT->data); for (i = 0; i < len; i++) printf("%d", a[i]); printf("\n"); } else { a[len] = 0; HuffManCoding(FBT->left, len + 1); a[len] = 1; HuffManCoding(FBT->right, len + 1); } } } int main() { int n, i; ElemType* a; struct BTreeNode* fbt; printf("請輸入帶權結點數n:\n"); while(1) { scanf("%d", &n); if (n > 1) break; else printf("重輸n值:"); } a = malloc(n * sizeof(ElemType)); printf("輸入%d個整數作為權值:\n", n); for (i = 0; i < n; i++) scanf(" %d", &a[i]); fbt = CreateHuffman(a, n); printf("哈夫曼樹如下:\n"); PrintBTree_int(fbt); printf("\n"); printf("哈夫曼樹的帶權路徑長度:\n"); printf("%d\n", WeightPathLength(fbt, 0)); printf("樹中每個葉子結點的哈夫曼編碼:\n"); HuffManCoding(fbt, 0); return 0; }
如圖: