數據結構基礎(9) --單鏈表的設計與實現(2)之高級操作

鏈表的鏈接:

    將第二條鏈表的所有內容鏈接到第一條鏈表之後, 其完整實現代碼與解析如下:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. //鏈表的鏈接  
  2. template <typename Type>  
  3. void MyList<Type>::concatenate(const MyList<Type> &list)  
  4. {  
  5.     if (isEmpty())//如果自己的鏈表爲空  
  6.     {  
  7.         first = list.first;  
  8.         return ;  
  9.     }  
  10.     else if (list.isEmpty())    //如果第二條鏈表爲空  
  11.     {  
  12.         return ;  
  13.     }  
  14.   
  15.     Node<Type> *endNode = first->next;  
  16.     //找到第一條鏈表的末尾節點  
  17.     while (endNode->next != NULL)  
  18.     {  
  19.         endNode = endNode->next;  
  20.     }  
  21.   
  22.     //找到第二條鏈表的第一個真實元素  
  23.     Node<Type> *secondListNode = (list.first)->next;  
  24.     //注意: 需要將第二個鏈表中的元素值copy出來  
  25.     //不能直接將第二條鏈表的表頭鏈接到第一條鏈表的表尾  
  26.     //不然在析構函數回收內存時會發生錯誤(即:同一段內存釋放兩次)  
  27.     while (secondListNode != NULL)  
  28.     {  
  29.         Node<Type> *newNode = new Node<Type>(secondListNode->data);  
  30.         newNode->next = NULL;  
  31.         endNode->next = newNode;  
  32.   
  33.         //兩條鏈表同時前進  
  34.         endNode = endNode->next;  
  35.         secondListNode = secondListNode->next;  
  36.     }  
  37. }  

鏈表的反轉:

基本思想:

    遍歷一遍鏈表,利用一個輔助指針(此處爲指針r),存儲遍歷過程中當前指針指向的下一個元素,然後將當前節點元素的指針反轉後,利用已經存儲的指針往後面繼續遍歷。

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. //鏈表的反轉  
  2. template <typename Type>  
  3. void MyList<Type>::invort()  
  4. {  
  5.     if (!isEmpty())  
  6.     {  
  7.         //p指向正向鏈表的第一個真實節點  
  8.         //隨後, p也會沿正方向遍歷到鏈表末尾  
  9.         Node<Type> *p = first->next;  
  10.   
  11.         //q會成爲倒向的第一個真實節點  
  12.         //首先將q設置爲NULL: 保證反向之後  
  13.         //最後一個元素的指針域指向NULL, 以表示鏈表結束  
  14.         Node<Type> *q = NULL;  
  15.         while (p != NULL)  
  16.         {  
  17.             Node<Type> *r = q;  //暫存q當前指向的節點  
  18.             //q後退(沿着正向後退)  
  19.             q = p;  
  20.             //p前進(沿着正向前進), 保證p能夠始終領先q一個位置  
  21.             p = p -> next;  
  22.             //將指針逆向反轉  
  23.             //注意:一點要保證這條語句在p指針移動之後運行,  
  24.             //不然p就走不了了...(因爲q改變了指針的朝向)  
  25.             q -> next = r;  
  26.         }  
  27.   
  28.         //此時q成爲反向鏈表的第一個真實元素  
  29.         //但是爲了維護像以前一樣的first指針指向一個無用的節點(以使前面的操作不會出錯)  
  30.         //於是我們需要將first的指針域指向q  
  31.         first->next = q;  
  32.     }  
  33. }  

鏈表打印:

    重載MyList<<運算符輸出鏈表所有元素以供測試之用

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. //顯示鏈表中的所有數據(測試用)  
  2. template <typename Type>  
  3. ostream &operator<<(ostream &os, const MyList<Type> &list)  
  4. {  
  5.     for (Node<Type> *searchNode = list.first -> next;  
  6.             searchNode != NULL;  
  7.             searchNode = searchNode -> next)  
  8.     {  
  9.         os << searchNode -> data;  
  10.         if (searchNode -> next != NULL) //尚未達到鏈表的結尾  
  11.             cout << " -> ";  
  12.     }  
  13.   
  14.     return os;  
  15. }  

-測試代碼:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. int main()  
  2. {  
  3.     cout << "------------ 1 ------------" << endl;  
  4.     MyList<int> first;  
  5.     for (int i = 0; i < 5; ++i)  
  6.     {  
  7.         first.insert(i+1, i+1);  
  8.     }  
  9.     first.remove(5);  
  10.   
  11.     MyList<int> second;  
  12.     for (int i = 0; i < 5; ++i)  
  13.     {  
  14.         second.insert(i+6, i+1);  
  15.     }  
  16.     second.insertFront(5);  
  17.     second.insert(88, 7);  
  18.   
  19.     cout << "Before concatenate..." << endl;  
  20.     cout << "first: " << first << endl;  
  21.     cout << "second: " << second << endl;  
  22.   
  23.     cout << "After concatenate..." << endl;  
  24.     first.concatenate(second);  
  25.     cout << "first: " << first << endl;  
  26.     cout << "second: " << second << endl;  
  27.   
  28.   
  29.     cout << "\n------------ 2 ------------" << endl;  
  30.     MyList<char> chList;  
  31.     for (char ch = '0'; ch <= '9'; ++ ch)  
  32.     {  
  33.         chList.insertFront(ch);  
  34.     }  
  35.     cout << "Before invort..." << endl;  
  36.     cout << chList << endl;  
  37.   
  38.     cout << "After invort..." << endl;  
  39.     chList.invort();  
  40.     cout << chList << endl;  
  41.   
  42.     cout << "After remove('5')..." << endl;  
  43.     chList.remove('5');  
  44.     cout << chList << endl;  
  45.   
  46.     cout << "\n------------ 3 ------------" << endl;  
  47.     MyList<double> dList;  
  48.     dList.insert(1.1, 1);  
  49.     dList.insertFront(2.2);  
  50.     cout << dList << endl;  
  51.   
  52.     return 0;  
  53. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章