Replace invalid characters with HTML entities
— with — ’ with ’ + with + × with x ç with ç “ with “ ” with ” ‘ with ‘ • with • – with - µ with µ † with † Fix C++ θ with θ Yen symbol instead of times Fix broken apos Bullet again E-circumflex
This commit is contained in:
parent
9e52de9586
commit
500e7f5654
353 changed files with 5091 additions and 5091 deletions
22
15-02.html
22
15-02.html
|
|
@ -45,7 +45,7 @@
|
|||
the head-of-list pointer is required. Returns the same pointer
|
||||
that was passed in. */
|
||||
|
||||
#include “llist.h”
|
||||
#include “llist.h”
|
||||
struct LinkNode *DeleteNodeAfter(struct LinkNode *NodeToDeleteAfter)
|
||||
{
|
||||
NodeToDeleteAfter->NextNode =
|
||||
|
|
@ -64,7 +64,7 @@ struct LinkNode *DeleteNodeAfter(struct LinkNode *NodeToDeleteAfter)
|
|||
struct LinkNode {
|
||||
struct LinkNode *NextNode;
|
||||
int Value;
|
||||
char Text[MAX_TEXT_LENGTH+1];
|
||||
char Text[MAX_TEXT_LENGTH+1];
|
||||
/* Any number of additional data fields may by present */
|
||||
};
|
||||
struct LinkNode *DeleteNodeAfter(struct LinkNode *);
|
||||
|
|
@ -81,7 +81,7 @@ struct LinkNode *InsertNodeSorted(struct LinkNode *,
|
|||
indicated node. List is headed by a head-of-list pointer; if the
|
||||
pointer to the node to delete after points to the head-of-list
|
||||
pointer, special handling is performed. */
|
||||
#include “llist.h”
|
||||
#include “llist.h”
|
||||
struct LinkNode *DeleteNodeAfter(struct LinkNode **HeadOfListPtr,
|
||||
struct LinkNode *NodeToDeleteAfter)
|
||||
{
|
||||
|
|
@ -97,18 +97,18 @@ struct LinkNode *DeleteNodeAfter(struct LinkNode **HeadOfListPtr,
|
|||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
<P>However, it is true that if you’re going to store a variety of types of structures in your linked lists, you should start each node with the <B>LinkNode</B> field. That way, the link pointer is in the same place in <I>every</I> structure, and the same linked list code can handle all of the structure types by casting them to the base link-node structure type. This is a less than elegant approach, but it works. C<SMALL>++</SMALL> can handle data mixing more cleanly than C, via derivation from a base link-node class.</P>
|
||||
<P>Note that Listings 15.1 and 15.3 have to specify the linked-list delete operation as “delete the <I>next</I> node,” rather than “delete this node,” because in order to relink it’s necessary to access the <B>NextNode</B> field of the node preceding the node to be deleted, and it’s impossible to backtrack in a singly linked list. For this reason, singly-linked list operations tend to work with the structure preceding the one of interest—and that makes the problem of having to special-case the head pointer all the more acute.</P>
|
||||
<P>Similar problems with the head pointer crop up when you’re inserting nodes, and in fact in all link manipulation code. It’s easy to end up working with either pointers to pointers or lots of special-case code, and while those approaches work, they’re inelegant and inefficient.</P>
|
||||
<P>However, it is true that if you’re going to store a variety of types of structures in your linked lists, you should start each node with the <B>LinkNode</B> field. That way, the link pointer is in the same place in <I>every</I> structure, and the same linked list code can handle all of the structure types by casting them to the base link-node structure type. This is a less than elegant approach, but it works. C<SMALL>++</SMALL> can handle data mixing more cleanly than C, via derivation from a base link-node class.</P>
|
||||
<P>Note that Listings 15.1 and 15.3 have to specify the linked-list delete operation as “delete the <I>next</I> node,” rather than “delete this node,” because in order to relink it’s necessary to access the <B>NextNode</B> field of the node preceding the node to be deleted, and it’s impossible to backtrack in a singly linked list. For this reason, singly-linked list operations tend to work with the structure preceding the one of interest—and that makes the problem of having to special-case the head pointer all the more acute.</P>
|
||||
<P>Similar problems with the head pointer crop up when you’re inserting nodes, and in fact in all link manipulation code. It’s easy to end up working with either pointers to pointers or lots of special-case code, and while those approaches work, they’re inelegant and inefficient.</P>
|
||||
<H3><A NAME="Heading4"></A><FONT COLOR="#000077">Dummies and Sentinels</FONT></H3>
|
||||
<P>A far better approach is to use a <I>dummy node</I> for the head of the list, as shown in Figure 15.2. I invented this one for myself the next time I encountered linked lists, while designing a seed fill function for MetaWindows, back during my tenure at Metagraphics Corp. But I could have learned it by spending five minutes with Sedgewick’s book.</P>
|
||||
<P>A far better approach is to use a <I>dummy node</I> for the head of the list, as shown in Figure 15.2. I invented this one for myself the next time I encountered linked lists, while designing a seed fill function for MetaWindows, back during my tenure at Metagraphics Corp. But I could have learned it by spending five minutes with Sedgewick’s book.</P>
|
||||
<P><A NAME="Fig2"><!-- </A><A HREF="javascript:displayWindow('images/15-02.jpg',407,102 )"> --><IMG SRC="images/15-02.jpg"><BR><!-- </A>
|
||||
<BR><A HREF="javascript:displayWindow('images/15-02.jpg',407,102)"> --><FONT COLOR="#000077"><B>Figure 15.2</B></FONT></A> <I>Using a dummy head and tail node with a linked list.</I>
|
||||
</P>
|
||||
<TABLE WIDTH="100%">
|
||||
<TD ALIGN="LEFT" VALIGN="TOP" WIDTH="5%"><IMG SRC="images/i.jpg"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="95%"><SMALL><I>The next-node pointer of the head node, which points to the first real node, is the only part of the head node that’s actually used. This way the same code works on the head node as on the rest of the list, so there are no special cases.</I></SMALL>
|
||||
<TD ALIGN="LEFT" VALIGN="TOP" WIDTH="5%"><IMG SRC="images/i.jpg"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="95%"><SMALL><I>The next-node pointer of the head node, which points to the first real node, is the only part of the head node that’s actually used. This way the same code works on the head node as on the rest of the list, so there are no special cases.</I></SMALL>
|
||||
</TABLE>
|
||||
<P>Likewise, there should be a separate node for the tail of the list, so that every node that contains real data is guaranteed to have a node on either side of it. In this scheme, an empty list contains two nodes, as shown in Figure 15.3. Although it is not necessary, the tail node may point to itself as its own next node, rather than contain a <B>NULL</B> pointer. This way, a deletion operation on an empty list will have no effect—quite unlike the same operation performed on a list terminated with a <B>NULL</B> pointer. The tail node of a list terminated like this can be detected because it will be the only node for which the next-node pointer equals the current-node pointer.</P>
|
||||
<P>Likewise, there should be a separate node for the tail of the list, so that every node that contains real data is guaranteed to have a node on either side of it. In this scheme, an empty list contains two nodes, as shown in Figure 15.3. Although it is not necessary, the tail node may point to itself as its own next node, rather than contain a <B>NULL</B> pointer. This way, a deletion operation on an empty list will have no effect—quite unlike the same operation performed on a list terminated with a <B>NULL</B> pointer. The tail node of a list terminated like this can be detected because it will be the only node for which the next-node pointer equals the current-node pointer.</P>
|
||||
<P>Figure 15.3 is a giant step in the right direction, but we can still make a few refinements. The inner loop of any code that scans through such a list has to perform a special test on each node to determine whether the tail has been reached. So, for example, code to find the first node containing a value field greater than or equal to a certain value has to perform two tests in the inner loop, as shown in Listing 15.4.</P>
|
||||
<P><B>LISTING 15.4 L15-4.C</B></P>
|
||||
<!-- CODE //-->
|
||||
|
|
@ -119,7 +119,7 @@ struct LinkNode *DeleteNodeAfter(struct LinkNode **HeadOfListPtr,
|
|||
NULL pointer if no such value was found. Assumes the list is
|
||||
terminated with a tail node pointing to itself as the next node. */
|
||||
#include <stdio.h>
|
||||
#include “llist.h”
|
||||
#include “llist.h”
|
||||
struct LinkNode *FindNodeBeforeValueNotLess(
|
||||
struct LinkNode *HeadOfListNode, int SearchValue)
|
||||
{
|
||||
|
|
@ -137,7 +137,7 @@ struct LinkNode *FindNodeBeforeValueNotLess(
|
|||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
<P>Suppose, however, that we make the tail node a <I>sentinel</I> by giving it a value that is guaranteed to terminate the search, as shown in Figure 15.4. The list in Figure 15.4 has a sentinel with a value field of 32,767; since we’re working with integers, that’s the highest possible search value, and is guaranteed to satisfy any search that comes down the pike. The success or failure of the search can then be determined outside the loop, if necessary, by checking for the tail node’s special pointer—but the inside of the loop is streamlined to just one test, as shown in Listing 15.5. Not all linked lists lend themselves to sentinels, but the performance benefits are considerable for those lend themselves to sentinels, but the performance benefits are considerable for those that do.</P>
|
||||
<P>Suppose, however, that we make the tail node a <I>sentinel</I> by giving it a value that is guaranteed to terminate the search, as shown in Figure 15.4. The list in Figure 15.4 has a sentinel with a value field of 32,767; since we’re working with integers, that’s the highest possible search value, and is guaranteed to satisfy any search that comes down the pike. The success or failure of the search can then be determined outside the loop, if necessary, by checking for the tail node’s special pointer—but the inside of the loop is streamlined to just one test, as shown in Listing 15.5. Not all linked lists lend themselves to sentinels, but the performance benefits are considerable for those lend themselves to sentinels, but the performance benefits are considerable for those that do.</P>
|
||||
<P><A NAME="Fig3"><!-- </A><A HREF="javascript:displayWindow('images/15-03.jpg',407,104 )"> --><IMG SRC="images/15-03.jpg"><BR><!-- </A>
|
||||
<BR><A HREF="javascript:displayWindow('images/15-03.jpg',407,104)"> --><FONT COLOR="#000077"><B>Figure 15.3</B></FONT></A> <I>Representing an empty list.</I>
|
||||
<P><BR></P>
|
||||
|
|
|
|||
Loading…
Reference in a new issue