Krótka odpowiedź: nie możesz.
Nieco dłuższa odpowiedź:
Będziesz potrzebował dodatkowej przestrzeni do przechowywania „wieku” swojego wpisu, co pozwoli ci rozróżnić identyczne priorytety. Będziesz potrzebował Ω ( n ) miejsca na informacje, które pozwolą na szybkie wstawianie i wyszukiwanie. Plus twoja ładowność (wartość i priorytet).Ω(n)Ω(n)
I dla każdego bloku danych przechowywanych, będziesz w stanie „ukryć” pewne informacje w adresie (np d d r ( X ) < d d r ( Y ) oznacza Y jest starsze niż X). Ale w tych „ukrytych” informacjach albo ukryjesz „wiek”, LUB „szybkie wyszukiwanie”. Nie oba.addr(X)<addr(Y)
Bardzo długa odpowiedź z niedokładną pseudo-matematyką:
Uwaga: jak wspomniano, sam koniec drugiej części jest szkicowy. Gdyby jakiś matematyk dostarczyłby lepszą wersję, byłbym wdzięczny.
Pomyślmy o ilości danych, które są zaangażowane na maszynie X-bitowej (powiedzmy 32 lub 64-bitowej), z szerokimi rekordami (wartość i priorytet) P
Masz zestaw potencjalnych rekordów, który jest częściowo uporządkowany: i ( a , 1 ) = ( a , 1 ), ale nie możesz porównać ( a , 1 ) i ( b , 1 ) .(a,1)<(a,2)(a,1)=(a,1)(a,1)(b,1)
Jednak chcesz być w stanie porównać dwie nieporównywalne wartości ze swojego zestawu rekordów, na podstawie tego, kiedy zostały wstawione. Więc masz tu inny zestaw wartości: tych, które zostały wstawione i chcesz zwiększyć jej częściowego porządku: wtw X został wstawiony przed Y .X<YXY
W najgorszym przypadku pamięć zostanie wypełniona zapisami formularza (z ? Innym dla każdego), więc będziesz musiał całkowicie polegać na czasie wstawiania, aby zdecydować, który z nich pójdzie pierwszy.(?,1)?
- X−log2(P)2X
- P
X−log2(P)O(n)n
Ile bitów informacji zapewnia nam każda „komórka” pamięci?
- WW being the machine word width).
- X bits of address.
Now, let's assume P≥1 (payload is at least one machine word wide (usually one octet)). This means that X−log2(P)<X, so we can fit the insertion order information in the cell's address. That's what happening in a stack : cells with the lowest address entered the stack first (and will get out last).
So, to store all our information, we have two possibilities :
- Store the insertion order in the address, and the payload in memory.
- Store both in memory and leave the address free for some other usage.
Obviously, in order to avoid waste, we'll use the first solution.
Now for the operations. I suppose you wish to have :
- Insert(task,priority) with O(logn) time complexity.
- StableExtractMin() with O(logn) time complexity.
Let's look at StableExtractMin() :
The really really general algorithm goes like this :
- Find the record with minimum priority and minimum "insertion time" in O(logn).
- Remove it from the structure in O(logn).
- Return it.
For example, in the case of a heap, it will be slightly differently organized, but the work is the same :
1. Find the min record in 0(1)
2. Remove it from the structure in O(1)
3. Fix everything so that next time #1 and #2 are still O(1) i.e. "repair the heap". This needs to be done in "O(log n)"
4. Return the element.
Going back to the general algorithm, we see that to find the record in O(logn) time, we need a fast way to choose the right one between 2(X−log2(P)) candidates (worst case, memory is full).
This means that we need to store X−log2(P) bits of information in order to retrieve that element (each bit bisects the candidate space, so we have O(logn) bisections, meaning O(logn) time complexity).
These bits of information might be stored as the address of the element (in the heap, the min is at a fixed address), or, with pointers for example (in a binary search tree (with pointers), you need to follow O(logn) on average to get to the min).
Now, when deleting that element, we'll need to augment the next min record so it has the right amount of information to allow O(logn) retrieval next time, that is, so it has X−log2(P) bits of information discriminating it from the other candidates.
That is, if it doesn't have already enough information, you'll need to add some. In a (non-balanced) binary search tree, the information is already there : You'll have to put a NULL pointer somewhere to delete the element, and without any further operation, the BST is searchable in O(logn) time on average.
After this point, it's slightly sketchy, I'm not sure about how to formulate that. But I have the strong feeling that each of the remaining elements in your set will need to have X−log2(P) bits of information that will help find the next min and augment it with enough information so that it can be found in O(logn) time next time.
The insertion algorithm usually just needs to update part of this information, I don't think it will cost more (memory-wise) to have it perform fast.
Now, that means that we'll need to store X−log2(P) more bits of information for each element. So, for each element, we have :
- The insertion time, X−log2(P) bits.
- The payload P machine words.
- The "fast search" information, X−log2(P) bits.
Since we already use the memory contents to store the payload, and the address to store the insertion time, we don't have any room left to store the "fast search" information. So we'll have to allocate some extra space for each element, and so "waste" Ω(n) extra space.