Ustuvor navbatlarni piramidada qurish
Piramidaning muhim ustunligidan biri undagi qiymatlardan maksimali uning uchida joylashgan bo’ladi. Piramidaning qayta tiklash up() va down() amallari ko’chishlar sonini piramidaning uchidan oshmagan holda amalga oshiradi, bu esa ustuvor navbatlarni samarali qo’llashga imkon yaratadi.
Avvalo, bu qo’llash elementning tuzilmasini (chunki element faqatgina prioritetni emas balki qiymatni ham o’zida saqlaydi) tavsiflashni va piramidani hosil qiluvchi massivni e’lon qilishni talab qiladi. Piramidani qayta tiklash amallari priority maydonini solishtirishi lozim. Navbatning elementlari sonini saqlash uchun konstruktorda 0 qiymati bilan tashkil qilinadigan alohida size o’zgaruvchisi ajratiladi.
static const int MAX_SIZE = 100;
struct Elem {
int val;
int priority;
Elem(int v = 0, int p = 0) {
val = v;
priority = p;
}
} a[MAX_SIZE];
int size;
Elementlar qo’shish a[size] yacheykasida amalga oshiriladi. Qo’shimcha element kiritilgandan so’ng piramidaning asosiy xususiyati o’zgarishi mumkin, qo’shimcha ravishta up() protsedurasini chaqirish talab qilinadi. Qo’shimcha element kiritishning umumiy murakkabligi O(lonN) tashkil qiladi.
void enqueue(int value, int priority) {
if (size + 1 == MAX_SIZE)
/* обработка ошибки - переполнение очереди */
a[size++] = Elem(value, priority);
up(size - 1);
}
Elementni o’chirishda quyidagicha yo’l tutish mumkin: piramidaning uchiga eng so’nggi elementni joylashtirish va uchun down() amalaini bajarish. O’chirishning murakkabligi O(logN) ga teng.
void enqueue(int value, int priority) {
if (size + 1 == MAX_SIZE)
/* обработка ошибки - переполнение очереди */
a[size++] = Elem(value, priority);
up(size - 1);
}
Quyida ustuvor navbatning qo’llanilishi bo’yicha to’liq kod keltirilgan. Navbat elementlarining oshib ketish va bo’sh navbatdan element yechib olishga urunishlar assert (/ yoki sarlavha fayli) konstruksiyasi yordamida qilinadi.
class PriorityQueue {
static const int MAX_SIZE = 100;
struct Elem {
int val;
int priority;
Elem(int v = 0, int p = 0) {
val = v;
priority = p;
}
} a[MAX_SIZE];
int size;
void up(int i) {
while (i != 0 && a[i].priority > a[(i - 1) / 2].priority) {
swap(a[i], a[(i - 1) / 2]);
i = (i - 1) / 2;
}
}
void down(int i) {
while (i < size / 2) {
int maxI = 2 * i + 1;
if (2 * i + 2 < size && a[2 * i + 2].priority > a[2 * i + 1].priority)
maxI = 2 * i + 2;
if (a[i].priority >= a[maxI].priority)
return;
swap(a[i], a[maxI]);
i = maxI;
}
}
public:
PriorityQueue() {
size = 0;
}
void enqueue(int value, int priority) {
assert(size + 1 < MAX_SIZE);
a[size++] = Elem(value, priority);
up(size - 1);
}
int dequeue() {
assert(size > 0);
swap(a[0], a[--size]);
down(0);
return a[size];
}
bool isEmpty() {
return size == 0;
}
};
Quyida mavjud algoritmlarning asimptotik tahlilini jadvallar bilan ko’rib chiqamiz. Bunda:
Saralash algoritmlari tahlili:
Do'stlaringiz bilan baham: |