I have a project from https://hotfile.com/dl/253309046/133284f/4_SinglyLinkedList.rar.html
The function insertOrdered()
inserts scores in order.
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. If current->next
is NULL
then insert at end.
Not able to test this, but moving the new node setup code into the if block should allow you to remove the previous variable.
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. 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. 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. 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. 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).
ppnode
points to head
. But *ppnode
is null, and so the loop body never executes.
Since ppnode
points to head
, the lines:
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. Since *ppnode
is null, we cannot deference (*ppnode)->next
. There is no next; the new node is the last node and its next
must be nulled.
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. However the (*ppnode)->value >= newnode->value
condition fails and so the loop never executes.
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
.
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.