C 插入双链表的优先级队列

C 插入双链表的优先级队列,c,priority-queue,doubly-linked-list,C,Priority Queue,Doubly Linked List,我正在使用双链接列表实现优先级队列等待列表。我的方法创建一个新节点(优先级和学生id)。根据节点优先级,该方法将节点排序到队列中 what I get is what I should get Waitlisted: 109 in 2123 | Waitlisted: 109 in 2123 Current waitlist: 109

我正在使用双链接列表实现优先级队列等待列表。我的方法创建一个新节点(优先级和学生id)。根据节点优先级,该方法将节点排序到队列中

what I get is                                what I should get

Waitlisted:             109 in 2123      |   Waitlisted:             109 in 2123
Current waitlist:       109              |   Current waitlist:       109
                                         |
Waitlisted:             105 in 2123      |   Waitlisted:             105 in 2123
Current waitlist:       105              |   Current waitlist:       105 109
                                         |
Waitlisted:             108 in 2123      |   Waitlisted:             108 in 2123
Current waitlist:       109 105          |   Current waitlist:       105 108 109
                                         |
Waitlisted:             106 in 2123      |   Waitlisted:             106 in 2123
Current waitlist:       106              |   Current waitlist:       105 106 108 109
                                         |
Waitlisted:             107 in 2123      |   Waitlisted:             107 in 2123
Current waitlist:       109 106          |   Current waitlist:       105 106 107 108 109
当队列在第一个循环中为空时,我可以插入一个新节点。从第二次运行开始,队列的返回值错误

代码


我已经设法修复了一些代码,但我仍然卡住了。

