鏈表的鏈接:
將第二條鏈表的所有內容鏈接到第一條鏈表之後, 其完整實現代碼與解析如下:
- //鏈表的鏈接
- template <typename Type>
- void MyList<Type>::concatenate(const MyList<Type> &list)
- {
- if (isEmpty())//如果自己的鏈表爲空
- {
- first = list.first;
- return ;
- }
- else if (list.isEmpty()) //如果第二條鏈表爲空
- {
- return ;
- }
- Node<Type> *endNode = first->next;
- //找到第一條鏈表的末尾節點
- while (endNode->next != NULL)
- {
- endNode = endNode->next;
- }
- //找到第二條鏈表的第一個真實元素
- Node<Type> *secondListNode = (list.first)->next;
- //注意: 需要將第二個鏈表中的元素值copy出來
- //不能直接將第二條鏈表的表頭鏈接到第一條鏈表的表尾
- //不然在析構函數回收內存時會發生錯誤(即:同一段內存釋放兩次)
- while (secondListNode != NULL)
- {
- Node<Type> *newNode = new Node<Type>(secondListNode->data);
- newNode->next = NULL;
- endNode->next = newNode;
- //兩條鏈表同時前進
- endNode = endNode->next;
- secondListNode = secondListNode->next;
- }
- }
鏈表的反轉:
基本思想:
遍歷一遍鏈表,利用一個輔助指針(此處爲指針r),存儲遍歷過程中當前指針指向的下一個元素,然後將當前節點元素的指針反轉後,利用已經存儲的指針往後面繼續遍歷。
- //鏈表的反轉
- template <typename Type>
- void MyList<Type>::invort()
- {
- if (!isEmpty())
- {
- //p指向正向鏈表的第一個真實節點
- //隨後, p也會沿正方向遍歷到鏈表末尾
- Node<Type> *p = first->next;
- //q會成爲倒向的第一個真實節點
- //首先將q設置爲NULL: 保證反向之後
- //最後一個元素的指針域指向NULL, 以表示鏈表結束
- Node<Type> *q = NULL;
- while (p != NULL)
- {
- Node<Type> *r = q; //暫存q當前指向的節點
- //q後退(沿着正向後退)
- q = p;
- //p前進(沿着正向前進), 保證p能夠始終領先q一個位置
- p = p -> next;
- //將指針逆向反轉
- //注意:一點要保證這條語句在p指針移動之後運行,
- //不然p就走不了了...(因爲q改變了指針的朝向)
- q -> next = r;
- }
- //此時q成爲反向鏈表的第一個真實元素
- //但是爲了維護像以前一樣的first指針指向一個無用的節點(以使前面的操作不會出錯)
- //於是我們需要將first的指針域指向q
- first->next = q;
- }
- }
鏈表打印:
重載MyList的<<運算符, 輸出鏈表所有元素, 以供測試之用
- //顯示鏈表中的所有數據(測試用)
- template <typename Type>
- ostream &operator<<(ostream &os, const MyList<Type> &list)
- {
- for (Node<Type> *searchNode = list.first -> next;
- searchNode != NULL;
- searchNode = searchNode -> next)
- {
- os << searchNode -> data;
- if (searchNode -> next != NULL) //尚未達到鏈表的結尾
- cout << " -> ";
- }
- return os;
- }
附-測試代碼:
- int main()
- {
- cout << "------------ 1 ------------" << endl;
- MyList<int> first;
- for (int i = 0; i < 5; ++i)
- {
- first.insert(i+1, i+1);
- }
- first.remove(5);
- MyList<int> second;
- for (int i = 0; i < 5; ++i)
- {
- second.insert(i+6, i+1);
- }
- second.insertFront(5);
- second.insert(88, 7);
- cout << "Before concatenate..." << endl;
- cout << "first: " << first << endl;
- cout << "second: " << second << endl;
- cout << "After concatenate..." << endl;
- first.concatenate(second);
- cout << "first: " << first << endl;
- cout << "second: " << second << endl;
- cout << "\n------------ 2 ------------" << endl;
- MyList<char> chList;
- for (char ch = '0'; ch <= '9'; ++ ch)
- {
- chList.insertFront(ch);
- }
- cout << "Before invort..." << endl;
- cout << chList << endl;
- cout << "After invort..." << endl;
- chList.invort();
- cout << chList << endl;
- cout << "After remove('5')..." << endl;
- chList.remove('5');
- cout << chList << endl;
- cout << "\n------------ 3 ------------" << endl;
- MyList<double> dList;
- dList.insert(1.1, 1);
- dList.insertFront(2.2);
- cout << dList << endl;
- return 0;
- }