在C问题中将相同优先级的项目添加到优先级队列中

Posted

技术标签:

【中文标题】在C问题中将相同优先级的项目添加到优先级队列中【英文标题】:Adding same priority items to a priority queue in C problem 【发布时间】:2019-12-03 16:48:36 【问题描述】:

我用 C 语言编写了一个优先级队列,它通过使用优先级来接受航班的乘客信息。有三个主要的机票舱位(商务舱、经济舱、标准舱),商务舱有一个特殊舱位,即“外交官”,经济舱也有“老兵”舱位。以下是输入信息列表,括号中是相应的优先级:

输入: bus_1(1)、eco_1(3)、bus_2(1)、eco_2(3)、std_1(4)、eco_3(3)、eco_4(3)、bus_3(0 )、bus_4(1)、eco_6(2)、eco_7(2)

输出: bus_3、bus_1、bus_4、bus_2、eco_7、eco_6、eco_4、eco_3、eco_2、eco_1、std_1

应该是什么: bus_3、bus_1、bus_2、bus_4、eco_6、eco_7、eco_1、eco_2、eco_3、eco_4、std_1

0 是最高优先级,4 是最低优先级。我知道我的代码不正确,但我无法找出正确的方法来编写算法以将相同的优先级项目推送到已经在队列中的项目之后。这是我的功能:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

enum classes

    business,
    economy,
    standard
;

struct flight

    char flightName[8];

    //for priority queue
    struct queueNode *rootNode;
    int hasRoot;
    int businessQueueCount, economyQueueCount, standardQueueCount;
    int totalPassengerCount;

;

struct passenger

    char passengerName[15];
    char flightName[8];
;

struct queueNode

    struct passenger passenger;
    int priority;
    struct queueNode *next;
;

struct queueNode *newQueueNode(char flightName[8], char passengerName[15], int priority)

    struct queueNode *temp = malloc(sizeof(struct queueNode));
    temp->priority = priority;
    temp->next = NULL;
    strcpy(temp->passenger.flightName, flightName);
    strcpy(temp->passenger.passengerName, passengerName);

    return temp;



void pushQueue(struct queueNode **head, char *flightName, char *passengerName, int priority)

    struct queueNode *start = (*head);

    struct queueNode *temp = newQueueNode(flightName, passengerName, priority);

    if ((*head)->priority > priority)
    
        temp->next = *head;
        (*head) = temp;
    
    else
    
        if (start->next != NULL && start->next->priority == priority)
        
            temp->next = start->next->next;
            start->next->next = temp;
        
        else
        
            while (start->next != NULL && start->next->priority < priority)
            
                start = start->next;
            

            temp->next = start->next;
            start->next = temp;
        
    


struct passenger peekQueue(struct queueNode **head)

    return (*head)->passenger;


void popQueue(struct queueNode **head)

    struct queueNode *temp = *head;
    (*head) = (*head)->next;
    free(temp);


int main()

    struct flight flight_temp;
    strcpy(flight_temp.flightName, "flight1");

    flight_temp.rootNode = newQueueNode(flight_temp.flightName, "bus_1", 1);
    pushQueue(&(flight_temp.rootNode), flight_temp.flightName, "eco_1", 3);
    pushQueue(&(flight_temp.rootNode), flight_temp.flightName, "bus_2", 1);
    pushQueue(&(flight_temp.rootNode), flight_temp.flightName, "std_1", 4);
    pushQueue(&(flight_temp.rootNode), flight_temp.flightName, "eco_3", 3);
    pushQueue(&(flight_temp.rootNode), flight_temp.flightName, "bus_3", 0);
    pushQueue(&(flight_temp.rootNode), flight_temp.flightName, "bus_4", 1);
    pushQueue(&(flight_temp.rootNode), flight_temp.flightName, "eco_4", 3);

    for (size_t i = 0; i < 6; i++)
    
        printf("%s\n", peekQueue(&(flight_temp.rootNode)).passengerName);
        popQueue(&(flight_temp.rootNode));
    







提前感谢您的帮助。

【问题讨论】:

