|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 pyzyd 于 2025-10-9 15:49 编辑
堆有最大堆和最小堆,
堆是完全二叉树,
要求:
1.每个父节点大于(或小于)等于其子节点,左右子节点没有大小要求
2.堆最多只能有一个单个的左子节点,不能有多个结点,不能是单个的右子节点
- 90
- / \
- 70 80
- / \ / \
- 60 20 75 50
- 这就是一个最大堆
- 错误示例
- 1
- / \
- 2 3
- / /
复制代码
堆的代码实现
- /*
- 堆是特殊的树,
- 堆是完全二叉树,
- 堆中每一个节点的值都大于或等于其左右孩子节点的值,称为大顶堆(最大堆);
- 堆中每一个节点的值都小于或等于其左右孩子节点的值,称为小顶堆(最小堆)。
- 堆可以用数组表示,数组中第i个元素,其左孩子为2i+1,右孩子为2i+2。
- */
- #include <cstring>
- #include <iomanip>
- #include <iostream>
- #include <string>
- #include <cmath>
- #define DEFAULT_CAPCITY 128
- typedef int DataType;
- typedef struct _Heap {
- DataType *data;
- int size;
- int capacity;
- } Heap;
- bool initHeap(Heap &heap, int *original, int size);
- bool insert(Heap &heap, DataType value);
- static void buildHeap(Heap &heap);
- static void adjustDown(Heap &heap, int index);
- static void adjustUp(Heap &heap, int index);
- int main() {
- Heap hp;
- int origVals[] = {1, 2, 3, 87, 93, 82, 92, 86, 95};
- if (!initHeap(hp, origVals, sizeof(origVals) / sizeof(origVals[0]))) {
- std::cerr << "init heap failed!" << std::endl;
- return -1;
- }
- if (typeid(1.0) == typeid(float)) {
- std::cout << "1.0 is float" << std::endl;
- } else {
- std::cout << "1.0 is double" << std::endl;
- }
- insert(hp, 100);
- return 0;
- }
- bool initHeap(Heap &heap, int *original, int size) {
- if (original == nullptr || size <= 0) {
- return false;
- }
- heap.capacity = DEFAULT_CAPCITY > size ? DEFAULT_CAPCITY : size;
- heap.data = new DataType[heap.capacity];
- if (!heap.data) {
- return false;
- }
- memcpy(heap.data, original, size * sizeof(int));
- heap.size = size;
- buildHeap(heap);
- return true;
- }
- bool insert(Heap &heap, DataType value) {
- if (heap.size == heap.capacity) {
- return false;
- }
- int index = heap.size++;
- heap.data[index] = value;
- adjustUp(heap, index);
- return true;
- }
- /*
- 从最后一个非叶子结点(父节点 size / 2 - 1
- 的位置)逐个往前调整所有父节点(直到根节点),
- 确保每一个父节点都是一个最大堆,最终整个堆就是一个最大堆。
- */
- static void buildHeap(Heap &heap) {
- int i;
- for (i = heap.size / 2 - 1; i >= 0; i--) {
- adjustDown(heap, i);
- }
- }
- /*
- 将当前节点和子节点调整成最大堆
- */
- static void adjustDown(Heap &heap, int index) {
- int cur = heap.data[index];
- int parent, child;
- for (parent = index; (parent * 2 + 1) < heap.size; parent = child) {
- child = parent * 2 + 1;
- // 比较左子节点和右子节点,取较大的那个
- if ((child + 1) < heap.size &&
- heap.data[child] < heap.data[child + 1]) {
- child++;
- }
- // 如果当前节点大于等于最大子节点,则不需要调整
- if (cur >= heap.data[child]) {
- break;
- } else {
- // 否则,将当前节点和最大子节点交换
- heap.data[parent] = heap.data[child];
- heap.data[child] = cur;
- }
- }
- }
- static void adjustUp(Heap &heap, int index) {
- if (index < 0 || index >= heap.size) {
- return;
- }
- while (index > 0) {
- int parent = (index - 1) / 2;
- if (heap.data[index] <= heap.data[parent]) {
- break;
- }
- // 交换当前节点与父节点
- int temp = heap.data[index];
- heap.data[index] = heap.data[parent];
- heap.data[parent] = temp;
- index = parent;
- }
- }
复制代码
用堆来实现优先队列,利用了堆可以用数组存储的特性
- #include <iostream>
- #include <cstring>
- #include <random>
- #define DEFAULT_CAPACITY 128
- typedef struct _task{
- int priority;
- }Task;
- typedef Task DataType;
- typedef struct _PriorityQueue {
- DataType* data;
- int size;
- int capacity;
- }PriorityQueue;
- bool init(PriorityQueue &pq, DataType *original, 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 *original, int size) {
- if (!original || size <= 0) {
- return false;
- }
- pq.capacity = size > DEFAULT_CAPACITY ? size : DEFAULT_CAPACITY;
- pq.data = new DataType[pq.capacity];
- // // 第一种初始化方式
- // memcpy(pq.data, original, size * sizeof(DataType));
- // pq.size = size;
- // build(pq);
- // 第二种初始化方式
- pq.size = 0;
- for (int i = 0; i < size; i++) {
- push(pq, original[i]);
- }
- return true;
- }
- static void build(PriorityQueue &pq) {
- for (int i = pq.size / 2 - 1; i >= 0; i--) {
- adjustDown(pq, i);
- }
- }
- static void adjustDown(PriorityQueue &pq, int index) {
- DataType cur = pq.data[index];
- int parent = index;
- int child;
- //从当前的节点开始,向下调整子节点及子节点的子节点使数组满足堆的特性
- while (parent * 2 + 1 < pq.size) {
- child = parent * 2 + 1;
- if (child + 1 < pq.size && pq.data[child].priority < pq.data[child + 1].priority) {
- child++;
- }
- if (pq.data[child].priority > cur.priority) {
- pq.data[parent] = pq.data[child]; // 子节点上移
- parent = child;
- } else {
- break;
- }
- }
- pq.data[parent] = cur;
- }
- bool push(PriorityQueue &pq, DataType value) {
- if (isFull(pq)) {
- return false;
- }
- pq.data[pq.size++] = value;
- adjustUp(pq, pq.size - 1);
- return true;
- }
- bool isFull(PriorityQueue &pq) {
- return pq.size == pq.capacity;
- }
- bool isEmpty(PriorityQueue &pq) {
- return pq.size == 0;
- }
- static void adjustUp(PriorityQueue &pq, int index) {
- DataType cur = pq.data[index];
- int child, parent;
- for (child = index; child > 0; child = parent) {
- parent = (child - 1) / 2;
- if (pq.data[parent].priority < cur.priority) {
- pq.data[child] = pq.data[parent];
- pq.data[parent] = cur;
- } else {
- break;
- }
- }
- }
- bool pop(PriorityQueue &pq, DataType &value) {
- if (isEmpty(pq)) {
- return false;
- }
- value = pq.data[0];
- pq.data[0] = pq.data[--pq.size];
- adjustDown(pq, 0);
- return true;
- }
- void destroy(PriorityQueue &pq) {
- delete[] pq.data;
- pq.data = nullptr;
- pq.size = pq.capacity = 0;
- }
- int main()
- {
- std::mt19937 gen(time(0)); // random device
- std::uniform_int_distribution<int> dis(0, 9);
- PriorityQueue pq;
- Task tasks[7];
- for (int i = 0; i < 7; i++) {
- tasks[i].priority = dis(gen);
- }
- if (!init(pq, tasks, sizeof(tasks) / sizeof(Task))) {
- std::cerr << "init failed" << std::endl;
- return -1;
- }
- std::cout << "Tasks priority:" <<std::endl;
- for (int i = 0; i < pq.size; i++){
- std::cout << tasks[i].priority << " ";
- }
- std::cout << std::endl;
- std::cout << "Priority queue:" << std::endl;
- for (int i = 0; i < pq.size; i++){
- std::cout << pq.data[i].priority << " ";
- }
- std::cout << std::endl;
- push(pq, (Task){100});
- std::cout << "Priority queue after push:" << std::endl;
- for (int i = 0; i < pq.size; i++){
- std::cout << pq.data[i].priority << " ";
- }
- std::cout << std::endl;
- return 0;
- }
复制代码
|
|