C 语言实现的优先级队列

news2024/11/25 10:25:17

C 语言实现的优先级队列

priorityqueue.h

/*******************************************************************************
* Copyright © 2024-2025 Light Zhang <mapaware@hotmail.com>, MapAware, Inc.     *
* ALL RIGHTS RESERVED.                                                         *
*                                                                              *
* PERMISSION IS HEREBY GRANTED, FREE OF CHARGE, TO ANY PERSON OR ORGANIZATION  *
* OBTAINING A COPY OF THE SOFTWARE COVERED BY THIS LICENSE TO USE, REPRODUCE,  *
* DISPLAY, DISTRIBUTE, EXECUTE, AND TRANSMIT THE SOFTWARE, AND TO PREPARE      *
* DERIVATIVE WORKS OF THE SOFTWARE, AND TO PERMIT THIRD - PARTIES TO WHOM THE  *
* SOFTWARE IS FURNISHED TO DO SO, ALL SUBJECT TO THE FOLLOWING :               *
*                                                                              *
* THE COPYRIGHT NOTICES IN THE SOFTWARE AND THIS ENTIRE STATEMENT, INCLUDING   *
* THE ABOVE LICENSE GRANT, THIS RESTRICTION AND THE FOLLOWING DISCLAIMER, MUST *
* BE INCLUDED IN ALL COPIES OF THE SOFTWARE, IN WHOLE OR IN PART, AND ALL      *
* DERIVATIVE WORKS OF THE SOFTWARE, UNLESS SUCH COPIES OR DERIVATIVE WORKS ARE *
* SOLELY IN THE FORM OF MACHINE - EXECUTABLE OBJECT CODE GENERATED BY A SOURCE *
* LANGUAGE PROCESSOR.                                                          *
*                                                                              *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR   *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,     *
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON - INFRINGEMENT.IN NO EVENT   *
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE    *
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,  *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER  *
* DEALINGS IN THE SOFTWARE.                                                    *
*******************************************************************************/
/*
** @file priorityqueue.h
** @brief Priority Queue implementation in C
**
** @author mapaware@hotmail.com
** @copyright © 2024-2030 mapaware.top All Rights Reserved.
** @version 1.0.0
**
** @since 2024-11-21 21:54:30
** @date
**
** @note
**   see: http://btechsmartclass.com/data_structures/max-heap.html
* 
* Usage:

    // same as: PQueueNew(256, PQMaxHeapComp, PQElemSwap)
    PQueue_t* pq = PQueueNew(256, 0, 0);

    PQueuePush(pq, (PQElem_t)40);
    PQueuePush(pq, (PQElem_t)10);
    PQueuePush(pq, (PQElem_t)60);
    PQueuePush(pq, (PQElem_t)50);
    PQueuePush(pq, (PQElem_t)20);
    PQueuePush(pq, (PQElem_t)20);

    const PQElem_t* elt = PQueueTop(pq);
    printf(">>top=%lld\n", (int64_t)(*elt)); // >>top=60

    PQueuePop(pq, 0);  // drop the toppest element(=60) here
    elt = PQueueTop(pq);
    printf(">>top=%lld\n", (int64_t)(*elt)); // >>top=50

    int64_t n = 50;
    PQueuePop(pq, (const PQElem_t*)&n);    // drop the element(=50) here
    elt = PQueueTop(pq);
    printf(">>top=%lld\n", (int64_t)(*elt)); // >>top=40

    PQueueFree(pq, 0);
* 
*/
#ifndef PRIORITY_QUEUE_H_
#define PRIORITY_QUEUE_H_


