日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【大话数据结构算法】哈夫曼树

發(fā)布時(shí)間:2024/4/14 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【大话数据结构算法】哈夫曼树 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

哈夫曼樹又稱為最優(yōu)二叉樹

1、路徑和路徑長度

在一棵樹中,從一個(gè)節(jié)點(diǎn)往下可以達(dá)到的孩子或者子孫節(jié)點(diǎn)之間的通路稱為路徑。通路中分支的數(shù)目稱為路徑長度。若規(guī)定根節(jié)點(diǎn)的層數(shù)為1,則從根節(jié)點(diǎn)
到第L層節(jié)點(diǎn)的路徑長度為L-1.

2、節(jié)點(diǎn)的權(quán)和帶權(quán)路徑長度

若將樹中結(jié)點(diǎn)賦給一個(gè)有著某種含義的數(shù)值,則這個(gè)數(shù)值稱為該結(jié)點(diǎn)的權(quán)。結(jié)點(diǎn)的帶權(quán)路徑長度為:從根結(jié)點(diǎn)到該結(jié)點(diǎn)之間的路徑長度與該結(jié)點(diǎn)的權(quán)的乘積。

3、樹的帶權(quán)路徑長度

樹的帶權(quán)路徑長度規(guī)定為所有葉子結(jié)點(diǎn)的帶權(quán)路徑長度之和,記為WPL。


4、哈夫曼樹的構(gòu)造:

假設(shè)有n個(gè)權(quán)值,則構(gòu)造出的哈夫曼樹有N個(gè)葉子節(jié)點(diǎn)。n個(gè)權(quán)值分別設(shè)為w1、w2……wn,則哈夫曼樹的構(gòu)造規(guī)則為:

1、將w1、w2……wn看成是有n棵樹的森林(每棵樹僅有一個(gè)節(jié)點(diǎn));
2、在森林中選出兩個(gè)根節(jié)點(diǎn)權(quán)值最小的樹合并,作為一棵新樹的左、右子樹,且新樹的根節(jié)點(diǎn)權(quán)值為其左、右子樹根節(jié)點(diǎn)權(quán)值之和;
3、從森林中刪除選取的兩棵樹,并將新樹加入森林;
4、重復(fù)2、3步,直到森林中只剩一棵樹為止,該樹即為所求的的哈夫曼樹。


5、基本性質(zhì):

具有n個(gè)葉子節(jié)點(diǎn)的哈夫曼樹,一共需要2n-1個(gè)葉子節(jié)點(diǎn)。


6、java實(shí)現(xiàn)構(gòu)造哈夫曼樹以及對哈夫曼樹的廣度優(yōu)先遍歷:

Node.java

/*** 哈夫曼樹的結(jié)點(diǎn)類* @author lmb**/ public class Node<T> implements Comparable<Node<T>> {private T data;private double weight;private Node<T> left;private Node<T> right;public Node(T data, double weight) {super();this.data = data;this.weight = weight;}public T getData() {return data;}public void setData(T data) {this.data = data;}public double getWeight() {return weight;}public void setWeight(double weight) {this.weight = weight;}public Node<T> getLeft() {return left;}public void setLeft(Node<T> left) {this.left = left;}public Node<T> getRight() {return right;}public void setRight(Node<T> right) {this.right = right;}public String toString(){return "data : " + this.data + "; weight : " + this.weight;}@Overridepublic int compareTo(Node<T> other) {if (other.getWeight() > this.getWeight()) {return 1;}if (other.getWeight() < this.getWeight()) {return -1;}return 0;}}

HuffmanTree.java

