Hello! A task is: Create a priority queue (each item has its own priority). Elements with the highest priority are put in the top of the queue, with the smallest – to the end. (The last digit of the number is its priority).
I realized the insert function itself, but how to deal with priority and how is it generally implemented?
void insert (tpqueue * & amp; pbq, tpqueue * & amp; PEQ, Telq Newel)
{
TPQueue * el = new tpqueue;
EL- & GT; info = newel;
EL- & GT; NEXT = NULL;
If (! Isempty (PEQ)) {
PEQ- & gt; next = EL;
PEQ = EL;
} else {
PEQ = EL;
pbq = el;
};
}
Answer 1, Authority 100%
The classic priority is always based on a binary heap.
# include & lt; Cstdio & gt;
#Include & lt; Cstdlib & gt;
Using Namespace STD;
TEMPLATE & LT; TYPENAME T, TYPENAME CMP & GT;
Class Tpqueue {
Private:
T * Arr;
Size_t CNT;
Size_t Mem;
CMP CMP;
Public:
TPQueue (Void): Arr (NULL), CNT (0), Mem (16) {}
~ TPQueue () {
This- & gt; Clear ();
}
TPQueue (Const Tpqueue & amp;);
TPQueue & amp; Operator = (Const Tpqueue & amp;);
Public:
BOOL PUSH (Const T & AMP; VAL) {
Size_t i, p;
T TMP;
if (! this- & gt; _alloc ())
RETURN FALSE;
ARR [CNT] = VAL;
i = CNT;
P = (! i)? 0: (i - 1) & gt; & gt; 1;
While ((i & gt; 0) & amp; & amp;! Cmp (Arr [P], Arr [i])) {
TMP = Arr [i];
arr [i] = arr [p];
ARR [P] = TMP;
i = p--;
If (! i)
Break;
P & GT; & gt; = 1;
}
++ CNT;
RETURN TRUE;
}
Void POP (Void) {
If (CNT & GT; 1) {
ARR [0] = ARR [- CNT];
this- & gt; this_heapify (0);
} ELSE.
CNT = 0;
}
T & amp; TOP (Void) {Return Arr [0]; }
T & amp; TOP (Void) Const {Return Arr [0]; }
BOOL EMPTY (Void) Const {Return (! CNT); }
Size_t Size (Void) Const {Return CNT; }
Void Clear (Void) {
if (Arr! = NULL)
delete [] arr;
arr = null;
CNT = 0;
mem = 16;
}
Private:
BOOL _ALLOC (Void) {
Size_T TMEM;
T * TMP;
if (arr == null) {
ARR = NEW T [MEM];
if (Arr == NULL)
RETURN FALSE;
}
If ((CNT + 1) & GT; = MEM) {
TMEM = CNT + 1 + CNT / 3;
TMP = NEW T [TMEM];
if (TMP == NULL)
RETURN FALSE;
For (Size_t i = 0u; i & lt; CNT; ++ I)
TMP [i] = Arr [i];
delete [] arr;
Arr = TMP;
Mem = TMem;
}
RETURN TRUE;
}
Void This_Heapify (Size_t Index) {
Size_T L, R, BIG;
T TMP;
While (1) {
L = (index & lt; & lt; 1) + 1u;
R = (index & lt; & lt; 1) + 2U;
if ((L & LT; CNT) & amp; & amp; cmp (arr [l], arr [index]))
Big = L;
ELSE.
Big = index;
If ((R & LT; CNT) & amp; & amp; Cmp (Arr [R], Arr [Big]))
Big = R;
if (Big! = index) {
TMP = Arr [index];
arr [index] = arR [BIG];
Arr [Big] = TMP;
index = Big;
} ELSE.
Break;
}
}
};
STRUCT CMP {
BOOL OPERATOR () (Const int & amp; a, const int & amp; b) const {
RETURN (A & GT; B);
}
};
INT MAIN (Void) {
Tpqueue & lt; int, cmp & gt; PQ;
for (int i = 0; i & lt; 30; ++ i)
pq.push (Rand ()% 400);
While (! pq.empty ()) {
PrintF ("% d \ n", pq.top ());
pq.pop ();
}
Return 0;
}
Answer 2, Authority 33%
@ Yura1996 , I have a limit of comments ended.
Indeed, you can look at Pile , as I advised @dzhioev . Still, guaranteed logarithmic from the number of elements The time of execution of requests is to deal with this at first a non-obvious algorithm.
I looked, everything should just get off.
Just keep in mind that you have the elements of the queue with the same priority must be selected in the order in the queue. Accordingly, the key of the element in a heap should be made composite. Something like
struct queuekey {
Long Priority;
unsigned long seqno;
};
and seqno
in the key it can be simply consistently decreasing (this is the earlier elements of the numeric value of the key with the same priority was greater than the number of the Insert_pqueue ()
, which she will add. Those. prototype
void insert_pqueue (strcript * queue, long priority, void * user_data);
Some kind.
and the queue itself can be done so
struct udata {
Struct QueueKey;
void * user_data;
};
STRUCT PQUEUE {
Size_t Size, Capacity;
Struct Udata * Data;
};
In essence it seems to be a dynamic array of Data [], which you will build up, causing realloc ().
An element with a maximum priority, inserted earlier than the rest will always be in
queue- & gt; data [0];
Try. If you are questions – ask.
Update
@ Yura1996 because you asked the option with lists, then I decided that it would be better to use two levels of lists.
At the external level, a list ordered by priorities, the elements of which will be lists with the user data in order of their receipt (that is, ordinary queues).
This will reduce the number of viewed elements when adding a new queue. Actually, in the loop we view only the top-level elements, at the same time finding the place of insertion in the list of the new queue, if there was no such priority yet. The user data is inserted into the end of the found (or created) queue. Since we support two pointers (on the first and last in line), then it is not needed to view it.
When sampling (deleting) the most priority element of the queue of cycles is not at all.
# include & lt; stdio.h & gt;
#Include & lt; stdlib.h & gt;
#Include & lt; String.h & gt;
#Include & lt; limits.h & gt;
STRUCT UITEM {
STRUCT UITEM * NEXT;
void * udata;
};
STRUCT PRIO {
STRUCT PRIO * NEXT, * PREV;
Long Prio;
Struct uitem * Head, * tail; // All items with this priority
};
STRUCT PRIOQUEUE {
Struct Prio * Head, * Tail;
Size_t Size;
};
#Define PQ_init () ((Struct PRIQUEUE) {0, 0, 0})
Void PQ_INSERT (struct PRIQUEUE * Q, Long Prio, Void * Data);
LONG PQ_PEEK (STRUCT PRIOQUEUE * Q, VOID ** UDATA);
LONG PQ_REMOVE (STRUCT PRIOQUEUE * Q, VOID ** UDATA);
STRUCT PRIO * PQ_FIND (Struct PRIOQUEUE * Q, LONG PRIO);
Static Struct Prio *
Get_Priostr (Long Prio)
{
STRUCT PRIO * T = (Typeof (T)) Malloc (SizeOF (Struct Prio));
t- & gt; next = t- & gt; prev = 0;
T- & GT; Head = T- & GT; tail = 0;
T- & GT; PRIO = PRIO;
RETURN T;
}
Struct Prio *
PQ_FIND (Struct PRIQUEUE * Q, Long Prio)
{
STRUCT PRIO * T = Q- & GT; HEAD;
While (T) {
if (t- & gt; prio & lt; = prio)
Break;
t = t- & gt; next;
}
RETURN T;
}
Void.
PQ_INSERT (STRUCT PRIOQUEUE * Q, Long Prio, Void * Data)
{
STRUCT UITEM * UI = (TypeOf (UI)) Malloc (SizeOF (* UI));
UI- & GT; udata = Data;
ui- & gt; next = 0;
If (! Q- & GT; Head) {
Q- & gt; Head = Q- & gt; tail = get_priostr (prio);
Q- & GT; Head- & gt; Head = Q- & GT; Head- & gt; tail = ui;
} else {
STRUCT PRIO * T = PQ_FIND (Q, PRIO); // INSERT BEFORE OR TO TAIL IF T == 0
If (! T || T- & GT; PRIO! = PRIO) {// New Priority
STRUCT PRIO * NP = Get_Priostr (PRIO);
NP- & GT; Head = NP- & GT; tail = ui;
if (! T) {
Q- & GT; Tail- & gt; next = NP;
NP- & GT; PREV = Q- & GT; Tail;
q- & gt; tail = np;
} else {
if ((NP- & GT; PREV = T- & GT; PREV))
NP- & GT; PREV- & GT; NEXT = NP;
np- & gt; next = t;
T- & GT; PREV = NP;
if (t == q- & gt; head)
Q- & GT; Head = NP;
}
} else {// SAME Priority, Add to Tail
T- & gt; tail- & gt; next = ui;
T- & gt; tail = ui;
}
}
Q- & GT; Size ++;
}
Long.
PQ_PEEK (STRUCT PRIOQUEUE * Q, Void ** DATA)
{
If (! Q- & GT; Head) {
* Data = 0;
RETURN LONG_MIN;
}
* Data = Q- & GT; Head- & gt; Head- & gt; udata;
Return Q- & gt; Head- & gt; prio;
}
Long.
PQ_REMOVE (STRUCT PRIOQUEUE * Q, VOID ** DATA)
{
If (! Q- & GT; Head) {
* Data = 0;
RETURN LONG_MIN;
}
STRUCT UITEM * UI = Q- & GT; Head- & gt; head;
* Data = ui- & gt; udata;
Long Res = Q- & GT; Head- & gt; prio;
If (! (Q- & GT; Head- & gt; head = ui- & gt; next)) {
STRUCT PRIO * P = Q- & GT; HEAD;
if (! (q- & gt; head = p- & gt; next))
q- & gt; tail = 0;
ELSE.
Q- & GT; Head- & gt; prev = 0;
FREE (P);
}
FREE (UI);
Q- & GT; Size--;
RETURN RES;
}
Void.
PR_PRINT (STRUCT PRIOQUEUE * Q)
{
PrintF ("Queue Size:% LD \ N", Q- & GT; Size);
STRUCT PRIO * P = Q- & GT; HEAD;
STRUCT UITEM * T;
While (P) {
PrintF ("Priority:% LD \ N", P- & GT; PRIO);
FOR (T = P- & GT; Head; T; T = T- & GT; NEXT)
PrintF (":% s", (char *) t- & gt; udata);
p = p- & gt; next;
}
}
int.
Main (Int AC, char * AV [])
{
STRUCT PRIOQUEUE Q1 = PQ_INIT ();
Char str [1000];
While (FGETS (STR, 1000, STDIN)) {
INT IPR = ATOI (STR);
char * r;
Long MP;
if (str [0] == '.') {
mp = pq_remove (& amp; q1, (void **) & amp; r);
PrintF ("Remove:% LD [% S] Size:% LD \ N", MP, R, Q1.Size);
FREE (R);
} ELSE if (str [0] == '?')
PR_PRINT (& amp; Q1);
ELSE.
PQ_INSERT (& amp; Q1, IPR, StrDUp (STR));
MP = PQ_PEEK (& amp; Q1, (void **) & amp; r);
printf ("peek:% LD [% s] Size:% LD \ N", MP, R, Q1.Size);
}
EXIT (0);
}
compiled G ++ and GCC. I hope you will figure it out.