#if defined(__cplusplus)
extern "C"
{
#endif

#include <stdio.h>
#include <stdint.h>


typedef void* PQElem_t;


typedef struct
{
    int (*compfunc)(const PQElem_t *, const PQElem_t *);
    void (*swapfunc)(PQElem_t*, PQElem_t*);

    size_t capcity;
    size_t length;
    PQElem_t elems[0];
} PQueue_t;

static void _PQBuildHeap(PQueue_t* pq, ssize_t size, ssize_t i)
{
    if (size > 1) {
        // Find the largest among root, left child and right child
        ssize_t largest = i;
        ssize_t l = 2 * i + 1;
        ssize_t r = 2 * i + 2;

        if (l < size && pq->compfunc(&pq->elems[l], &pq->elems[largest]) > 0) {
            largest = l;
        }
        if (r < size && pq->compfunc(&pq->elems[r], &pq->elems[largest]) > 0) {
            largest = r;
        }

        // Swap and continue heapifying if root is not largest
        if (largest != i) {
            pq->swapfunc(&pq->elems[i], &pq->elems[largest]);
            _PQBuildHeap(pq, size, largest);
        }
    }
}


static int PQMaxHeapComp(const PQElem_t* elt1, const PQElem_t* elt2)
{
    PQElem_t v1 = (PQElem_t)(*elt1);
    PQElem_t v2 = (PQElem_t)(*elt2);
    return (v1 > v2 ? 1 : (v1 < v2 ? -1 : 0));
}

static int PQMinHeapComp(const PQElem_t* elt1, const PQElem_t* elt2)
{
    PQElem_t v1 = (PQElem_t)(*elt1);
    PQElem_t v2 = (PQElem_t)(*elt2);
    return (v1 > v2 ? -1 : (v1 < v2 ? 1 : 0));
}


static void PQElemSwap(PQElem_t * elt1, PQElem_t * elt2)
{
    PQElem_t elt = *elt1;
    *elt1 = *elt2;
    *elt2 = elt;
}


static PQueue_t * PQueueNew(size_t capcity, int (*comp)(const PQElem_t*, const PQElem_t*), void (*swap)(PQElem_t*, PQElem_t*))
{
    PQueue_t * pq = (PQueue_t *) malloc(sizeof(PQueue_t) + sizeof(PQElem_t) * capcity);
    if (pq) {
        pq->capcity = capcity;
        pq->length = 0;
        pq->compfunc = comp? comp: PQMaxHeapComp;
        pq->swapfunc = swap? swap: PQElemSwap;
    }
    return pq;
}


static const PQElem_t * PQueueTop(const PQueue_t* pq)
{
    if (pq->length) {
        return &pq->elems[0];
    }
    return 0;
}


// Function to insert an element into the tree
static int PQueuePush(PQueue_t* pq, const PQElem_t elt) {
    if (! pq->length) {
        pq->elems[0] = elt;
        pq->length++;
        // success
        return 1;
    }
    else if (pq->length != pq->capcity) {
        pq->elems[pq->length++] = elt;
        for (ssize_t i = pq->length / 2 - 1; i >= 0; i--) {
            _PQBuildHeap(pq, pq->length, i);
        }
        // success
        return 1;
    }
    else {
        // overflow
        return 0;
    }
}


// Function to delete an element from the tree
static PQElem_t * PQueuePop(PQueue_t* pq, const PQElem_t* eltp)
{
    ssize_t i = 0;
    if (eltp) {
        for (; i != pq->length; i++) {
            if (!pq->compfunc(&pq->elems[i], eltp)) {
                break;
            }
        }
    }
    if (i != pq->length) {
        pq->swapfunc(&pq->elems[i], &pq->elems[pq->length - 1]);
        pq->length--;

        for (i = (ssize_t) pq->length / 2 - 1; i >= 0; i--) {
            _PQBuildHeap(pq, pq->length, i);
        }

        return &pq->elems[pq->length];
    }

    // no element pop
    return 0;
}


static void PQueueFree(PQueue_t* pq, void (*elemdtor)(PQElem_t*))
{
    if (pq) {
        if (elemdtor) {
            ssize_t i = 0;
            PQElem_t* elt = pq->elems;
            while (i++ != pq->length) {
                elemdtor(elt++);
            }
        }
        free(pq);
    }
}

#ifdef __cplusplus
}
#endif
#endif /* PRIORITY_QUEUE_H_ */

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2247227.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++设计模式——Singleton单例模式