import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; import java.util.Queue;import edu.emory.mathcs.backport.java.util.Collections;public class HuffmanTree<T> {public static void main(String[] args){List<Node<String>> list = new ArrayList<Node<String>>();list.add(new Node<String>("a",9));list.add(new Node<String>("b",5));list.add(new Node<String>("c",3));list.add(new Node<String>("d",7));list.add(new Node<String>("e",8));list.add(new Node<String>("f",6));//構(gòu)造一棵哈夫曼樹Node<String> root = createTree(list);//廣度優(yōu)先遍歷剛剛構(gòu)造的哈夫曼樹List<Node<String>> nodes = breadth(root);for (int i = 0; i < nodes.size(); i++) {System.out.println(nodes.get(i));}}//創(chuàng)建哈夫曼樹public static <T> Node<T> createTree(List<Node<T>> nodes){while(nodes.size() > 1){Collections.sort(nodes);Node<T> left = nodes.get(nodes.size() - 1);//左節(jié)點(diǎn)Node<T> right = nodes.get(nodes.size() - 2);//右節(jié)點(diǎn)//父節(jié)點(diǎn)Node<T> parent = new Node<T>(null,left.getWeight() + right.getWeight());//利用左右節(jié)點(diǎn)構(gòu)造父節(jié)點(diǎn)parent.setLeft(left);parent.setRight(right);//從森林中刪除所選的兩棵樹,并將新樹加入森林nodes.remove(left);nodes.remove(right);nodes.add(parent); }return nodes.get(0);}public static <T> List<Node<T>> breadth(Node<T> root){List<Node<T>> list = new ArrayList<Node<T>>();Queue<Node<T>> queue = new ArrayDeque<Node<T>>();//如果根節(jié)點(diǎn)不為空,將根節(jié)點(diǎn)加入隊(duì)列if (root != null) {queue.offer(root);}while(!queue.isEmpty()){//將隊(duì)列前端元素節(jié)點(diǎn)加入list中(使用但不移出)list.add(queue.peek());//獲取并移出隊(duì)列中的元素節(jié)點(diǎn)Node<T> node = queue.poll();//如果節(jié)點(diǎn)的左子樹存在,將其加入隊(duì)列if (node.getLeft() != null) {queue.offer(node.getLeft());}//如果節(jié)點(diǎn)的右子樹存在,將其加入隊(duì)列if (node.getRight() != null) {queue.offer(node.getRight());}}return list;}}

運(yùn)行結(jié)果:

data : null; weight : 38.0
data : null; weight : 16.0
data : null; weight : 22.0
data : null; weight : 8.0
data : e; weight : 8.0
data : a; weight : 9.0
data : null; weight : 13.0
data : c; weight : 3.0
data : b; weight : 5.0
data : f; weight : 6.0


附錄:java.util.Queue用法

隊(duì)列是一種特殊的線性表,它只允許在表的前端(front)進(jìn)行刪除操作,而在表的后端(rear)進(jìn)行插入操作。進(jìn)行插入操作的端稱為隊(duì)尾,進(jìn)行刪除操作的端稱為隊(duì)頭。隊(duì)列中沒有元素時(shí),稱為空隊(duì)列。

在隊(duì)列這種數(shù)據(jù)結(jié)構(gòu)中,最先插入的元素將是最先被刪除的元素;反之最后插入的元素將是最后被刪除的元素,因此隊(duì)列又稱為“先進(jìn)先出”(FIFO—first in first out)的線性表。

在java5中新增加了java.util.Queue接口,用以支持隊(duì)列的常見操作。該接口擴(kuò)展了java.util.Collection接口。

Queue使用時(shí)要盡量避免Collection的add()和remove()方法,而是要使用offer()來加入元素,使用poll()來獲取并移出元素。它們的優(yōu)點(diǎn)是通過返回a.u值可以判斷成功與否,add()和remove()方法在失敗的時(shí)候會拋出異常。 如果要使用前端而不移出該元素,使用element()或者peek()方法。

值得注意的是LinkedList類實(shí)現(xiàn)了Queue接口,因此我們可以把LinkedList當(dāng)成Queue來用。

超強(qiáng)干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生

總結(jié)

以上是生活随笔為你收集整理的【大话数据结构算法】哈夫曼树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。