由二叉樹構造赫夫曼樹
阿新 • • 發佈:2017-05-19
family 如果 csdn img log ret iss struct center
赫夫曼樹:
如果有n個權值{w1,w2,w3....},試構造一棵具有n個葉子節點的二叉樹,每一個葉子節點帶權為wi。則當中帶權路徑長度最小的二叉樹稱為最優二叉樹或者叫赫夫曼樹。
構造赫夫曼樹:
如果有n個權值,則構造出的赫夫曼樹有n個葉子節點,n個權值分別設置為w1,w2,....wn,則赫夫曼樹的構造規則為:
1.將w1,w2...看成是有n棵樹的森林;
2.在森林中選擇兩個根節點的權值最小的樹合並,作為一棵新樹的左右子樹,且新樹的根節點權值為其左右子樹根節點權值之和;
3.從森林中刪除選取的兩棵樹,並將新樹增加森林。
4.反復2、3步,直到森林中僅僅剩一棵樹為止。該樹即為所求得的赫夫曼樹。
實現: 以數組形式存儲赫夫曼樹節點,節點形態:
測試:
圖解構造過程:
1.首先將二叉樹中的節點所有存到代表赫夫曼樹的數組中。其余位置為0:
2.循環遍歷該數組。每次找到最小權重的兩個節點。之和作為其父節點的權重
3.循環一遍後。便得到赫夫曼樹:
實現: 以數組形式存儲赫夫曼樹節點,節點形態:
/************************************************** 構造赫夫曼樹 by Rowandjj 2014/6/2 **************************************************/ #include<IOSTREAM> using namespace std; #define UINT_MAX 0xffffffff typedef struct _BITREE_//二叉樹 { int data;//存放節點的圈中 struct _BITREE_ *lChild; struct _BITREE_ *rChild; }Bitree,*pBitree; typedef struct _HUFFMANTREE_//赫夫曼樹 { unsigned int weight; unsigned int parent; unsigned int lChild; unsigned int rChild; }HuffmanTree,*pHuffmanTree; int iCount = 0;//葉子節點數 int iIndex = 1;//索引 //----------------------------------------- void CreateBiTree(pBitree* pBitreeTemp);//創建二叉樹 void CreatreArray(pHuffmanTree& pHuffmanTreeTemp,pBitree pBitreeTemp);//將二叉樹每一個節點的值作為權放進赫夫曼樹中 pHuffmanTree InitHuffmanTree();//初始化赫夫曼樹, void CreateHuffmanTree(pHuffmanTree& pHuffmanTreeTemp);//創建赫夫曼樹 int GetNode(pHuffmanTree& pHuffmanTreeTemp,int i);//獲取赫夫曼樹中位置0-i中值最小的節點的索引 void SelectNode(pHuffmanTree& pHuffmanTreeTemp,int i,int *m,int *n);//選擇赫夫曼樹數組中值最小的兩個節點的索引(不包括已有父節點的節點) void DestroyTree(pBitree* pBitreeTemp); void DestroyHuffmanTree(pHuffmanTree& pHuffmanTreeTemp); int main() { int i; //創建二叉樹 pBitree pBitreeTemp; CreateBiTree(&pBitreeTemp); //初始化赫夫曼樹 pHuffmanTree pHuffmanTreeTemp = InitHuffmanTree(); //初始化赫夫曼樹的葉子節點的權 CreatreArray(pHuffmanTreeTemp,pBitreeTemp); for(i = 1; i <= iCount ; i++) { cout<<pHuffmanTreeTemp[i].weight<<" "; } cout<<endl; //創建赫夫曼樹 CreateHuffmanTree(pHuffmanTreeTemp); for(i = 1; i <= 2*iCount-1 ; i++) { cout<<pHuffmanTreeTemp[i].weight<<" "; } cout<<endl; DestroyTree(&pBitreeTemp); DestroyHuffmanTree(pHuffmanTreeTemp); return 0; } void CreateBiTree(pBitree* pBitreeTemp) { int data; cin>>data; if(data == -1) { return; } *pBitreeTemp = (pBitree)malloc(sizeof(Bitree)); if(*pBitreeTemp == NULL) { return; } (*pBitreeTemp)->data = data; (*pBitreeTemp)->lChild = NULL; (*pBitreeTemp)->rChild = NULL; CreateBiTree(&(*pBitreeTemp)->lChild); CreateBiTree(&(*pBitreeTemp)->rChild); iCount++; } pHuffmanTree InitHuffmanTree() { int num = 2*iCount - 1;//赫夫曼樹的節點總數為:葉子節點數*2-1 pHuffmanTree pTemp = (pHuffmanTree)malloc(sizeof(HuffmanTree)*(num+1));//0位不存 if(pTemp == NULL) { return NULL; } for(int i = 0; i <= num; i++) { pTemp[i].lChild = 0; pTemp[i].rChild = 0; pTemp[i].parent = 0; pTemp[i].weight = 0; } return pTemp; } void CreatreArray(pHuffmanTree& pHuffmanTreeTemp,pBitree pBitreeTemp) { if(pBitreeTemp == NULL || pHuffmanTreeTemp == NULL) { return; } pHuffmanTreeTemp[iIndex].weight = pBitreeTemp->data; iIndex++; CreatreArray(pHuffmanTreeTemp,pBitreeTemp->lChild); CreatreArray(pHuffmanTreeTemp,pBitreeTemp->rChild); } int GetNode(pHuffmanTree& pHuffmanTreeTemp,int i) { int min = UINT_MAX; int flag; for(int j = 1; j <= i; j++) { if(pHuffmanTreeTemp[j].weight < min && pHuffmanTreeTemp[j].parent == 0)//已有父節點的不算 { min = pHuffmanTreeTemp[j].weight; flag = j; } } pHuffmanTreeTemp[flag].parent = 1;//防止兩次調用獲取的索引同樣 return flag; } void SelectNode(pHuffmanTree& pHuffmanTreeTemp,int i,int *m,int *n)//m為序號小的那個 { *m = GetNode(pHuffmanTreeTemp,i); *n = GetNode(pHuffmanTreeTemp,i); int t; if(*m > *n) { t = *m; *m = *n; *n = t; } } void CreateHuffmanTree(pHuffmanTree& pHuffmanTreeTemp) { if(pHuffmanTreeTemp == NULL) { return; } int m = 0,n = 0; for(int i = iCount+1;i <= 2*iCount-1; i++) { SelectNode(pHuffmanTreeTemp,i-1,&m,&n); pHuffmanTreeTemp[m].parent = pHuffmanTreeTemp[n].parent = i; //構造兩個最小權重的節點的父節點 pHuffmanTreeTemp[i].lChild = m; pHuffmanTreeTemp[i].rChild = n; pHuffmanTreeTemp[i].weight = pHuffmanTreeTemp[m].weight+pHuffmanTreeTemp[n].weight; } } void DestroyTree(pBitree* pBitreeTemp) { if(*pBitreeTemp == NULL) { return; } if((*pBitreeTemp)->lChild) { DestroyTree(&(*pBitreeTemp)->lChild); } if((*pBitreeTemp)->rChild) { DestroyTree(&(*pBitreeTemp)->rChild); } free(*pBitreeTemp); *pBitreeTemp = NULL; } void DestroyHuffmanTree(pHuffmanTree& pHuffmanTreeTemp) { if(pHuffmanTreeTemp) { free(pHuffmanTreeTemp); } pHuffmanTreeTemp = NULL; }
2.循環遍歷該數組。每次找到最小權重的兩個節點。之和作為其父節點的權重
3.循環一遍後。便得到赫夫曼樹:
由二叉樹構造赫夫曼樹