1. 程式人生 > >資料結構————哈夫曼樹

資料結構————哈夫曼樹

資料結構——哈夫曼樹

哈夫曼樹又被稱為最優二叉樹,是指一類帶權路徑長度最小的二叉樹,
哈夫曼樹的遍歷不是唯一的,因為在構造樹的時候左右子樹的位置是不同的。
哈夫曼樹的構造思想如下

1:在給定權值的結點集合中,每個結點都是一顆獨立的二叉樹,並且左右子樹為空,且只有一個根結點。
2:在集合中找到倆個最小的結點,並且組成一個新的結點,這倆個最小的分別為這個新結點的左右子樹。新的結點為這兩個結點的根結點。並且刪除這倆個最小的結點,將新組成的結點新增集合中。
3:直到集合中元素長度不為1的時候 重複2

例如:
{1,2,3,4}構成的哈夫曼樹是什麼?
1

在這裡用連結串列實現,因為經常要刪除和新增,連結串列比較好。
流程圖如下
_


程式碼如下:

//  main.cpp
//  hafuman
//
//  Created by 橘子和香蕉 on 2018/11/22.
//  Copyright © 2018 橘子和香蕉. All rights reserved.
//

#include <iostream>
using namespace std;
typedef struct node{
    int data;
    node * parent;
    node *lchild;
    node *rchild;
    node *next;
}node;

class Tree{
private:
    node* head;
    node *hufmTreeHead;
    int length;
#pragma 私有函式宣告
    void inorderNode(node *p);//中序遍歷
    void findMinNodeandDelete(node *&p);//找最小的結點並且刪除掉
    void addNode(node *p1);//兩個引數組成一個新的結點然後新增這個新的結點
public:
    Tree(){head = new node; head->lchild = head->rchild=head->parent=head->next =  NULL;hufmTreeHead = NULL; }
    void initTreeList();//建立一條連結串列
    void createHufmTree();//建立一個二叉樹
    void inorderTree();//中序遍歷
    void printNode();//輸出所有連結串列中的結點
};
#pragma 私有函式的實現開始
void Tree::inorderNode(node *p){
    if(p ==  NULL) return;
    else{
        inorderNode(p->lchild);
        cout<<"data: "<<p->data<<"\n";
        inorderNode(p->rchild);
    }
}
void Tree::findMinNodeandDelete(node *&p){
    /*查詢分為兩步;
     1:遍歷連結串列,找到最小值所在的結點的位置,記下這個位置
     2:遍歷連結串列,找個這個結點。
     
     因為不能在第一遍遍歷連結串列的時候同時刪除這個最小值所在的單向連結串列。同時也不能刪除這個結點,因為這個結點還是留下來聯接。
     */
    node *h1 = head;
    node *h = h1->next;
    int min = INT_MAX;
    while ( h != NULL) {
        if(h->data < min){
            min = h->data;
            p = h;
        }
        h = h->next;
    }
    h = h1->next;
    while (h != NULL) {
        if(h == p){
            h1->next = h->next;
            break;
        }
        h1 = h;
        h = h->next;
    }
    length--;//刪除一個結點length-1;
}
void Tree::addNode(node *p){
    
    //頭插法新增結點每次新增的都是在結點的頭部
    p->next = head->next;
    head->next = p;
    length++;//新增一個新的結點length++;
}

#pragma 私有函式實現結束


#pragma 公有函式實現開始
void Tree::initTreeList(){
    cout<<"input data length:\n";
    int length;
    cin>>length;
    this->length = length;//資料長度
    cout<<"begin  input node data:\n";
    int data = 0;
    node *h = head;
    node* p;
    for (int i = 0; i<length; i++) {
        cout<<"input data: \t";
        cin>>data;
        p = new node;
        p->data= data;
        p->lchild = p->rchild=p->parent=p->next =  NULL;
        h->next = p;
        h = p;
        
    }
    
}
void Tree::createHufmTree(){
    node *p1,*p2;//找到的新結點
    while (length > 1) {
        findMinNodeandDelete(p1);
        findMinNodeandDelete(p2);
        node *n  = new node;//通過p1和p2組成一個新的結點;
        n->data = p1->data+p2->data;
        n->lchild = p1;
        n->rchild = p2;
        n->next = NULL;
        p1->parent = p2->parent = n;
        addNode(n);
    }
    hufmTreeHead = head->next;
    cout<<"hufmanHead:"<<hufmTreeHead->data<<endl;
}

void Tree::inorderTree(){
    cout<<"inorderTree-------------------------------------------\n";
    node *p = hufmTreeHead;
    inorderNode(p);
    cout<<endl;
    cout<<"inorderTree___________________________________________\n";
}

void Tree::printNode(){
    cout<<endl;
    cout<<"printNode begin---------------------------\n";
    node *h = head->next;
    cout<<"length"<<length<<";";
    while (h !=  NULL) {
        cout<<"h->data:"<<h->data<<endl;
        h = h->next;
    }
    cout<<"printNode finish_____________________\n";
}

#pragma 公有函式的實現的結束
int main(){
    Tree t;
    t.initTreeList();
    t.printNode();
    t.createHufmTree();
    t.inorderTree();
    return 1;
}