简体   繁体   English

单链表

[英]Singly Linked List

I have a project from https://hotfile.com/dl/253309046/133284f/4_SinglyLinkedList.rar.html 我有一个来自https://hotfile.com/dl/253309046/133284f/4_SinglyLinkedList.rar.html的项目

The function insertOrdered() inserts scores in order. 函数insertOrdered()按顺序插入分数。

My questions is: can this loop be rewritten without using a "previous" variable? 我的问题是:可以在不使用“上一个”变量的情况下重写此循环吗?

SinglyNode* current = head;
SinglyNode* previous= NULL;
while (current != NULL)
{
    if(newNode->score >= current->score)
        previous = current; 
    else
        break;
    current = current->next;
}

newNode->next   = previous->next;
previous->next  = newNode;  

获取另一个变量(例如x)中先前变量的值(例如p),并使用x代替p。

A simple solution is to first check if it should be inserted before the head. 一个简单的解决方案是首先检查是否应将其插入头部。 If not then use a loop similar to your but compare against current->next (if not NULL ), then when the loop ends the new node should be inserted between current and current->next , ie current is used as previous in the code you have now. 如果不是,则使用类似于您的循环,但将其与current->next比较(如果不是NULL ),则当循环结束时,应在currentcurrent->next之间插入新节点,即current用作代码中的previous你现在有。 If current->next is NULL then insert at end. 如果current->nextNULL则在末尾插入。

Not able to test this, but moving the new node setup code into the if block should allow you to remove the previous variable. 无法对此进行测试,但是将新的节点设置代码移动到if块中应该可以删除以前的变量。

SinglyNode* current = head;
while (current != NULL)
{
    if(newNode->score >= current->score) {
        newNode->next  = current->next;
        current->next  = newNode; 
    }
    else break;
    current     = current->next;
}
if(current == NULL) { // got to end of list
    current->next  = newNode;
    newNode->next  = NULL;
}

This should work: 这应该工作:

SinglyNode* current = head;
if(current == NULL) {
    head = newNode;
}
else if(newNode->score < current->score) {
    newNode->next  = current;
    head  = newNode;  
}
else {
    while (current->next != NULL)
    {
        if(newNode->score < current->next->score)
          break;
        current = current->next;
    }

    newNode->next  = current->next;
    current->next  = newNode;  
}

You cannot eliminate the "previous" variable, but you can disguise it; 您不能消除“上一个”变量,但是可以掩饰它; and furthermore, you can structure the loop so that it is the only iteration variable. 而且,您可以构造循环,使其成为唯一的迭代变量。

Of course to insert the new, you need to update the previous node to point to it. 当然要插入新节点,您需要更新前一个节点以指向它。

You can do that from the current node by looking ahead in the list and handling various cases. 您可以通过在列表中向前看并处理各种情况从当前节点执行此操作。

Another way is to keep a pointer to the pointer field in the previous node. 另一种方法是将指针保留到上一个节点中的指针字段。

node **ppnode;

for (ppnode = &head;
     *ppnode != NULL && (*ppnode)->value >= newnode->value;
     ppnode = &(*ppnode)->next) 
   ; /* empty body */

newnode->next = (*ppnode) ? (*ppnode)->next : NULL;
*ppnode = newnode;

Here, instead of using a current pointer to point to the current, we use a ppnode pointer which points to the current node indirectly. 在这里,我们使用一个ppnode指针间接指向当前节点,而不是使用current指针指向当前节点。 Instead of pointing to that node, it points to the pointer which points to that node (and so it must be suitably typed: it is a pointer to pointer: double star). 它不是指向该节点,而是指向指向该节点的指针(因此必须正确键入:它是指向指针:双星的指针)。

The pointer to the first node is the list head variable, so ppnode points to that head variable initially. 指向第一个节点的指针是列表head变量,因此ppnode最初指向该head变量。 The pointer to every other node after that is the next field of the previous node: each one of these next fields is really like a head of the rest of the list. 指向此后每个其他节点的指针是上一个节点的next字段:这些next字段中的每个字段实际上都像列表其余部分的head So with this one ppnode variable, we keep track of the location within the previous node that must be updated, without keeping track of the previous node itself. 因此,使用这个ppnode变量,我们可以跟踪必须更新的上一个节点中的位置,而不必跟踪上一个节点本身。 And this lets us handle the front of list case where there is no previous node. 这使我们能够处理没有前一个节点的列表开头的情况。

Let's trace through the case that head is null (the list is empty). 让我们追溯一下head为null(列表为空)的情况。

ppnode points to head . ppnode指向head But *ppnode is null, and so the loop body never executes. 但是*ppnode为null,因此循环体从不执行。

Since ppnode points to head , the lines: 由于ppnode指向head ,因此行:

newnode->next = (*ppnode) ? (*ppnode)->next : NULL;
*ppnode = newnode;

have the same meaning as: 具有以下含义:

newnode->next = head ? head->next : NULL;
head = newnode;

The conditional check in these lines handles the case when the new node is added to an empty list or to the tail of a nonempty list. 这些行中的条件检查处理了将新节点添加到空列表或非空列表尾部的情况。 If the list is empty or all the values in it are smaller than the new value, then the loop terminates with ppnode pointing at the list's null terminator, which is head if the list is empty, or else the next field of the tail node. 如果列表为空,或者列表中的所有值都小于新值,则循环终止, ppnode指向列表的空终止符,如果列表为空,则终止符为head ,否则为尾节点的next字段。 Since *ppnode is null, we cannot deference (*ppnode)->next . 由于*ppnode为null,因此我们无法参考(*ppnode)->next There is no next; 没有下一个; the new node is the last node and its next must be nulled. 新节点是最后一个节点, next必须为空。

Now let's look what happens in the case that there is a head node, and its value is greater so that the new node must be inserted at the front. 现在,让我们看一下在存在头节点的情况下会发生什么,并且其值更大,因此必须在前面插入新节点。 In this case ppnode points to head , as before, and the *ppnode != NULL condition is true. 在这种情况下, ppnode像以前ppnode指向head ,并且*ppnode != NULL条件为true。 However the (*ppnode)->value >= newnode->value condition fails and so the loop never executes. 但是(*ppnode)->value >= newnode->value条件失败,因此循环永远不会执行。

Now, again, we are executing the equivalent of this code: 现在,我们再次执行以下代码:

newnode->next = head ? head->next : NULL;
head = newnode;

But this time head is not null, and so newnode->next = head->next , and, as before, newnode becomes the new head . 但是这次head不为空,因此newnode->next = head->next ,和以前一样, newnode成为新的head

All the other cases proceed from these two: except instead of head , the action plays out using the next pointer of the previous node, which is like the head of the rest of the list. 所有其他情况都从这两种情况出发:除了代替head ,该动作使用上next节点的next指针进行播放,就像该列表的其余部分的头一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM