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