問題已知一個簡單鏈表,請複製鏈表並返回頭結點指標。解法1:遍曆演算法從頭開始遍曆原鏈表,依次複製鏈表各個節點。結點定義如下:
struct node { int data; struct node* next;};typedef struct node* pNode;
建立新結點newNode代碼:
pNode newNode(int data){ pNode nd = (pNode)malloc(sizeof(node)); nd->data = data; nd->next = NULL; return nd;}複製鏈表函數,注意第一個結點的特殊情況。此外保留有尾結點指標,便於新結點插入到鏈表中。
struct node* copyList(struct node* head) { struct node* current = head; struct node* newList = NULL; //新鏈表的頭指標 struct node* tail = NULL; // 新鏈表的尾部指標 while (current != NULL) { if (newList == NULL) { // 特殊情況,第一個新結點 newList = newNode(current->data); tail = newList; } else { tail->next = newNode(current->data); tail = tail->next; } current = current->next; } return(newList);}
如果要把第一個新結點這種特殊情況一起考慮,則可以使用指向指標的指標來實現。代碼如下:
void push(struct node** headRef, int data){ pNode nd = newNode(data); nd->next = *headRef; *headRef = nd;}struct node* copyListWithRef(struct node* head){ struct node* current = head; struct node* newList = NULL; struct node** lastPtr = &newList; while (current != NULL) { push(lastPtr, current->data); lastPtr = &((*lastPtr)->next); current = current->next; } return newList;}
解法2:遞迴演算法使用遞迴使得代碼量很少,邏輯也很清晰。主要思路是首先複製原鏈表頭結點,遞迴調用函數複製鏈表的剩下部分,並設定新鏈表頭結點的next域指向複製的剩下部分鏈表。代碼如下:
pNode copyListRecursive(pNode head){ if (head == NULL) return NULL; else { pNode newList = newNode(head->data); //複製原鏈表頭結點,新鏈表頭部指向它 newList->next = copyListRecursive(head->next); //新鏈表的next指向複製的剩下鏈表部分 return newList; }}