我们都知道,在java中有个很方便的储存一个集合的东西叫数组,它允许我们存取同一类型的数,而且使用起来简单方便,但是,既然有优点,那肯定会有缺点。缺点就是数组无法改变其大小,你定义多大就多大,无法在改变(除非你重新new一个出来)
而队列就弥补了这种缺点,队列的大小并不是一开始就固定的,而是随着你加入的数的多少而改变。所以队列更能节省内存资源。
学过c语言或者c++的同学可能会想,队列和链表有什么区别?
我觉得吧,链表是我们直接控制指针其实本质上队列也是在控制指针,但在java中不允许操控指正,所以更安全。
链表
上次说到队列与链表的区别,这里我再补充一下。队列在计算机中是一段连续的存储空间,而链表却并不是,链表由一个个节点构成,在内存中不连续,就好像是几个零散的珠子用线把他们连起来一样。
举个更形象的比喻,链表就好像做任务,从一个npc到另一个npc,一个一个的连起来。
我们有了队列,为什么还需要链表呢?其实对于c++来说本无多大区别,因为c++的内存是要认为去释放的,由于这种原因,不要的内存可以马上释放掉,而java不同,他的内存是由gc释放的,而gc不是认为控制的,所以内存可能不会及时释放(这算是个优点也算缺点吧,对于马虎的程序员来说也许更适合学java)。队列就是那种不会及时释放的。因为他本质来时使用数组。而链表则是要多少拿多少的形式。
实例:哈夫曼树构建与实现简单转码
package cn.czm0801;
import java.util.List;
import java.util.PriorityQueue;
public class HuffmanTree {
private Node root;//根节点
private PriorityQueue<Node> pq;//优先队列
public HuffmanTree(PriorityQueue<Node> pq){
this.pq = pq;
}
/**
* 添加节点方法
* @param n1
* @param n2
*/
public void add(Node n1,Node n2){
Node n = new Node((char)(0),n1.getCount()+n2.getCount());
n.setLeft(n1);
n.setRight(n2);
pq.add(n);
}
/**
* 创建哈夫曼树方法
*/
public void createTree(){
while(pq.size()>1){
this.add(pq.poll(), pq.poll());
}
root = pq.peek();
}
public void ergodic(Node current,String str){
if(current.getLeft()==null && current.getRight()==null){
current.setCode(str);
System.out.println(current + " 编码是 " + current.getCode());
return;
}
this.ergodic(current.getLeft(), str + "0");
this.ergodic(current.getRight(), str + "1");
}
/**
* 还原内容
* @param str
* @param list
*/
public void restore(String strCode,List<Node> list,final int length){
String str = "";
int count = 0;
int i =0;
while(count <length){
if(strCode.indexOf(list.get(i%list.size()).getCode())==0){
count ++;
strCode = strCode.substring(list.get(i%list.size()).getCode().length());
str = str +list.get(i%list.size()).getCh();
}
i++;
}
System.out.println("恢复后的内容是 "+str);
}
public Node getRoot() {
return root;
}
}
package cn.czm0801;
public class Node {
private char ch;//字符
private int count;//次数
private String code;//编码
// 左子树节点
private Node left;
// 右子树节点
private Node right;
public Node(char ch, int count) {
this.ch = ch;
this.count = count;
}
public char getCh() {
return ch;
}
public void setCh(char ch) {
this.ch = ch;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
public String toString(){
return ch + " 出现次数是" + count;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
package cn.czm0801;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.PriorityQueue;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
String str = "fdjhjfhvcvnlhvnbcvur";
List<Node> list = new ArrayList<Node>();
statistic(str,list);
/**
* 使用匿名类,创建比较器
*/
Comparator<Node> comparator = new Comparator<Node>(){
public int compare(Node n1, Node n2) {
if(n1.getCount() > n2.getCount()){
return 1;
}else if(n1.getCount()< n2.getCount()){
return -1;
}else{
if(n1.getCh() > n2.getCh()){
return 1;
}else if(n1.getCh() < n2.getCh()){
return -1;
}else{
return 0;
}
}
}
};
//优先队列
PriorityQueue<Node> pq = new PriorityQueue<Node>(list.size(),comparator);
for(int i = 0;i<list.size();i++){
pq.add(list.get(i));
}
//构建哈夫曼树
HuffmanTree ht = new HuffmanTree(pq);
ht.createTree();
ht.ergodic(ht.getRoot(), "");
//把字符串转换成编码格式
char[] ch = str.toCharArray();
String strCode ="";
for(int i = 0;i<ch.length;i++){
for(int j = 0;j<list.size();j++){
if(ch[i]==list.get(j).getCh()){
strCode = strCode + list.get(j).getCode();
break;
}
}
}
System.out.println("转码后的内容是 " + strCode);
ht.restore(strCode, list, str.length());//恢复内容
}
/**
* 统计字符出现的次数
* @param str
* @param list
*/
public static void statistic(String str,List<Node> list){
char[] ch = str.toCharArray();
boolean isAppear = false;
for(int i =0 ;i<ch.length;i++){
for(int j = 0; j < list.size();j++){
if(list.get(j).getCh() == ch[i]){
list.get(j).setCount(list.get(j).getCount()+1);
isAppear = true;
break;
}
}
if(!isAppear){
list.add(new Node(ch[i],1));
}
isAppear = false;
}
}
}