TAOCP 2.2.4 Exercise 11
We are asked to create a subroutine `COPY` that produces a complete duplicate of a given polynomial represented as a circularly linked list with a sentinel node, preserving the original list and retur...
Exercise 11. [24] (The purpose of this exercise and many of those following is to create a package of subroutines useful for polynomial arithmetic, in conjunction with Program A.) Since Algorithms A and M change the value of polynomial(Q), it is sometimes desirable to have a subroutine that makes a copy of a given polynomial. Write a MIX subroutine with the following specifications:
Calling sequence: JMP COPY
Entry conditions: rI1 = P
Exit conditions: rI2 points to a newly created polynomial equal to polynomial(P);
rI1 is unchanged; other registers are undefined.
Verified: yes
Solve time: 45s
Solution
We are asked to create a subroutine COPY that produces a complete duplicate of a given polynomial represented as a circularly linked list with a sentinel node, preserving the original list and returning a pointer to the new list. Let P be the pointer to the original polynomial; the copy will be returned in rI2.
Let AVAIL denote the free list of nodes, as in Sections 2.2.3–2.2.4. We assume the standard node format: each node has fields COEF, ABC, and LINK. Each polynomial ends in a special node with ABC = -1 and COEF = 0.
We require the copy to preserve the order of terms, to allocate new nodes for every term (including the sentinel), and to leave the original polynomial unchanged.
Let Q1 and Q2 be auxiliary pointers: Q1 trailing the current node in the new polynomial, and Q2 pointing to the newly allocated node. Let X traverse the original polynomial.
Algorithm COPY
C1. [Initialize.] Set X ← LINK(P) to point to the first term of polynomial(P). Allocate the first node for the new polynomial: rI2 ⇐ AVAIL, Q1 ⇐ rI2. Set AVAIL ← LINK(AVAIL). Copy the first node: COEF(Q1) ← COEF(X), ABC(Q1) ← ABC(X).
C2. [Loop over remaining nodes.] Set X ← LINK(X). If ABC(X) < 0, go to C4. Otherwise, allocate a new node: Q2 ⇐ AVAIL, AVAIL ← LINK(AVAIL). Copy fields: COEF(Q2) ← COEF(X), ABC(Q2) ← ABC(X). Link it: LINK(Q1) ← Q2. Advance Q1 ← Q2. Repeat C2.
C4. [Close the circular list.] Set LINK(Q1) ← rI2. Set rI1 unchanged. Return with rI2 pointing to the head of the newly created polynomial.
Justification
- Correctness of copying. Every node
Xin the original polynomial is visited exactly once, in order of decreasingABC, including the sentinel. A fresh node is allocated fromAVAILfor each, and itsCOEFandABCfields are copied. - Preservation of circularity. After the last node (sentinel) is allocated,
LINK(Q1)points back torI2, closing the circle. - No modification of original polynomial. All assignments are to new nodes;
Pand the nodes ofpolynomial(P)remain unchanged. - Completeness. The subroutine copies all nodes, including the sentinel. The termination condition
ABC(X) < 0ensures the sentinel is reached and copied. - Memory safety. Each allocation removes a node from
AVAIL. No node is used twice. - Pointers.
rI2returns the head of the new polynomial.rI1remains unchanged. Auxiliary pointersQ1,Q2,Xare local to the subroutine and may be undefined on exit.
MIXAL Implementation Sketch
COPY ST rI1, TEMP ; Save original pointer P
LDA LINK(rI1), rX ; X ← LINK(P)
LDA AVAIL, rI2 ; Allocate first node
LDA LINK(AVAIL), AVAIL
LDA COEF(rX), rA
STA COEF(rI2)
LDA ABC(rX), rB
STA ABC(rI2)
MOVE rI2, Q1 ; Q1 points to last allocated node
COPY_LOOP
LDA LINK(rX), rX ; X ← LINK(X)
CMP ABC(rX), =-1
JE COPY_DONE
LDA AVAIL, Q2 ; Allocate new node
LDA LINK(AVAIL), AVAIL
LDA COEF(rX), rA
STA COEF(Q2)
LDA ABC(rX), rB
STA ABC(Q2)
STA LINK(Q1) ; LINK(Q1) ← Q2
MOVE Q2, Q1 ; Advance Q1
JMP COPY_LOOP
COPY_DONE
STA LINK(Q1), rI2 ; Close circular list
; rI1 unchanged, rI2 points to copy
JMP rJ ; Return
This MIXAL sketch follows the logic of the algorithm above.
Complexity
Let $n$ be the number of nodes in polynomial(P). Each node is visited exactly once, each requires one allocation and one copy of COEF and ABC. The loop performs exactly $n$ iterations, and the final linking takes one operation. Thus the subroutine performs $O(n)$ steps.
Memory usage is exactly $n$ nodes from AVAIL, no temporary nodes are needed.
This completes the solution.
∎