一、单例模式的定义 单例模式&#xff0c;英文全称Singleton Pattern&#xff0c;是一种创建型设计模式&#xff0c;它保证一个类在程序中仅有一个实例&#xff0c;并对外提供一个访问的该类实例的全局接口。 单例模式通常用于需要控制对象资源的开发场景&#xff0c;一个类…

【Linux系统】—— 基本指令(三)

【Linux系统】—— 基本指令&#xff08;三&#xff09; 1 一切皆文件2 重定向操作2.1 初始重定向2.2 重定向的妙用2.3 追加重定向2.4 输入重定向2.5 一切皆文件与重定向结合 3 Linux 中的文件类型4 日志5 「more」命令6 「less」命令7 「head」与「tail」7.1 查看文件开头和结…

探索 Python 任务自动化的新境界:Invoke 库揭秘

文章目录 探索 Python 任务自动化的新境界&#xff1a;Invoke 库揭秘背景&#xff1a;为何选择 Invoke&#xff1f;什么是 Invoke&#xff1f;如何安装 Invoke&#xff1f;5个简单的库函数使用方法1. 定义任务2. 带参数的任务3. 运行 Shell 命令4. 任务参数化5. 列出任务 场景应…

【C++】list模拟实现(详解)

本篇来详细说一下list的模拟实现&#xff0c;list的大体框架实现会比较简单&#xff0c;难的是list的iterator的实现。我们模拟实现的是带哨兵位头结点的list。 1.准备工作 为了不和C库里面的list冲突&#xff0c;我们在实现的时候用命名空间隔开。 //list.h #pragma once #…

shell脚本(6)

声明&#xff1a;学习视频来自b站up主 泷羽sec&#xff0c;如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 视频地址&#xff1a;shell(6)if条件判断与for循环结构_哔哩哔哩_bilibili 本文主要讲解shell脚本中的if条件判断和for循环结构。 一、if语句 Shell 脚本中的 if 语句…

JavaScript基础 document.write()方法

JavaScript基础 document.write方法 1.简单认识document.write()2.document.write() 的使用 1.简单认识document.write() document.write() 是一种 JavaScript 方法&#xff0c;用于将内容直接写入到 HTML 文档中。它可以用来动态地在页面加载时插入文本、HTML 代码、图片等内…

Linux笔记---进程:进程切换与O(1)调度算法

1. 补充概念 1.1 并行与并发 竞争性&#xff1a;系统进程数目众多&#xff0c;而CPU资源只有少量&#xff0c;甚至只有1个&#xff0c;所以进程之间是具有竞争属性的。为了高效完成任务&#xff0c;更合理竞争相关资源&#xff0c;便具有了优先级。独立性&#xff1a;多进程运…

使用ENSP实现浮动静态路由

一、项目拓扑 二、项目实现 1.路由器AR1配置 进入系统试图 sys将路由器命名为R1 sysname R1关闭信息中心 undo info-center enable 进入g0/0/0接口 int g0/0/0将g0/0/0接口IP地址配置为1.1.1.1/24 ip address 1.1.1.1 24进入g0/0/1接口 int g0/0/1将g0/0/1接口IP地址配置为2.…

GoF设计模式——结构型设计模式分析与应用

文章目录 UML图的结构主要表现为&#xff1a;继承&#xff08;抽象&#xff09;、关联 、组合或聚合 的三种关系。1. 继承&#xff08;抽象&#xff0c;泛化关系&#xff09;2. 关联3. 组合/聚合各种可能的配合&#xff1a;1. 关联后抽象2. 关联的集合3. 组合接口4. 递归聚合接…

【论文复现】深度知识追踪

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀ 深度知识追踪 1. 论文概述2. 论文方法3. 实验部分3.1 数据集3.2 实验步骤3.3 实验结果 4 关键代码 1. 论文概述 知识追踪的任务是对学生的知…

Linux: 进程地址空间(理解虚拟地址和页表)

目录 1. 虚拟地址 2. 进程地址空间分布 3. 描述进程地址空间 4. 内存管理——页表 5. 父子进程的虚拟地址关系 6. 页表标记位 6.1 读写权限 6.2 命中权限 7.为什么存在进程地址空间 1. 虚拟地址 #include <stdio.h> #include <unistd.h> #include <sy…

