C++ 数据结构算法 学习笔记(14) - 优先队列
操作系统内核作业调度是优先队列的一个应用实例,它根据优先级的高低而不是先到先服务的方 式来进行调度:
如果最小键值元素拥有最高的优先级,那么这种优先队列叫作升序优先队列(即总是先删除最小 的元素),类似的,如果最大键值元素拥有最高的优先级,那么这种优先队列叫作降序优先队列 (即总是先删除最大的元素);由于这两种类型是完全对称的,所以只需要关注其中一种,如升 序优先队列.
完整代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEFAULT_CAPCITY 128
typedef int DataType;
#define isLess(a,b) (a<b)
typedef struct _PriorityQueue {
DataType* arr;
int size;
int capacity;
}PriorityQueue;
bool init(PriorityQueue& pq, int* orginal, int size);
bool push(PriorityQueue& pq, DataType value);
bool pop(PriorityQueue& pq, DataType& value);
bool isEmpty(PriorityQueue& pq);
bool isFull(PriorityQueue& pq);
void destroy(PriorityQueue& pq);
static void build(PriorityQueue& pq);
static void adjustDown(PriorityQueue& pq, int index);
static void adjustUp(PriorityQueue& pq, int index);
bool init(PriorityQueue& pq, DataType* orginal, int size) {
int capacity = DEFAULT_CAPCITY > size ? DEFAULT_CAPCITY : size;
pq.arr = new DataType[capacity];
if (!pq.arr) return false;
pq.capacity = capacity;
pq.size = 0;
if (size > 0) {
memcpy(pq.arr, orginal, size * sizeof(int));
pq.size = size;
build(pq);
}
return true;
}
void destroy(PriorityQueue& pq) {
if (pq.arr) delete[] pq.arr;
}
bool isEmpty(PriorityQueue& pq) {
if (pq.size < 1) return true;
return false;
}
bool isFull(PriorityQueue& pq) {
if (pq.size < pq.capacity) return false;
return true;
}
int size(PriorityQueue& pq) {
return pq.size;
}
void build(PriorityQueue& pq) {
int i;
for (i = pq.size / 2 - 1; i >= 0; i--) {
adjustDown(pq, i);
}
}
void adjustDown(PriorityQueue& pq, int index)
{
DataType cur = pq.arr[index];
int parent, child;
for (parent = index; (parent * 2 + 1) < pq.size; parent = child) {
child = parent * 2 + 1;
if (((child + 1) < pq.size) && isLess(pq.arr[child], pq.arr[child
+ 1])) {
child++;
}
if (isLess(pq.arr[child], cur)) {
break;
}
else {
pq.arr[parent] = pq.arr[child];
pq.arr[child] = cur;
}
}
}
void adjustUp(PriorityQueue& pq, int index) {
if (index < 0 || index >= pq.size) {
return;
}
while (index > 0) {
DataType temp = pq.arr[index];
int parent = (index - 1) / 2;
if (parent >= 0) {
if (isLess(pq.arr[parent], temp)) {
pq.arr[index] = pq.arr[parent];
pq.arr[parent] = temp;
index = parent;
}
else {
break;
}
}
else {
break;
}
}
}
bool pop(PriorityQueue& pq, DataType& value) {
if (isEmpty(pq)) return false;
value = pq.arr[0];
pq.arr[0] = pq.arr[--pq.size];
//heap.arr[0] = heap.arr[heap.size-1];
//heap.size--;
adjustDown(pq, 0);
return true;
}
bool push(PriorityQueue& pq, DataType value) {
if (isFull(pq)) {
fprintf(stderr, "The memory for the heap is EMPTY!\n");
return false;
}
int index = pq.size;
pq.arr[pq.size++] = value;
adjustUp(pq, index);
return true;
}
int main(void) {
PriorityQueue pq;
int task[] = { 1, 2, 3, 87, 93, 82, 92, 86, 95 };
int i = 0;
if (!init(pq, task, sizeof(task) / sizeof(task[0]))) {
fprintf(stderr, "Failed to initialized the heap\n");
exit(-1);
}
for (i = 0; i < pq.size; i++) {
printf("the %dth task:%d\n", i, pq.arr[i]);
}
push(pq, 88);
printf("Follow the priority to exit the element from the queue\n");
DataType value;
while (pop(pq, value)) {
printf(" %d\n", value);
}
destroy(pq);
system("pause");
return 0;
}
课后练习
上面优先队列算法实现中的 DataType
如果换成以下类型,上面的代码该如何调整?
typedef struct _Task
{
int priority;
//Ignore other status
}Task;
完整代码
#include <iostream>
#include <cstring>
using namespace std;
#define MAX_SIZE 128
#define IsLess(a,b) ((a)->priority < (b)->priority)
struct Task {
int priority;
};
typedef struct _Heap {
Task** arr; // Pointer to a pointer of Task
int size;
int capacity;
} PriorityQueue;
bool Init_heap(PriorityQueue& heap, Task* original, int size);
bool push_heap(PriorityQueue& heap, Task* element);
bool pop_heap(PriorityQueue& heap, Task*& element);
bool IsEmpty(PriorityQueue& heap);
bool IsFull(PriorityQueue& heap);
bool Destroy_heap(PriorityQueue& heap);
static void built_heap(PriorityQueue& heap);
static void adjust_down(PriorityQueue& heap, int i);
static void adjust_up(PriorityQueue& heap, int i);
bool IsEmpty(PriorityQueue& heap) {
return heap.size <= 0;
}
bool IsFull(PriorityQueue& heap) {
return heap.size >= heap.capacity;
}
bool Destroy_heap(PriorityQueue& heap) {
if (heap.arr) {
for (int i = 0; i < heap.size; i++) {
delete heap.arr[i];
}
delete[] heap.arr;
return true;
}
return false;
}
bool Init_heap(PriorityQueue& heap, int* original, int size) {
if (!original || size <= 0) return false;
int capacity = MAX_SIZE > size ? MAX_SIZE : size;
heap.arr = new Task * [capacity];
if (!heap.arr) return false;
for (int i = 0; i < size; i++)
{
heap.arr[i] = new Task;
heap.arr[i]->priority = original[i];
}
heap.capacity = capacity;
heap.size = size;
built_heap(heap);
return true;
}
void adjust_down(PriorityQueue& heap, int i) {
Task* tmp = heap.arr[i];
int parent, child;
for (parent = i; (parent * 2 + 1) < heap.size; parent = child) {
child = parent * 2 + 1;
if (child + 1 < heap.size && IsLess(heap.arr[child], heap.arr[child + 1])) {
child++;
}
if (!IsLess(heap.arr[child], tmp)) {
heap.arr[parent] = heap.arr[child];
heap.arr[child] = tmp;
}
else {
break;
}
}
}
void built_heap(PriorityQueue& heap) {
for (int i = (heap.size - 2) / 2; i >= 0; i--) {
adjust_down(heap, i);
}
}
void adjust_up(PriorityQueue& heap, int i) {
if (i <= 0 || i >= heap.size) {
return;
}
Task* tmp = heap.arr[i];
int parent = (i - 1) / 2;
while (i > 0 && IsLess(heap.arr[parent], tmp)) {
heap.arr[i] = heap.arr[parent];
i = parent;
parent = (i - 1) / 2;
heap.arr[i] = tmp;
}
}
bool push_heap(PriorityQueue& heap, Task& element) {
if (IsFull(heap)) return false;
heap.arr[heap.size] = new Task;
*heap.arr[heap.size] = element;
adjust_up(heap, heap.size);
heap.size++;
return true;
}
bool pop_heap(PriorityQueue& heap, Task*& element) {
if (IsEmpty(heap)) return false;
element = heap.arr[0];
heap.arr[0] = heap.arr[--heap.size];
adjust_down(heap, 0);
return true;
}
int main() {
PriorityQueue pq;
//Task tasks[] = { {1}, {2}, {3}, {87}, {93}, {82}, {92}, {86}, {95} };
int tasks[] = { 1,2,3,87,93,82,92,86,95 };
int nTasks = sizeof(tasks) / sizeof(tasks[0]);
if (!Init_heap(pq, tasks, nTasks)) {
cerr << "Failed to initialize the heap\n";
exit(-1);
}
cout << "Heap elements by priority:" << endl;
for (int i = 0; i < pq.size; i++) {
cout << "Task " << i << " priority: " << pq.arr[i]->priority << endl;
}
Task newTask = { 88 };
push_heap(pq, newTask);
cout << "Follow the priority to exit the element from the queue" << endl;
Task* value;
while (pop_heap(pq, value)) {
cout << value->priority << endl;
delete value; // Free the memory of the popped element
}
Destroy_heap(pq);
system("pause");
return 0;
}