如果我們的物件沒有隨機存取的功能,那該如何取得鏈結串列的內容?
目前來說,我們所擁有的類別屬性只有指標 head
( 和指標 tail
),
因此從這裡下手絕對是正確的方向!
class SLL {
private:
SLLNode *head;
public:
SLL();
void pushFront(int);
void printElement();
};
class DLL {
private:
DLLNode *head, *tail;
public:
DLL();
void pushFront(int);
void printElement();
};
剛剛說到我們的起點就是鏈結串列的頭部指標,那麼我們就從他開始吧!
cur
代表 current)cur
設為 this -> head
cur == NULL
,就跳出迴圈
cur != NULL
意味著這個指標指向的記憶體有存著一個節點,
因此我們可以讀取cur -> data
,
也可以藉著cur -> next
找到下一個節點
"NULL"
, " -> "
假設鏈結串列中包含:1, 5, 6, 7
輸出的結果應為1 -> 5 -> 6 -> 7 -> NULL
void SLL::printElement() {
SLLNode *cur = this -> head;
while (cur != NULL) {
std::cout << cur -> data << " -> ";
cur = cur -> next;
}
std::cout << "NULL\n";
}
void DLL::printElement() {
DLLNode *cur = this -> head;
while (cur != NULL) {
std::cout << cur -> data << " -> ";
cur = cur -> next;
}
std::cout << "NULL\n";
}
class SLL {
private:
SLLNode *head;
public:
SLL();
void pushFront(int);
void printElement(SLLNode *);
};
class DLL {
private:
DLLNode *head;
public:
DLL();
void pushFront(int);
void printElement(DLLNode *);
};
遞迴的想法相對迴圈解法也許相對抽象,但是學會遞迴後,在某些情況下可以少走彎路!
以這題來說,我們根據當前傳入的頭部節點參數來決定輸出的內容:
head != NULL
:因為此節點存在,所以輸出節點內容,並呼叫函式本身進行遞迴,參數傳入下一個節點head == NULL
:節點不存在,代表此函式進行到了尾聲,改為輸出字串 "NULL"
(作為遞迴的終點)void SLL::printElement(SLLNode *head) {
if (head == NULL) {
std::cout << "NULL\n";
return ;
}
std::cout << head -> data << " -> ";
printElement(head -> next);
}
void DLL::printElement(DLLNode *head) {
if (head == NULL) {
std::cout << "NULL\n";
return ;
}
std::cout << head -> data << " -> ";
printElement(head -> next);
}
從上述來看,不論是用遞迴解法,或是迴圈解法,「單向鏈結串列」、「雙向鏈結串列」的函式程式碼近乎相同。原因是我們都是從頭不斷呼叫節點的屬性 next
,並無使用到 tail
或屬性 prev
,因此程式碼的結構是完全相同的。
下一篇,我們就來試著刪除節點吧!