艾偉 用 C 實現帶鍵值的優先佇列

2021-09-07 23:31:11 字數 3592 閱讀 7680

keyedpriorityqueue來儲存已分配的「記憶體塊」,使用priorityqueue

現在,就開始行動吧。

首先,需要乙個介面,用來獲取鍵以及獲取和設定值,如下所示:

namespace skyiv.util

}

接著,就是我們的帶鍵值的優先佇列keyedpriorityqueue
登場了:

using system;

using system.collections.generic;

namespace skyiv.util

public keyedpriorityqueue(ikeyvalue kv) : this(null, kv)

public keyedpriorityqueue(int capacity, ikeyvalue kv) : this(capacity, null, kv)

public keyedpriorityqueue(icomparer comparer, ikeyvalue kv) : this(16, comparer, kv)

public keyedpriorityqueue(int capacity, icomparer comparer, ikeyvalue kver)

public bool containskey(k key)

public void update(t v)

public void push(t v)

public t pop()

public t top()

void siftup(int n)

void siftdown(int n)

heap[haskey ? (keys[kver.getkey(v)] = n) : n] = v;

}}}

上述keyedpriorityqueue類中,t是要儲存在這個帶鍵值的優先佇列中的資料的型別,k是鍵的資料型別,v是值的資料型別。

dictionary

int> keys字段用於儲存鍵(k)在堆(heap)中的索引。

bool containskey(k key)方法用於查詢指定的鍵是否在該優先佇列中。

update(t v)方法用於更新指定專案的值。注意,如果要使用這個方法的話,t不能是值型別。之所以在這個方法的第二行:

if (typeof(t).isvaluetype) throw new

invalidoperationexception("t 不能是值型別");

進行這個判斷,而不是在將該類宣告為:

class

keyedpriorityqueue

where t : class

這是因為,如果不需要呼叫update(t v)方法的話,t還是允許是值型別的。

該類的其他方面,除了加入對 keys 欄位的處理以外,就和標準的優先佇列差不多了。

有了這個keyedpriorityqueue類,就可以從中派生出priorityqueue類來:

class 

priorityqueue : keyedpriorityqueue

object, object>

public priorityqueue(int capacity) : base(capacity, null)

public priorityqueue(icomparer comparer) : base(comparer, null)

public priorityqueue(int capacity, icomparer comparer) : base(capacity, comparer, null)

}

對於priorityqueue類的例項,如果呼叫containskey方法,總是返回false。如果呼叫update方法,總是引發notsupportedexception異常。

首先,block必須從結構改為類,如下所示:

sealed class 

block

public int time

public block(int id, int time)

}

然後,需要乙個實現ikeyvalue介面的類:

sealed class 

idtime : ikeyvalue

public int getvalue(block x)

public void setvalue(block x, int v)

}

最後,就剩下最簡單的工作了,將 main 方法的第二行:

var used = new

keyedpriorityqueue(new

timecomparer());

修改為:

var used = new

keyedpriorityqueue

(new

timecomparer(), new

idtime());

就可以了。

當然,這也是有代價的,就是執行時間和記憶體使用都增加了:

iddate

author

problem

language

judgement

result

execution

time

memory

used

2568007

21:22:09 18 apr 2009

skyivben

1037

c#accepted

0.406

6 129 kb

2566773

09:24:17 18 apr 2009

skyivben

1037

c#accepted

0.265

4 521 kb

實際上,雖然keyedpriorityqueue類中的**與priorityqueue類中**有大量的重複,可以用本篇隨筆的方法將keyedpriorityqueue類改為keyedpriorityqueue泛型類,再從中派生出priorityqueue類來,以消除重複的**。但是,這樣必然造成priorityqueue類的執行效率降低。所以,一般情況下,priorityqueue類還是使用原來的**為好。

當然,如果能夠從priorityqueue類派生出keyedpriorityqueue類,那就比較完美了。不知各位大俠是否還有更好的方法?

利用redis實現帶優先順序的訊息佇列

以前一直有使用celery的優先順序機制 基於redis的任務佇列 一直很好奇它的實現機制,在查閱了部分資料後,決定寫這篇文章,作為總結。使用sorted set 做優先順序佇列最大的優點是直觀明了。zadd key score member score member score member sc...

C 實現優先佇列的簡單例項

c 實現優先佇列的簡單例項 優先佇列類模版實現 buildmaxheap.h標頭檔案 include using namespace std define left i i 2 1 define right i i 2 2 define parent i i 1 2 void max heapify...

容易理解的python用佇列實現廣度優先遍歷檔案

需求簡單介紹 硬碟中查詢檔案,不同目錄中檔案的整合,專案開發中多檔案聯合查詢,等都要用到檔案遍歷。首先簡單闡述一下廣度遍歷實現方式 廣度遍歷檔案很明顯,每一次遍歷不追求遍歷目錄的深度,只追求其廣度。下面畫張圖形容一下 看圖分析 對 廣度遍歷測試 這個資料夾,進行遍歷,第一次把a中的東西遍歷完,資料夾...