Linked Lists Using Pointers

advertisement
clark
cs1713
syllabus
lecture notes
programming assignments
Dynamic (Heap) Memory
C allocates dynamic memory via the void *malloc(iBytes) and void
*calloc(iNum, iBytes). Unlike Java which uses garbage collection,
the programmer is responsible for freeing the memory using free(void *).
malloc returns a void * pointer. In this case, void doesn't mean no
returned value. void * means it is returning a pointer; however, the thing
it is pointing to is generic. (It can be almost anything.) You must tell it the
type of thing it is referencing. This is done using type casting. See the
example below.
Linked List Implementations in C
We can implement linked lists using dynamic memory and pointers.
Instead of us keeping track of the free memory (with a free list like was
done for the array implementation of a linked list), C will keep track. We
are still responsible for allocating and freeing the nodes.
Notice the struct Node and Node typedef. pNext points to another Node.
homework
set up
Typically, a C run-time environment is provided two large segments
of memory:
run-time memory stack - manages calls(return addresses,
parameters, saving registers) and automatic
variables
heap memory - manages dynamic memory
typedef struct Node
{
int iInfo;
struct Node *pNext;
} Node;
Node *pHead = NULL;
Node *pNew = NULL;
Node *pPrecedes = NULL;
Since we want malloc to return a pointer to a Node, we type cast its
results to a Node *.
// to allocate a new node
pNew = (Node *) malloc(sizeof(Node));
if (pNew == NULL)
exitError("Memory allocation error", "");
printLL - print the iInfo for every element in the list
void printLL(Node *pHead)
{
Node *p;
printf("iInfo Values\n");
for (p = pHead; p != NULL; p = p->pNext)
{
printf("%7d\n", p->iInfo;
}
}
Our iteration is similar to the array implementation.
searchLL (not returning ppPrecedes)
Show code for the function searchLL(Node *pHead, int iMatch) which
functionally returns a pointer to the node that matches iMatch. If a
matching node is not found, NULL is returned.
Node *searchLL(Node *pHead, int iMatch)
{
Node *p;
for (p = pHead; p != NULL; p = p->pNext)
{
if (iMatch == p->iInfo)
return p;
if (iMatch < p->iInfo)
return NULL;
}
return NULL;
The **pointer
It means the parameter is a pointer to a pointer. This is done
when we want to return a pointer through the parameter list.
When we needed to return a double value like in the
determineMinMax function, we declared the parameter to be a
pointer to a double.
If we want to return a pointer, we need a pointer to a pointer.
Exercise
Show code for the function searchLL(Node *pHead, int iMatch, Node
**ppPrecedes) which functionally returns a pointer to the node that
matches iMatch and also returns a pointer to the node that precedes that
node. If a matching node is not found, NULL is returned. If there isn't a
preceding node, return NULL in ppPrecedes.
Node Insertion
We have to allocate a node. Let's use Node *allocateNode(int
iNewInfo) which returns a pointer to a new node which has been
properly populated.
}
Recall how we return double values through the parameter ist:
void determineMinMax(StudentScores *pstudentScores
, double *pdMin, double *pdMax)
{
int i;
*pdMin = 200.0; // arbitrary high value
*pdMax = 0.0;
for (i = 0; i < pstudentScores->iScoreCount; i++)
{
if (pstudentScores->dScoreM[i] < *pdMin)
*pdMin = pstudentScores->dScoreM[i];
if (pstudentScores->dScoreM[i] > *pdMax)
*pdMax = pstudentScores->dScoreM[i];
}
}
We had to pass a pointer to the doubles. To return the value, we had
to dereference it.
Node *searchLL(Node *pHead, int iMatch, Node **ppPrecedes)
{
Node *p;
??
return NULL;
}
Node * allocateNode(int iNewInfo)
{
// to allocate a new node
pNew = malloc(sizeof(Node));
if (pNew == NULL)
exitError("Memory allocation error", "");
pNew->iInfo = iNewInfo;
pNew->pNext = NULL;
return pNew;
}
Insert a new Node after pPrecedes.
Exercise
Show code for the function insertLL(Node *ppHead, int iNewInfo) which
inserts the new info into the singly linked list using searchLL(). If it already
exists in the list, it returns the pointer to that node. Otherwise, It returns
the pointer for the new node.
// to insert the new node after pPrecedes, assuming it is set
// and using a singly linked list
if (pPrecedes == NULL)
{
// insert at head
??
}
else
{
// insert after a node
??
}
Node *insertLL(Node **ppHead, int iNewInfo)
{
Node *pNew;
Node *pPrecedes;
Node *pFind;
// see if it already exists
??
// Doesn't already exist.
??
return pNew;
}
Allocate a node and insert it
Download