Java中的優先隊列

Form一個問題

假設百度搜索引擎一天會搜索M億條URL,如何根據URL被搜索的次數來找出次數最高的N個URL呢?
個人有一個抽象的思路:
- 先對所有的URL日誌文檔進行整合,同一類型的當作一個結點,利用B或者B+樹搜索的優秀性能來處理
- 再使用優先隊列或者是最大值堆來進行一個排序

正確與否先撇開不談,整合同類URL的過程中會給後續排序減少大量的工作量(但究竟對於這種億級的數據量還是隻有一個朦朧的概念)。不管怎麼說,先來研究一下Java中的優先隊列好了

優先隊列和遍歷層次樹

優先隊列(PriorityQueue)是不同於普通隊列的先進先出的隊列,每次從隊列中取出的是具有最高優先權的元素。這是從Java1.5開始引入的數據結構的接口。

// TestPriorityQueue.java
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;

class Student{
    int id;
    String name;

    public Student(){
        this.id = 0;
        this.name = "";
    }

    public Student(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }
    public String getName() {
        return name;
    }
}

public class TestPriorityQueue {

    private static Comparator<Student> stCompare = new Comparator<Student>(){
        // 重寫了比較器中的compare方法,否則直接把Student類型的元素加入優先隊列會報錯
        @Override
        public int compare(Student st1,Student st2){
            // 針對Student的id屬性進行比較
            return (int)(st1.getId()-st2.getId());
        }
    };

    public static void main(String[] args){
        Queue<Integer> number = new PriorityQueue<Integer>();// 存放int類型的數據
        Random rand = new Random();
        for(int i=0;i<5;i++){
            //因爲實例化時使用了默認的比較器,所以隊列新增的元素時都會自動排序
            number.add(rand.nextInt(100));
        }
        for(Integer i : number){
            System.out.println(i);
        }
        System.out.println();

        // ----- 下面開始排序自定義類
        // 把重寫後的比較器作爲參數傳入優先隊列
        Queue<Student> students = new PriorityQueue<Student>(5,stCompare);
        for(int i=0;i<5;i++){
            students.add(new Student(rand.nextInt(10),String.valueOf(i)));
        }

        // 預計的輸出結果會是:不管st.name是怎樣的順序,但是st.id一定是由小到大
        for(Student st : students){
            System.out.println(st.id + " " + st.name);
        }
    }
}

遍歷層次樹

怎麼百度的都是概念層次樹(黑人問號….),相關的知識有如何層次遍歷二叉樹,思路是
- 使其根節點入隊列,然後出隊進行訪問
- 若左子節點不爲空,使左子節點入隊
- 若該節點的右子節點,再使右子節點入隊
- 重複上面三個步驟,直到訪問了所有節點

大概的思路是這樣,開的坑已經夠多了,這個就先放後面好了 /:doge

又回到了HashMap高性能讀寫方法?

其實是自己沒有繞出這個圈,那天和dalao討論的時候,ta認爲沒有什麼優化的方法,畢竟HashMap已經被寫好放在jar中了,若是使用,怎麼會優化呢?

of cause,自己擼一個HashMap實現,這就引出了一個重點,在我們討論這個問題的時候,前提是什麼?,有說可以自己擼嗎?不知道,有說必須要用jdk中的HashMap嗎?不知道。

So,…….

日常總結

今天被教育“凡是遇到問題的時候,第一個想到的就應該是前提條件”,沒有前提條件,問題是不受約束的。看似是一個誰都懂的道理,但真的很多時候,會被自己潛意識認爲的條件侷限了自己的思維。就這樣。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章