正如BLUEPIXY所提到的,函数的最后一点有点错误(//编辑您在此期间更改了代码,我指的是您的原始代码)。当您在
while
块中浏览列表,然后您意识到
curr
是尾部,您无法检查您是否到达了那里,因为
temp
的优先级大于尾部,或者您已经到达列表的末尾,并且
temp
应该成为新的尾部

另外,您插入的最后一个零件
temp
位于错误的一侧

代码的最后一部分应该是这样的

//编辑发布整个代码,我只更改了函数的最后一部分,以及
排队
的参数,编写测试代码要容易得多

void print_queue(PQNode *queue)
{
    if(queue == NULL)
    {
        puts("empty queue");
        return;
    }

    for(;;)
    {
        printf("%d (priority %d)", queue->info.iStudentID, queue->info.iPriority);
        queue = queue->pNext;

        if(queue == NULL)
        {
            puts("");
            return;
        }

        printf(" <--> ");
    }
}


void enqueue( PQNode** ppFront, int id, int prio ){
    /* create a new node to store the info */
    PQNode *temp = (PQNode*)malloc(sizeof(PQNode)); //create a new node to store the info
    temp->info.iStudentID = id;
    temp->info.iPriority = prio;
    temp->pNext = NULL;
    temp->pPrev = NULL;
    PQNode *curr = *ppFront;


    /* check if the LL is empty and add the new node to the front if it is */
    if(curr == NULL){
        *ppFront = temp;
        return;
    }

    /* check if the new node should come before the first node in the LL */
    if(temp->info.iPriority > curr->info.iPriority){
        temp->pNext = *ppFront;
        (*ppFront)->pPrev = temp;
        *ppFront = temp;
        return;
    }   

    /* walk back through the previous nodes in the LL until the correct insertion point is found */
    /* remember to also check whether the previous node is NULL */
    while(curr->pNext != NULL && temp->info.iPriority <= curr->info.iPriority){
        curr = curr->pNext;
    }



    /* insert the new node into the place you found with your loop */
    /* note you may need a special case for when the previous node is NULL */
    if(curr->pNext == NULL){
        // we don't know whether the while stopped because it reached the
        // final node or the priority was greater, we have to check it
        if(temp->info.iPriority <= curr->info.iPriority)
        {
            // the priority is smaller, temp should be the tail
            curr->pNext = temp;
            temp->pPrev = curr;
            return;
        } else {
            // the priority is bigger, curr should the the tail
            // this case is handled by the next section
        }
    }

    temp->pPrev = curr->pPrev;
    temp->pNext = curr;
    curr->pPrev->pNext = temp;
    curr->pPrev = temp;
}

int main(void)
{
    PQNode *queue = NULL;

    enqueue(&queue, 109, 10);
    enqueue(&queue, 105, 40);
    enqueue(&queue, 108, 20);
    enqueue(&queue, 110, 30);
    enqueue(&queue, 911, 11);
    enqueue(&queue, 219, 25);

    print_queue(queue);

    return 0;
}
void打印队列(PQNode*队列)
{
if(队列==NULL)
{
放置(“空队列”);
回来
}
对于(;;)
{
printf(“%d(优先级%d)”,queue->info.iStudentID,queue->info.iPriority);
queue=queue->pNext;
if(队列==NULL)
{
认沽权(“”);
回来
}
printf(“”);
}
}
无效排队(PQNode**ppFront,int-id,int-prio){
/*创建一个新节点来存储信息*/
PQNode*temp=(PQNode*)malloc(sizeof(PQNode));//创建一个新节点来存储信息
temp->info.iStudentID=id;
temp->info.iPriority=prio;
temp->pNext=NULL;
temp->pPrev=NULL;
PQNode*curr=*ppFront;
/*检查LL是否为空,如果为空,则将新节点添加到前面*/
if(curr==NULL){
*ppFront=温度;
回来
}
/*检查新节点是否应位于LL中的第一个节点之前*/
如果(临时->信息优先权>当前->信息优先权){
temp->pNext=*ppFront;
(*ppFront)->pPrev=温度;
*ppFront=温度;
回来
}   
/*返回LL中以前的节点,直到找到正确的插入点*/
/*记住还要检查前一个节点是否为空*/
while(curr->pNext!=NULL&&temp->info.iPriority info.iPriority){
curr=curr->pNext;
}
/*将新节点插入到使用循环找到的位置*/
/*注意:当上一个节点为空时,可能需要一个特殊情况*/
如果(curr->pNext==NULL){
//我们不知道while是否因为到达目的地而停止
//最终节点或优先级更高,我们必须检查它
如果(临时->info.iPriority info.iPriority)
{
//优先级较小,temp应该是尾部
curr->pNext=温度;
温度->pPrev=电流;
回来
}否则{
//优先级越高,curr应该是尾部
//本案由下一节处理
}
}
临时->pPrev=当前->pPrev;
温度->pNext=电流;
当前->pPrev->pNext=温度;
电流->pPrev=温度;
}
内部主(空)
{
PQNode*队列=NULL;
排队(&queue,109,10);
排队(&queue,105,40);
排队(和排队,108,20);
排队(&queue,110,30);
排队(排队,911,11);
排队(&排队,219,25);
打印队列(队列);
返回0;
}
我明白了

105(优先级40)110(优先级30)219(优先级25)108(优先级20)911(优先级11)109(优先级10)

排队逻辑中有一个错误,但假定显示函数中有一个与之无关的错误。当出现类似情况时,将内容分解为较小的函数可以帮助您调试逻辑。例如,当我处理双链接列表时,我倾向于依赖一组
connect(prev,current,next)
disconnect(prev,next)
函数,因为在处理空列表、空prev/next指针等时,逻辑可能会混淆。同样,查找插入点也可以放在自己的函数中。举个例子来说明我在说什么。要查看的主要函数是
FindPriorityEnd
Enqueue
.hmm,这很有意义。我甚至没有意识到我在最后把温度放在了错误的一边。我单独尝试了这个,效果很好,但是当我在我的程序中尝试它时,结果是不同的,我想我必须处理我的其他函数。至少我现在知道错误不在这里。BLUEPIXY提到,您的显示例程中可能也有错误。确保您的显示例程工作正常。您也可以尝试为此使用调试器。
typedef struct{
    int iPriority;          /* Priority of the student to be enrolled */
    int iStudentID;         /* ID of the student */
} WaitlistEntry;

typedef struct PQNode {
    WaitlistEntry info;     /* WaitlistEntry stored in the node (sorted with largest priority first) */
    struct PQNode* pNext;   /* Pointer to next node in the LL */
    struct PQNode* pPrev;   /* Pointer to previous node in the LL */
} PQNode;

typedef struct{
    int iCourseNumber;      /* Course number of the course */
    int* iStudentIDs;       /* Array of IDs of students enrolled in the course */
    int iNumEnrolled;       /* Number of Students currently enrolled in course */
    int iMaxEnrolled;       /* Max number of Students that can enroll in the course */
    PQNode* pFront;         /* Priority queue representing the waitlist for the course */
} Course;
void print_queue(PQNode *queue)
{
    if(queue == NULL)
    {
        puts("empty queue");
        return;
    }

    for(;;)
    {
        printf("%d (priority %d)", queue->info.iStudentID, queue->info.iPriority);
        queue = queue->pNext;

        if(queue == NULL)
        {
            puts("");
            return;
        }

        printf(" <--> ");
    }
}


void enqueue( PQNode** ppFront, int id, int prio ){
    /* create a new node to store the info */
    PQNode *temp = (PQNode*)malloc(sizeof(PQNode)); //create a new node to store the info
    temp->info.iStudentID = id;
    temp->info.iPriority = prio;
    temp->pNext = NULL;
    temp->pPrev = NULL;
    PQNode *curr = *ppFront;


    /* check if the LL is empty and add the new node to the front if it is */
    if(curr == NULL){
        *ppFront = temp;
        return;
    }

    /* check if the new node should come before the first node in the LL */
    if(temp->info.iPriority > curr->info.iPriority){
        temp->pNext = *ppFront;
        (*ppFront)->pPrev = temp;
        *ppFront = temp;
        return;
    }   

    /* walk back through the previous nodes in the LL until the correct insertion point is found */
    /* remember to also check whether the previous node is NULL */
    while(curr->pNext != NULL && temp->info.iPriority <= curr->info.iPriority){
        curr = curr->pNext;
    }



    /* insert the new node into the place you found with your loop */
    /* note you may need a special case for when the previous node is NULL */
    if(curr->pNext == NULL){
        // we don't know whether the while stopped because it reached the
        // final node or the priority was greater, we have to check it
        if(temp->info.iPriority <= curr->info.iPriority)
        {
            // the priority is smaller, temp should be the tail
            curr->pNext = temp;
            temp->pPrev = curr;
            return;
        } else {
            // the priority is bigger, curr should the the tail
            // this case is handled by the next section
        }
    }

    temp->pPrev = curr->pPrev;
    temp->pNext = curr;
    curr->pPrev->pNext = temp;
    curr->pPrev = temp;
}

int main(void)
{
    PQNode *queue = NULL;

    enqueue(&queue, 109, 10);
    enqueue(&queue, 105, 40);
    enqueue(&queue, 108, 20);
    enqueue(&queue, 110, 30);
    enqueue(&queue, 911, 11);
    enqueue(&queue, 219, 25);

    print_queue(queue);

    return 0;
}
105 (priority 40) <--> 110 (priority 30) <--> 219 (priority 25) <--> 108 (priority 20) <--> 911 (priority 11) <--> 109 (priority 10)