C++ 数据结构算法 学习笔记(14) - 优先队列

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;
}

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值