哈夫曼樹的編碼與解碼
#include<stdio.h> #include<stdlib.h> #include<iostream> #include<string> using namespace std; #define MAXSIZE 30
typedef struct node { int data; char value; struct node *lchild, *rchild; struct node *next; }*TreeLink,Link;
TreeLink CreateTree(int n) { TreeLink link = NULL, p = NULL, q = NULL, s = NULL; int i; link = (TreeLink)malloc(sizeof(Link)); link->lchild = link->lchild = link->next = NULL; s= (TreeLink)malloc(sizeof(Link)); cout << "請輸入葉子的權值" << endl; cin >> s->data; cout << "請輸入葉子的值" << endl; cin >> s->value; s->lchild = s->rchild = s->next = NULL; link->next = s; for (i = 2; i <= n; i++) { s= (TreeLink)malloc(sizeof(Link)); cout << "請輸入葉子的權值" << endl; cin >> s->data; cout << "請輸入葉子的值" << endl; cin >> s->value; s->lchild = s->rchild = s->next = NULL; q = link; p = q->next; while (p != NULL) { if (s->data < p->data) { s->next = p; q->next = s; break; } else { q = p; p = p->next; } } if (p == NULL) { q->next = s;
} } return link; }
void Print(TreeLink h) { TreeLink p = h->next; while (p != NULL) { cout << "權值為:" <<p->data<<endl; p = p->next; } printf("\n"); }
TreeLink HuffTree(TreeLink link) { TreeLink p = NULL, q = NULL, s = NULL; while (link->next != NULL) { p = link->next; q = p->next; if (q->next != NULL) link->next = q->next; else { link->next = NULL; } s= (TreeLink)malloc(sizeof(Link)); s->data = p->data + q->data; cout << "s->data" << s->data << endl; s->next = NULL; s->lchild = p; s->rchild = q; q = link; p = q->next; while (p != NULL) { //順序插入,不要破壞連結串列的從小到大的順序 if (s->data <= p->data) { q->next = s; s->next = p; break; } else { q = p; p = p->next;
} if (q != NULL && s->data > q->data) { q->next = s; s->next = p; } } } return s; } void HuffCode(TreeLink p) { TreeLink stack[MAXSIZE], q = NULL; int b, i = -1, j = 0, k, code[MAXSIZE]; do { while (p != NULL) { if (p->lchild == NULL && p->rchild == NULL) { cout << "p->data:" << p->data << endl;//輸出葉子結點的權值 for (k = 0; k < j; k++)//輸出編碼 cout << code[k]; cout << endl; cout << "該葉子的值為:" << p->value << endl;//輸出值 j--; } stack[++i] = p;//指向當前結點的指標p入棧 p = p->lchild;//p指向p的左孩子 code[j++] = 0;//對應的左分支上編碼0 } //棧頂結點已經沒有左孩子或是其左子樹上的結點都已被訪問 q = NULL; b = 1;//置已訪問過的標記 while (i >= 0 && b)//棧不空且棧頂結點的左子樹已經遍歷過 { p = stack[i];//取出當前棧頂儲存的結點指標 if (p->rchild ==q)//當前棧頂結點p無右孩子或右孩子已經訪問 { i--; j--; q = p;//q指向剛訪問過的結點p } else//當前棧頂p有右子樹 { p = p->rchild;//p指向當前棧頂結點的右孩子結點 code[j++] = 1;//對應的右分支編碼置1 b = 0;//置右孩子結點未遍歷過其右子樹標記 } } } while (i >= 0);//當棧非空時繼續遍歷 } void PreOrder(TreeLink head) { if (head) { cout << head->data << endl; PreOrder(head->lchild); PreOrder(head->rchild); } }
void decodeing(string str, TreeLink head) { TreeLink temp = head; int i = 0; while (str[i] != '\n' && temp->lchild && temp->rchild) { if (str[i] - 48 == 0 ) { temp = temp->lchild; } else { if (str[i] - 48 == 1 ) temp = temp->rchild; } i++; } cout << "解碼的值為:" << temp->value; }
int main() { int n; cout << "請輸入結點的個數" << endl; cin >> n; TreeLink head = CreateTree(n),s=NULL; Print(head); cout << "HuffmanTree" << endl; s = HuffTree(head); PreOrder(s); cout << "編碼" << endl; HuffCode(s); string str; for (int i = 0; i < 3; i++) { cout << "請輸入你想要解的碼" << endl; cin >> str; decodeing(str, s); } return 0; }