C语言:深入理解指针

一.内存和地址 我们知道计算机上CPU&#xff08;中央处理器&#xff09;在处理数据的时候&#xff0c;需要的数据是在内存中读取的&#xff0c;处理后的数据也会放回内存中&#xff0c;那我们买电脑的时候&#xff0c;电脑上内存是 8GB/16GB/32GB 等&#xff0c;那这些内存空间…

transformer.js(一):这个前端大模型运行框架的可运行环境、使用方式、代码示例以及适合与不适合的场景

随着大模型的广泛应用&#xff0c;越来越多的开发者希望在前端直接运行机器学习模型&#xff0c;从而减少对后端的依赖&#xff0c;并提升用户体验。Transformer.js 是一个专为前端环境设计的框架&#xff0c;它支持运行基于 Transformer 架构的深度学习模型&#xff0c;尤其是…

uni-app 发布媒介功能(自由选择媒介类型的内容) 设计

1.首先明确需求 我想做一个可以选择媒介的内容&#xff0c;来进行发布媒介的功能 &#xff08;媒介包含&#xff1a;图片、文本、视频&#xff09; 2.原型设计 发布-编辑界面 通过点击下方的加号&#xff0c;可以自由选择添加的媒介类型 但是因为预览中无法看到视频的效果&…

行业分析---2024年小鹏汽车AI Day及三季度财报

1 背景 在之前的博客中&#xff0c;笔者撰写了多篇行业类分析的文章&#xff08;科技新能源&#xff09;&#xff1a; 《行业分析---我眼中的Apple Inc.》 《行业分析---马斯克的Tesla》 《行业分析---造车新势力之蔚来汽车》 《行业分析---造车新势力之小鹏汽车》 《行业分析-…

数据可视化复习1-Matplotlib简介属性和创建子图

1.Matplotlib简介 Matplotlib是一个Python的2D绘图库&#xff0c;它可以在各种平台上以各种硬拷贝格式和交互环境生成具有出版品质的图形。通过Matplotlib&#xff0c;开发者可以仅需要几行代码&#xff0c;便可以生成绘图、直方图、功率谱、条形图、错误图、散点图等。 以下…

WebStorm 2024.3/IntelliJ IDEA 2024.3出现elementUI提示未知 HTML 标记、组件引用爆红等问题处理

WebStorm 2024.3/IntelliJ IDEA 2024.3出现elementUI提示未知 HTML 标记、组件引用爆红等问题处理 1. 标题识别elementUI组件爆红 这个原因是&#xff1a; 在官网说明里&#xff0c;才版本2024.1开始&#xff0c;默认启用的 Vue Language Server&#xff0c;但是在 Vue 2 项目…

如何安全删除 Linux 用户帐户和主目录 ?

Linux 以其健壮性和灵活性而闻名&#xff0c;是全球服务器和桌面的首选。管理用户帐户是系统管理的一个基本方面&#xff0c;包括创建、修改和删除用户帐户及其相关数据。本指南全面概述了如何在 Linux 中安全地删除用户帐户及其主目录&#xff0c;以确保系统的安全性和完整性。…

如何利用ros搭建虚拟场景通过仿真机器人完成一次简单的SLAM建图、导航规划(超简单)?——学习来源:机器人工匠阿杰

一&#xff1a;什么是SLAM&#xff0c;SLAM和导航规划又有什么关系&#xff1f; SLAM&#xff08;Simultaneous Localization and Mapping&#xff0c;即同时定位与建图&#xff09;是一种在未知或动态环境中自行驶的重要技术。主要通过设备上的传感器&#xff08;如激光雷达、…

shell脚本(完结)

声明&#xff1a;学习视频来自b站up主 泷羽sec&#xff0c;如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 视频地址&#xff1a;shell编程&#xff08;完结&#xff09;_哔哩哔哩_bilibili 本文主要讲解不同shell脚本中的相互调用以及输入输出重定向操作。 一、不同脚本之间…