这能回答你的问题吗? C++ priority queue does not respect FIFO order 您的队列代码似乎部分基于相同优先级的 LIFO(而您所需的输出似乎需要基于 FIFO 以匹配优先级)。很难说没有实际显示您的优先级计算的minimal reproducible example(必须有一些东西somewhere为每个给定的类和优先级调整priority,但你没有在这里显示它) .把一个 mcve 放在一起,我们可能可以解决这个问题。无论如何,是时候启动调试器并开始单步执行了。使用minimal reproducible example 更新您的代码,包括输入格式的输入数据、插入等。 @Klaus 感谢您的回答。据我从您推荐的那个问题中了解到,我必须添加另一个功能来做我想做的事。但是我不知道该怎么做,因为我没有任何时间戳等。对我来说最好的解决方案是在不添加其他区域的情况下保持与 FIFO 相同的优先级。 @WhozCraig 我准备好了你问的,我应该直接将我的问题添加为代码吗? 我很确定您需要做的就是将while (start-&gt;next != NULL &amp;&amp; start-&gt;next-&gt;priority &lt; priority) 中的&lt; 更改为&lt;= 【参考方案1】:

本质上,您的pushQueue 函数正在尝试插入一个排序列表,确保如果一个相等的项目已经存在,那么新的项目会在它之后。但是你的代码中有几个问题会导致它失败。我在您的代码中添加了一些 cmets,以向您显示错误所在。

void pushQueue(struct queueNode **head, char *flightName, char *passengerName, int priority)

    struct queueNode *start = (*head);

    struct queueNode *temp = newQueueNode(flightName, passengerName, priority);

    if ((*head)->priority > priority)
    
        temp->next = *head;
        (*head) = temp;
        // if you put a return statement here, then you can get rid of
        // the else. It reduces nesting and makes your code cleaner.
    
    else
    
        // If the new item has the same priority as what's already in the list,
        // then you insert the new item right after it. What if there were two
        // or more items with the same priority? The new one wouldn't go
        // to the end of the list.
        // This code really is just a broken special case for the else below.
        if (start->next != NULL && start->next->priority == priority)
        
            temp->next = start->next->next;
            start->next->next = temp;
        
        else
        
            // You want to insert the new item after any existing items that
            // have the same priority. But your logic will stop when it finds
            // the first node that has the same priority. So the new item
            // gets inserted at the front. You need to change '<' to '<='
            while (start->next != NULL && start->next->priority < priority)
            
                start = start->next;
            

            temp->next = start->next;
            start->next = temp;
        
    

您可以通过组合案例来大大简化您的代码。并且还要避免像start-&gt;next-&gt;next 这样难以推理且容易出错的令人费解的表达式,从而导致尝试取消引用 NULL 指针。

void pushQueue(struct queueNode **head, char *flightName, char *passengerName, int priority)

    struct queueNode *currentNode = (*head);
    struct queueNode *nextNode;

    struct queueNode *newNode = newQueueNode(flightName, passengerName, priority);

    // if the new node's priority is less than the head node's priority,
    // then the new node becomes the head.    
    if ((*head)->priority > priority)
    
        newNode->next = *head;
        (*head) = newNode;
        return;
    

    // Traverse the list looking for the first node whose priority
    // is greater than the new node's priority.
    nextNode = currentNode->next;
    while (nextNode != NULL && nextNode->priority <= priority)
    
        currentNode = nextNode;
        nextNode = currentNode->next;
    
    // at this point, you want to insert your new node between
    // currentNode and nextNode
    currentNode->next = newNode;
    newNode->next = nextNode;

当然,你会想要测试它。我并没有真正改变你的算法:只是将你的两种特殊情况合二为一。

【讨论】:

以上是关于在C问题中将相同优先级的项目添加到优先级队列中的主要内容,如果未能解决你的问题,请参考以下文章

将多个项目添加到具有固定大小数组的优先级队列时出错

swift中的优先队列

队列和广度优先搜索

将键和值添加到优先级队列中并在 Java 中按键排序

C/C++优先级队列

如何生成随机数并将它们插入优先级队列?