題目: 寫C++程式碼說明如何複製一整個鏈結串列linked list到另一個變數。
答案: 因為 LinkedList本身的資料與指標是環環相扣的，因此無法單純的直接讓新的 Head 指向原本的 Head 的 Next 否則改動新的LinkedList，舊的也會跟著改動。  那既然要實現複製的話，就只能使用狠暴力的方式 : 那就是將每個節點走訪，並且將內容推向新的 LinkedList。 ( 可能有更方便的方式，只是我目前想到的是這個 )  以下是程式碼的部分  #include<string.h> #include<iostream> #include<stdlib.h> #include<sstream>  using namespace std; // 我就懶  // -*- c++ 11 -*-  // Node // 利用泛型實作 template <typename T> struct Node {     T num; // 資料     Node * next; // 下一個點  };  // 利用泛型實作LinkedList // 殘缺的LinkedList, 不過可以應付這題 template <typename T> class LinkedList {     public:         // 建構子         // 初始化資料         LinkedList() {             head = NULL; // 頭先設定為NULL              tail = NULL; // 尾也先設定為NULL              size = 0;         }          // 把資料放進去         void push(T data) {             // 如果裡面空空的             if(size==0) {                 head = new Node<T>; // 讓head變成新的Node                 head -> num = data; // 把資料放進去                 head -> next = NULL; // 指定head的next是null                 size++; // 讓size++                 tail = head;// 讓tail變成head                 return; // return 回去 避免進入下一行             }              // 要是不是空的話             tail -> next = new Node<T>; // 先讓tail的下一個變成新的Node             tail = tail -> next; // 把tail 移到下一層             tail -> num = data;// 把資料放進去             tail -> next = NULL; // tail的下一個指定為NULL             size++;// size增加             return;// return 回去 可加可不加         }          // 單純的複製LinkedList         // 這邊是產生一個新的LinkedList 而不是把原本的return回去         // 因為如果是把原本的return回去，會導致資料會被互相引響         LinkedList copy() {             LinkedList toReturn; // 準備回傳回去的資料             Node<T> * temp = head; // 指標 用來走訪整個LinkedList             while(temp!=NULL) {                 toReturn.push(temp->num); // 透過方法一直去push資料                 temp = temp -> next;             }             return toReturn; // return          }          // 透過 index 去取得資料         T getDataFromIndex(int k) {             Node<T> * temp = getFromIndex(k);             return temp -> num;         }          // 透過index 移除資料 並且將資料回傳          T removeFromIndex(int k) {             // 如果k的大小==0 就代表刪掉頭              if(k==0){                 if(head==NULL) return NULL;                 T n = head -> num;                 head = head -> next;                 size--;                 return n;             }             // 如果k小於0或者不小於size 就代表越界 因此直接return NULL              if(k>=size || k < 0) return NULL;                          // 暫時的節點 用來儲存即將被刪除的節點的上一個節點              Node<T> * temp = getFromIndex(k-1);             if(temp==NULL) return NULL; // 如果取不到 就代表越界 直接 return NULL              T n = temp -> next -> num; // N是即將被回傳的值 也就代表被刪除的節點的值              temp -> next = temp -> next -> next; // 讓next指向更下一層的節點              size--; // size記得要-1              return n; // return value         }          // 取得大小          int getSize() {             return size;         }                  // 排序          void sortList(){             head = mergeSort(head);         }                // 不公開的      private:         Node<T> * head;         Node<T> * tail;         int size;          // 這邊之所以放在private 是為了防止有人透過此方法破壞 LinkedList          // 此方法單純就是將第i個Node回傳          Node<T> * getFromIndex(int i) {             if(i==0) return head;             if(i>=size) return NULL;             Node<T> * temp = head;             for(int j = 0 ; j < i ; j++) {                 temp = temp -> next;             }              return temp;         }                  // 將節點排序          Node<T> * mergeSort(Node<T> * h){             // 如果 h 的大小只有 1 或者是根本沒東西 直接回傳 h              if(h==NULL||h -> next == NULL) return h;             // 找出中心點             // 利用快慢指標              Node<T> * slow = h;             Node<T> * fast = h -> next;             while(fast!=NULL&&fast-> next!=NULL){                 fast = fast -> next;                 slow = slow -> next;             }                          Node<T> * mid = slow -> next;             // 找到中心點後 分割開前半部以及後半部              slow -> next = NULL;             // 再度分割前半部 並且等待回傳的結果              Node<T> * left = mergeSort(h);             // 再度分割後半部 並且等待回傳的結果              Node<T> * right = mergeSort(mid);             // 開頭 Dummy head Node             Node<T> * ans = new Node<T>;             // 結尾先指向ans              Node<T> * last = ans;                          // 跑回圈 逐漸合併各個節點 並且回傳回去              while(left!=NULL||right!=NULL){                 T n1 = (left != NULL? left -> num : INT_MAX ); // 判斷 left 是不是 NULL 若不是 就指定 n1 為左邊的資料，否則設為 INT_MAX                  T n2 = (right != NULL? right -> num: INT_MAX ); // 判斷 right 是不是 NULL 若不是 就指定 n2 為右邊的資料，否則設為 INT_MAX                  // 若左邊小於右邊，就讓 last 後面接著左邊                  if(n1<n2){                     last -> next = left;                     left = left -> next;                 }                 // 否則就做相反的事情                  else{                     last -> next = right;                     right = right -> next;                  }                                  last = last -> next; // 記得 last 要移動             }                          // 記得不要把dummy head 回傳，而是將dummy head的下一個 ( 也就是真正的頭 ) 回傳              return ans -> next;         }      };  int main(){     LinkedList<int> k; // 新增一個 LinkedList<int> k      for(int i = 100 ; i >= 0 ; i--){         k.push(i); // 將 100 到 0 推進去 k 裡面      }     LinkedList<int> t = k.copy(); // 套copy這個function去複製整個LinkedList     t.sortList(); // 排序 為了證明這兩個LinkedList是不一樣的           // 印出k裡面的內容     // 印出資料 100 到 0      for(int i = 0 ; i < k.getSize() ; i++){         printf( %d\n ,k.getDataFromIndex(i));     }          printf( ==================\n ); // 分隔線           // 印出t的內容      // 印出資料 會印出 0 到 100      for(int i = 0 ; i <t.getSize() ;i++){         printf( %d\n ,t.getDataFromIndex(i));     } }  另外值得一提的是，我的排序是用 Merge Sort 排的，比起Bubble Sort使用了O( n ^ 2 )，Merge Sort只需要 O( nlog( n ) ) 。  至於怎麼實現的，請參考 https://www.geeksforgeeks.org/merge-sort-for-linked-list/ 想試試看自己寫的是否為正確，可以上 https://leetcode.com/problems/sort-list/ 測試
評論: Excellent!  排序的程式碼好像反而寫得比複製多...  小瑕疵： 互相引響