我很难理解为什么这种排序功能不起作用。它确实将节点放入排序顺序,但第一个节点总是在进程中丢失。这是我的代码(head
变量是全局的):
void medianscore() {
int i, j=0;
int counter=0;
struct student *curr=head;
struct student *trail=head;
struct student *temp=NULL;
while (curr !=NULL)
{
curr=curr->next; //couting the number of items I have in my list.
counter++; //this works fine.
}
curr=head->next; // reseting the curr value for the 2nd position.
for (i=0; i<counter; i++)
{
while (curr != NULL)
{
if (trail->grade > curr->grade)
{
temp=curr->next; //bubble sort for the pointers.
curr->next=trail;
trail->next=temp;
temp=curr; //reseting trail and curr. curr gets back to be infront.
curr=trail;
trail=temp;
if (j==0) //i'm using j to determine the start of the loop so i won't loose the head pointer.
{
head=trail;
}
}
j++;
trail=curr;
curr=curr->next; //traversing thru the list. nested loop.
}
trail=head;
curr=trail->next;
curr->next=trail->next->next; //traversing thru the list. outer loop.
j=0;
}
}
我做错了什么?
答案 0 :(得分:0)
您的节点计数和使用变量i
和j
来控制排序具有错误的代码味道。这些不应该是必要的。
我稍后会解决j
和您的列表处理问题。对于i
之外的外环,您可以为外循环的每次迭代维护一个标志,以便在该迭代结束时确定是否进行了交换。如果不是,那么就不需要执行另一次迭代。这种方法永远不会比现有技术执行更多的迭代,对于大多数输入,它将执行更少的。
但是,我在代码中看到的主要问题是它没有正确执行节点交换。假设你从这种情况开始......
prev --> trail --> curr --> Z
....你问的问题是{必须交换trail
和curr
,并假设你确定它们必须是。{1}}和trail
。在这种情况下,您更新了next
的{{1}}指针和curr
,而不是prev
,最后是链接看起来像这样:
prev ----V
trail --> Z
curr ----^
此时,curr
实际上已经丢失了 - 从列表头到Z
的链接链不再通过它,你没有其他任何东西修复它。
我想你可能最终遇到了这个问题,部分原因是你的头部节点是一个特殊情况,因为没有任何东西链接到它。但这不是必须的。在不改变代码中其他地方如何使用链接列表的情况下,您可以创建一个指向头部的medianscore()
本地虚拟节点:
struct student dummy;
dummy->next = head;
然后,您可以使用...
开始外循环的每次迭代trail = &dummy;
...并在内循环测试中trail->next
是否应与trail->next->next
交换。当然,你的循环终止条件和交换需要稍微不同,但是你需要总是有一个指向交换对的第一个节点之前的节点的指针,因为这提供了,所以你可以更新它的{{1指针。
这样做有另一个好处:头节点不再需要在排序循环中进行任何特殊处理。相反,最后您只需设置next
。