head
+--------+ +--------+ -->+--------+ -->+--------+
| |---->| info1 | / | info2 | / | info3 |
+--------+ | | / | | / | |
+--------+ / +--------+ / +--------+
| ref1 |- | ref2 |- | null |
+--------+ +--------+ +--------+
And you have a linked list element at "elem":
elem
+--------+ +--------+
| |---->| infoX | (information has been filled in)
+--------+ | |
+--------+
| ???? | (don't care, because we know there
+--------+ is no "next" element)
Memory:
+---------------+
head: | 8000 |-------------------------------+
+---------------+ |
| | |
....... |
....... |
+---------------+ |
8000 | info1 | Linked list element 1 <-----+
+---------------+
| ref1=10000 |-------------------------------------+
+---------------+ |
| | |
+---------------+ |
....... |
....... |
+---------------+ |
9000 | info3 | Linked list element 3 <----+ |
+---------------+ | |
| ref3=0 (null) | | |
+---------------+ | |
....... | |
....... | |
+---------------+ | |
10000 | info2 | Linked list element 2 | <-----+
+---------------+ |
| ref2=9000 |-----------------------------+
+---------------+
.......
.......
+---------------+
elem: | 20000 |-----------------------------+
+---------------+ |
....... |
....... |
+---------------+ |
20000 | infoX | New linked list element <---+
+---------------+
| refX=???? |
+---------------+
This process is illustrated by the following diagram:
Before insertion:
head
+--------+ +--------+ -->+--------+ -->+--------+
| |---->| info1 | / | info2 | / | info3 |
+--------+ | | / | | / | |
+--------+ / +--------+ / +--------+
| ref1 |- | ref2 |- | null |
+--------+ +--------+ +--------+
elem
+--------+ +--------+
| |---->| infoX |
+--------+ | |
+--------+
| ???? |
+--------+
After insertion:
head
+--------+ +--------+ -->+--------+ -->+--------+
| |---->| info1 | / | info2 | / | info3 |
+--------+ | | / | | / | |
+--------+ / +--------+ / +--------+
| ref1 |- | ref2 |- | ref3 |--+
+--------+ +--------+ +--------+ |
elem |
+--------+ +--------+ |
| |---->| infoX |<-----------------------------------+
+--------+ | |
+--------+
| null |
+--------+
Memory:
+---------------+
head: | 8000 |-------------------------------+
+---------------+ |
| | |
....... |
....... |
+---------------+ |
8000 | info1 | Linked list element 1 <-----+
+---------------+
| ref1=10000 |-------------------------------------+
+---------------+ |
| | |
+---------------+ |
....... |
....... |
+---------------+ |
9000 | info3 | Linked list element 3 <----+ |
+---------------+ | |
| ref3=20000 |-----------------------------|---+ |
+---------------+ | | |
....... | | |
....... | | |
+---------------+ | | |
10000 | info2 | Linked list element 2 | <-----+
+---------------+ | |
| ref2=9000 |-----------------------------+ |
+---------------+ |
....... |
....... |
+---------------+ |
elem: | 20000 |-----------------------------+ |
+---------------+ | |
....... | |
....... | |
+---------------+ | |
20000 | infoX | New linked list element <---+---+
+---------------+
| refX=null |
+---------------+
This address (20000) is also the address of the list element pointed to by "elem"
We must make a distinction between inserting into an empty list and a non-empty list....
elem.next = null; head = elem; (new head)
ptr = "Find the last element in the list at head"; ptr.next = elem; elem.next = null; (head remains unchanged)
static ListElement Insert(ListElement head, ListElement newelem)
{
ListElement ptr; // local variable to run down the list
if (head == null)
{ // Empty list, make "newelem" the first element
newelem.next = null; // Mark last element
return(newelem);
}
else
{ // find the last element
ptr = head;
while (ptr.next != null)
ptr = ptr.next;
ptr.next = newelem; // Link new to the last element
newelem.next = null; // Mark last element
return(head);
}
}
|
This function will return the head of the new list (with the "newelem" inserted.
But I will show you the code -- you can study it on your own.
The following program fragment shows how to use this function:
ptr = new ListElement(); // Create a new list element .... (initialize the list element) head = Insert(head, ptr); // Insert new element into list |
ListELement ptr; ptr = new ListElement(); // Create a new list element |
Recall that the new operator will:
|
|
Java: ListELement ptr; ptr = new ListElement(); ptr.value = 1234; |
In this case, the list is empty and we make "elem" the only element of the list.
In this case, the head of the new list is "elem"
In this case, we insert "elem" at the tail of a "shorter" list that is formed by leaving the first element off the original list.
The new list that is formed by inserting "elem" at the tail of the "shorter" list is linked AFTER the first element in the original list.
In this case, the head of the list is unchanged.
ListElement Insert(ListElement head, ListElement newelem)
{
ListElement help;
if head == null)
{ // Base case
newelem.next = null;
return(newelem); // New elem is the head
}
else
{ // Recursion
help = Insert(head.next, newelem);
// Insert elem in shorter list
head.next = help; // Link return list AFTER
// the first elem in orig. list
return(head); // head is unchanged
}
}
|
ptr = new ListElement(); // Make a new list element
// Effect:
// 1. reserve 8 bytes of memory
// to store a List oject
// 2. return the address of the
// location of the reserved memory
ptr.value = 1234; // Assignment some value
head = Insert(head, ptr); // Insert into list
|
**** ptr = new ListElement();
move.l #8, d0 ; 8 byte used to store a List object
jsr malloc ; allocate (8 bytes) of memory
move.l a0, ptr ; ptr = address of the allocated memory
**** ptr.value = 1234;
move.l #1234, (a0)
**** head = Insert(head, ptr);
move.l head, -(17) ; pass head in a0
move.l ptr, -(a7) ; pass ptr in a1
bsr InsertList ; call InsertList
adda.l #8, a7 ; pop parameters
move.l d0, head ; head = return value
|
static ListElement Insert(ListElement head, ListElement newelem)
{
ListElement help;
if head == null)
{ // Base case
newelem.next = null;
return(newelem); // New elem is the head
}
else
{ // Recursion
help = Insert(head.next, newelem);
// Insert elem in shorter list
head.next = help; // Link return list AFTER
// the first elem in orig. list
return(head); // head is unchanged
}
}
|
InsertList:
*-------------------------------- Prelude
move.l a6, -(a7)
move.l a7, a6
suba.l #4, a7
*--------------------------------
move.l 12(a6), d0 d0 = head
cmp.l #0, d0 Test: head == null
bne ElsePart Go to "ElsePart" if head != null
* ========================= Then part
move.l 8(a6), a0 a0 = newelem
move.l #0, 4(a0) newelem.next = null;
move.l 8(a6), d0 return(newelem) [in agreed location d0]
*-------------------------------- Postlude
move.l a6, a7
move.l (a7)+, a6
rts
*--------------------------------
ElsePart:
* ======================== help = InsertList(head.next, newelem);
move.l 12(a6), a0 (a0 = head)
move.l 4(a0), -(a7) (pass head.next)
move.l 8(a6), -(a7) (pass newelem)
bsr InsertList Recursion: InsertList(head.next, newelem);
adda.l #8, a7 Pop the 2 parameters from the stack
move.l d0, -4(a6) help = result of InsertList(head.next, newelem);
* ======================== head.next = help;
move.l 12(a6), a0 (a0 = head;)
move.l -4(a6), 4(a0) help is in -4(16), so this does: head.next = help;
* ======================== return(head);
move.l 12(a6), d0 return(head) [in agreed location d0]
*-------------------------------- Postlude
move.l a6, a7
move.l (a7)+, a6
rts
|
NOTE: when you read the assembler program: